xref: /netbsd-src/sbin/atactl/atactl.c (revision 7788a0781fe6ff2cce37368b4578a7ade0850cb1)
1 /*	$NetBSD: atactl.c,v 1.71 2013/08/06 19:13:13 soren Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Ken Hornstein.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * atactl(8) - a program to control ATA devices.
34  */
35 #include <sys/cdefs.h>
36 
37 #ifndef lint
38 __RCSID("$NetBSD: atactl.c,v 1.71 2013/08/06 19:13:13 soren Exp $");
39 #endif
40 
41 
42 #include <sys/param.h>
43 #include <sys/ioctl.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <pwd.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <util.h>
53 
54 #include <dev/ata/atareg.h>
55 #include <sys/ataio.h>
56 
57 struct ata_smart_error {
58 	struct {
59 		uint8_t device_control;
60 		uint8_t features;
61 		uint8_t sector_count;
62 		uint8_t sector_number;
63 		uint8_t cylinder_low;
64 		uint8_t cylinder_high;
65 		uint8_t device_head;
66 		uint8_t command;
67 		uint8_t timestamp[4];
68 	} command[5];
69 	struct {
70 		uint8_t reserved;
71 		uint8_t error;
72 		uint8_t sector_count;
73 		uint8_t sector_number;
74 		uint8_t cylinder_low;
75 		uint8_t cylinder_high;
76 		uint8_t device_head;
77 		uint8_t status;
78 		uint8_t extended_error[19];
79 		uint8_t state;
80 		uint8_t lifetime[2];
81 	} error_data;
82 } __packed;
83 
84 struct ata_smart_errorlog {
85 	uint8_t			data_structure_revision;
86 	uint8_t			mostrecenterror;
87 	struct ata_smart_error	log_entries[5];
88 	uint16_t		device_error_count;
89 	uint8_t			reserved[57];
90 	uint8_t			checksum;
91 } __packed;
92 
93 struct command {
94 	const char *cmd_name;
95 	const char *arg_names;
96 	void (*cmd_func)(int, char *[]);
97 };
98 
99 struct bitinfo {
100 	u_int bitmask;
101 	const char *string;
102 };
103 
104 __dead static void	usage(void);
105 static void	ata_command(struct atareq *);
106 static void	print_bitinfo(const char *, const char *, u_int,
107     const struct bitinfo *);
108 static void	print_bitinfo2(const char *, const char *, u_int, u_int,
109     const struct bitinfo *);
110 static void	print_smart_status(void *, void *);
111 static void	print_error_entry(int, const struct ata_smart_error *);
112 static void	print_selftest_entry(int, const struct ata_smart_selftest *);
113 
114 static void	print_error(const void *);
115 static void	print_selftest(const void *);
116 
117 static const struct ataparams *getataparams(void);
118 
119 static int	is_smart(void);
120 
121 static int	fd;				/* file descriptor for device */
122 static const	char *dvname;			/* device name */
123 static char	dvname_store[MAXPATHLEN];	/* for opendisk(3) */
124 static const	char *cmdname;			/* command user issued */
125 
126 static void	device_identify(int, char *[]);
127 static void	device_setidle(int, char *[]);
128 static void	device_idle(int, char *[]);
129 static void	device_apm(int, char *[]);
130 static void	device_checkpower(int, char *[]);
131 static void	device_smart(int, char *[]);
132 static void	device_security(int, char *[]);
133 
134 static void	device_smart_temp(const struct ata_smart_attr *, uint64_t);
135 
136 static const struct command device_commands[] = {
137 	{ "identify",	"",			device_identify },
138 	{ "setidle",	"idle-timer",		device_setidle },
139 	{ "apm",	"disable|set #",	device_apm },
140 	{ "setstandby",	"standby-timer",	device_setidle },
141 	{ "idle",	"",			device_idle },
142 	{ "standby",	"",			device_idle },
143 	{ "sleep",	"",			device_idle },
144 	{ "checkpower",	"",			device_checkpower },
145 	{ "smart",
146 		"enable|disable|status|offline #|error-log|selftest-log",
147 						device_smart },
148 	{ "security",
149 		"status|freeze|[setpass|unlock|disable|erase] [user|master]",
150 						device_security },
151 	{ NULL,		NULL,			NULL },
152 };
153 
154 static void	bus_reset(int, char *[]);
155 
156 static const struct command bus_commands[] = {
157 	{ "reset",	"",			bus_reset },
158 	{ NULL,		NULL,			NULL },
159 };
160 
161 /*
162  * Tables containing bitmasks used for error reporting and
163  * device identification.
164  */
165 
166 static const struct bitinfo ata_caps[] = {
167 	{ WDC_CAP_DMA, "DMA" },
168 	{ WDC_CAP_LBA, "LBA" },
169 	{ ATA_CAP_STBY, "ATA standby timer values" },
170 	{ WDC_CAP_IORDY, "IORDY operation" },
171 	{ WDC_CAP_IORDY_DSBL, "IORDY disabling" },
172 	{ 0, NULL },
173 };
174 
175 static const struct bitinfo ata_vers[] = {
176 	{ WDC_VER_ATA1,	"ATA-1" },
177 	{ WDC_VER_ATA2,	"ATA-2" },
178 	{ WDC_VER_ATA3,	"ATA-3" },
179 	{ WDC_VER_ATA4,	"ATA-4" },
180 	{ WDC_VER_ATA5,	"ATA-5" },
181 	{ WDC_VER_ATA6,	"ATA-6" },
182 	{ WDC_VER_ATA7,	"ATA-7" },
183 	{ WDC_VER_ATA8, "ATA-8" },
184 	{ 0, NULL },
185 };
186 
187 static const struct bitinfo ata_cmd_set1[] = {
188 	{ WDC_CMD1_NOP, "NOP command" },
189 	{ WDC_CMD1_RB, "READ BUFFER command" },
190 	{ WDC_CMD1_WB, "WRITE BUFFER command" },
191 	{ WDC_CMD1_HPA, "Host Protected Area feature set" },
192 	{ WDC_CMD1_DVRST, "DEVICE RESET command" },
193 	{ WDC_CMD1_SRV, "SERVICE interrupt" },
194 	{ WDC_CMD1_RLSE, "Release interrupt" },
195 	{ WDC_CMD1_AHEAD, "Look-ahead" },
196 	{ WDC_CMD1_CACHE, "Write cache" },
197 	{ WDC_CMD1_PKT, "PACKET command feature set" },
198 	{ WDC_CMD1_PM, "Power Management feature set" },
199 	{ WDC_CMD1_REMOV, "Removable Media feature set" },
200 	{ WDC_CMD1_SEC, "Security Mode feature set" },
201 	{ WDC_CMD1_SMART, "SMART feature set" },
202 	{ 0, NULL },
203 };
204 
205 static const struct bitinfo ata_cmd_set2[] = {
206 	{ ATA_CMD2_FCE, "FLUSH CACHE EXT command" },
207 	{ WDC_CMD2_FC, "FLUSH CACHE command" },
208 	{ WDC_CMD2_DCO, "Device Configuration Overlay feature set" },
209 	{ ATA_CMD2_LBA48, "48-bit Address feature set" },
210 	{ WDC_CMD2_AAM, "Automatic Acoustic Management feature set" },
211 	{ WDC_CMD2_SM, "SET MAX security extension" },
212 	{ WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" },
213 	{ WDC_CMD2_PUIS, "Power-Up In Standby feature set" },
214 	{ WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
215 	{ ATA_CMD2_APM, "Advanced Power Management feature set" },
216 	{ ATA_CMD2_CFA, "CFA feature set" },
217 	{ ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
218 	{ WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
219 	{ 0, NULL },
220 };
221 
222 static const struct bitinfo ata_cmd_ext[] = {
223 	{ ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" },
224 	{ ATA_CMDE_TL, "Time-limited Read/Write" },
225 	{ ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" },
226 	{ ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" },
227 	{ ATA_CMDE_WWN, "World Wide Name" },
228 	{ ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" },
229 	{ ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" },
230 	{ ATA_CMDE_GPL, "General Purpose Logging feature set" },
231 	{ ATA_CMDE_STREAM, "Streaming feature set" },
232 	{ ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" },
233 	{ ATA_CMDE_MS, "Media serial number" },
234 	{ ATA_CMDE_SST, "SMART self-test" },
235 	{ ATA_CMDE_SEL, "SMART error logging" },
236 	{ 0, NULL },
237 };
238 
239 static const struct bitinfo ata_sata_caps[] = {
240 	{ SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
241 	{ SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
242 	{ SATA_SIGNAL_GEN3, "6.0Gb/s signaling" },
243 	{ SATA_NATIVE_CMDQ, "Native Command Queuing" },
244 	{ SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
245 	{ SATA_PHY_EVNT_CNT, "PHY Event Counters" },
246 	{ 0, NULL },
247 };
248 
249 static const struct bitinfo ata_sata_feat[] = {
250 	{ SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" },
251 	{ SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" },
252 	{ SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" },
253 	{ SATA_IN_ORDER_DATA, "In-order Data Delivery" },
254 	{ SATA_SW_STTNGS_PRS, "Software Settings Preservation" },
255 	{ 0, NULL },
256 };
257 
258 static const struct {
259 	const int	id;
260 	const char	*name;
261 	void (*special)(const struct ata_smart_attr *, uint64_t);
262 } smart_attrs[] = {
263 	{   1,		"Raw read error rate", NULL },
264 	{   2,		"Throughput performance", NULL },
265 	{   3,		"Spin-up time", NULL },
266 	{   4,		"Start/stop count", NULL },
267 	{   5,		"Reallocated sector count", NULL },
268 	{   6,		"Read channel margin", NULL },
269 	{   7,		"Seek error rate", NULL },
270 	{   8,		"Seek time performance", NULL },
271 	{   9,		"Power-on hours count", NULL },
272 	{  10,		"Spin retry count", NULL },
273 	{  11,		"Calibration retry count", NULL },
274 	{  12,		"Device power cycle count", NULL },
275 	{  13,		"Soft read error rate", NULL },
276 	{ 184,          "End-to-end error", NULL },
277 	{ 187,          "Reported uncorrect", NULL },
278 	{ 189,          "High Fly Writes", NULL },
279 	{ 190,          "Airflow Temperature",		device_smart_temp },
280 	{ 191,		"G-sense error rate", NULL },
281 	{ 192,		"Power-off retract count", NULL },
282 	{ 193,		"Load cycle count", NULL },
283 	{ 194,		"Temperature",			device_smart_temp},
284 	{ 195,		"Hardware ECC Recovered", NULL },
285 	{ 196,		"Reallocated event count", NULL },
286 	{ 197,		"Current pending sector", NULL },
287 	{ 198,		"Offline uncorrectable", NULL },
288 	{ 199,		"Ultra DMA CRC error count", NULL },
289 	{ 200,		"Write error rate", NULL },
290 	{ 201,		"Soft read error rate", NULL },
291 	{ 202,		"Data address mark errors", NULL },
292 	{ 203,		"Run out cancel", NULL },
293 	{ 204,		"Soft ECC correction", NULL },
294 	{ 205,		"Thermal asperity check", NULL },
295 	{ 206,		"Flying height", NULL },
296 	{ 207,		"Spin high current", NULL },
297 	{ 208,		"Spin buzz", NULL },
298 	{ 209,		"Offline seek performance", NULL },
299 	{ 220,		"Disk shift", NULL },
300 	{ 221,		"G-Sense error rate", NULL },
301 	{ 222,		"Loaded hours", NULL },
302 	{ 223,		"Load/unload retry count", NULL },
303 	{ 224,		"Load friction", NULL },
304 	{ 225,		"Load/unload cycle count", NULL },
305 	{ 226,		"Load-in time", NULL },
306 	{ 227,		"Torque amplification count", NULL },
307 	{ 228,		"Power-off retract count", NULL },
308 	{ 230,		"GMR head amplitude", NULL },
309 	{ 231,		"Temperature",			device_smart_temp },
310 	{ 232,		"Available reserved space", NULL },
311 	{ 233,		"Media wearout indicator", NULL },
312 	{ 240,		"Head flying hours", NULL },
313 	{ 250,		"Read error retry rate", NULL },
314 	{   0,		"Unknown", NULL },
315 };
316 
317 static const struct bitinfo ata_sec_st[] = {
318 	{ WDC_SEC_SUPP,		"supported" },
319 	{ WDC_SEC_EN,		"enabled" },
320 	{ WDC_SEC_LOCKED,	"locked" },
321 	{ WDC_SEC_FROZEN,	"frozen" },
322 	{ WDC_SEC_EXP,		"expired" },
323 	{ WDC_SEC_ESE_SUPP,	"enhanced erase support" },
324 	{ WDC_SEC_LEV_MAX,	"maximum level" },
325 	{ 0,			NULL },
326 };
327 
328 int
329 main(int argc, char *argv[])
330 {
331 	int i;
332 	const struct command *commands = NULL;
333 
334 	/* Must have at least: device command */
335 	if (argc < 3)
336 		usage();
337 
338 	/* Skip program name, get and skip device name and command. */
339 	dvname = argv[1];
340 	cmdname = argv[2];
341 	argv += 3;
342 	argc -= 3;
343 
344 	/*
345 	 * Open the device
346 	 */
347 	fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
348 	if (fd == -1) {
349 		if (errno == ENOENT) {
350 			/*
351 			 * Device doesn't exist.  Probably trying to open
352 			 * a device which doesn't use disk semantics for
353 			 * device name.  Try again, specifying "cooked",
354 			 * which leaves off the "r" in front of the device's
355 			 * name.
356 			 */
357 			fd = opendisk(dvname, O_RDWR, dvname_store,
358 			    sizeof(dvname_store), 1);
359 			if (fd == -1)
360 				err(1, "%s", dvname);
361 		} else
362 			err(1, "%s", dvname);
363 	}
364 
365 	/*
366 	 * Point the dvname at the actual device name that opendisk() opened.
367 	 */
368 	dvname = dvname_store;
369 
370 	/* Look up and call the command. */
371 	for (i = 0; device_commands[i].cmd_name != NULL; i++) {
372 		if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
373 			commands = &device_commands[i];
374 			break;
375 		}
376 	}
377 	if (commands == NULL) {
378 		for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
379 			if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
380 				commands = &bus_commands[i];
381 				break;
382 			}
383 		}
384 	}
385 	if (commands == NULL)
386 		errx(1, "unknown command: %s", cmdname);
387 
388 	(*commands->cmd_func)(argc, argv);
389 	exit(0);
390 }
391 
392 static void
393 usage(void)
394 {
395 	int i;
396 
397 	fprintf(stderr, "usage: %s device command [arg [...]]\n",
398 	    getprogname());
399 
400 	fprintf(stderr, "   Available device commands:\n");
401 	for (i=0; device_commands[i].cmd_name != NULL; i++)
402 		fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
403 					    device_commands[i].arg_names);
404 
405 	fprintf(stderr, "   Available bus commands:\n");
406 	for (i=0; bus_commands[i].cmd_name != NULL; i++)
407 		fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
408 					    bus_commands[i].arg_names);
409 
410 	exit(1);
411 }
412 
413 /*
414  * Wrapper that calls ATAIOCCOMMAND and checks for errors
415  */
416 
417 static void
418 ata_command(struct atareq *req)
419 {
420 	int error;
421 
422 	error = ioctl(fd, ATAIOCCOMMAND, req);
423 
424 	if (error == -1)
425 		err(1, "ATAIOCCOMMAND failed");
426 
427 	switch (req->retsts) {
428 
429 	case ATACMD_OK:
430 		return;
431 	case ATACMD_TIMEOUT:
432 		fprintf(stderr, "ATA command timed out\n");
433 		exit(1);
434 	case ATACMD_DF:
435 		fprintf(stderr, "ATA device returned a Device Fault\n");
436 		exit(1);
437 	case ATACMD_ERROR:
438 		if (req->error & WDCE_ABRT)
439 			fprintf(stderr, "ATA device returned Aborted "
440 				"Command\n");
441 		else
442 			fprintf(stderr, "ATA device returned error register "
443 				"%0x\n", req->error);
444 		exit(1);
445 	default:
446 		fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
447 			"%d\n", req->retsts);
448 		exit(1);
449 	}
450 }
451 
452 /*
453  * Print out strings associated with particular bitmasks
454  */
455 
456 static void
457 print_bitinfo(const char *bf, const char *af, u_int bits,
458     const struct bitinfo *binfo)
459 {
460 
461 	for (; binfo->bitmask != 0; binfo++)
462 		if (bits & binfo->bitmask)
463 			printf("%s%s%s", bf, binfo->string, af);
464 }
465 
466 static void
467 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables,
468     const struct bitinfo *binfo)
469 {
470 
471 	for (; binfo->bitmask != 0; binfo++)
472 		if (bits & binfo->bitmask)
473 			printf("%s%s (%s)%s", bf, binfo->string,
474 			    (enables & binfo->bitmask) ? "enabled" : "disabled",
475 			    af);
476 }
477 
478 
479 /*
480  * Try to print SMART temperature field
481  */
482 
483 static void
484 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value)
485 {
486 	printf("%" PRIu8, attr->raw[0]);
487 	if (attr->raw[0] != raw_value)
488 		printf(" Lifetime min/max %" PRIu8 "/%" PRIu8,
489 		    attr->raw[2], attr->raw[4]);
490 }
491 
492 
493 /*
494  * Print out SMART attribute thresholds and values
495  */
496 
497 static void
498 print_smart_status(void *vbuf, void *tbuf)
499 {
500 	const struct ata_smart_attributes *value_buf = vbuf;
501 	const struct ata_smart_thresholds *threshold_buf = tbuf;
502 	const struct ata_smart_attr *attr;
503 	uint64_t raw_value;
504 	int flags;
505 	int i, j;
506 	int aid;
507 	uint8_t checksum;
508 
509 	for (i = checksum = 0; i < 512; i++)
510 		checksum += ((const uint8_t *) value_buf)[i];
511 	if (checksum != 0) {
512 		fprintf(stderr, "SMART attribute values checksum error\n");
513 		return;
514 	}
515 
516 	for (i = checksum = 0; i < 512; i++)
517 		checksum += ((const uint8_t *) threshold_buf)[i];
518 	if (checksum != 0) {
519 		fprintf(stderr, "SMART attribute thresholds checksum error\n");
520 		return;
521 	}
522 
523 	printf("id value thresh crit collect reliability description"
524 	    "                 raw\n");
525 	for (i = 0; i < 256; i++) {
526 		int thresh = 0;
527 
528 		attr = NULL;
529 
530 		for (j = 0; j < 30; j++) {
531 			if (value_buf->attributes[j].id == i)
532 				attr = &value_buf->attributes[j];
533 			if (threshold_buf->thresholds[j].id == i)
534 				thresh = threshold_buf->thresholds[j].value;
535 		}
536 
537 		if (thresh && attr == NULL)
538 			errx(1, "threshold but not attr %d", i);
539 		if (attr == NULL)
540 			continue;
541 
542 		if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
543 			continue;
544 
545 		for (aid = 0;
546 		     smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
547 		     aid++)
548 			;
549 
550 		flags = le16toh(attr->flags);
551 
552 		printf("%3d %3d  %3d     %-3s %-7s %stive    %-27s ",
553 		    i, attr->value, thresh,
554 		    flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
555 		    flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
556 		    attr->value > thresh ? "posi" : "nega",
557 		    smart_attrs[aid].name);
558 
559 		for (j = 0, raw_value = 0; j < 6; j++)
560 			raw_value += ((uint64_t)attr->raw[j]) << (8*j);
561 
562 		if (smart_attrs[aid].special)
563 			(*smart_attrs[aid].special)(attr, raw_value);
564 		else
565 			printf("%" PRIu64, raw_value);
566 		printf("\n");
567 	}
568 }
569 
570 static const struct {
571 	int number;
572 	const char *name;
573 } selftest_name[] = {
574 	{ 0, "Off-line" },
575 	{ 1, "Short off-line" },
576 	{ 2, "Extended off-line" },
577 	{ 127, "Abort off-line test" },
578 	{ 129, "Short captive" },
579 	{ 130, "Extended captive" },
580 	{ 256, "Unknown test" }, /* larger then uint8_t */
581 	{ 0, NULL }
582 };
583 
584 static const char *selftest_status[] = {
585 	"No error",
586 	"Aborted by the host",
587 	"Interrupted by the host by reset",
588 	"Fatal error or unknown test error",
589 	"Unknown test element failed",
590 	"Electrical test element failed",
591 	"The Servo (and/or seek) test element failed",
592 	"Read element of test failed",
593 	"Reserved",
594 	"Reserved",
595 	"Reserved",
596 	"Reserved",
597 	"Reserved",
598 	"Reserved",
599 	"Reserved",
600 	"Self-test in progress"
601 };
602 
603 static void
604 print_error_entry(int num, const struct ata_smart_error *le)
605 {
606 	int i;
607 
608 	printf("Log entry: %d\n", num);
609 
610 	for (i = 0; i < 5; i++)
611 		printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x "
612 		    "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
613 		    le->command[i].device_control,
614 		    le->command[i].features,
615 		    le->command[i].sector_count,
616 		    le->command[i].sector_number,
617 		    le->command[i].cylinder_low,
618 		    le->command[i].cylinder_high,
619 		    le->command[i].device_head,
620 		    le->command[i].command,
621 		    le->command[i].timestamp[3],
622 		    le->command[i].timestamp[2],
623 		    le->command[i].timestamp[1],
624 		    le->command[i].timestamp[0]);
625 	printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x "
626 	    "status=%02x state=%02x lifetime=%02x%02x\n",
627 	    le->error_data.error,
628 	    le->error_data.sector_count,
629 	    le->error_data.sector_number,
630 	    le->error_data.cylinder_low,
631 	    le->error_data.cylinder_high,
632 	    le->error_data.device_head,
633 	    le->error_data.status,
634 	    le->error_data.state,
635 	    le->error_data.lifetime[1],
636 	    le->error_data.lifetime[0]);
637 	printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
638 	    "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
639 	    le->error_data.extended_error[0],
640 	    le->error_data.extended_error[1],
641 	    le->error_data.extended_error[2],
642 	    le->error_data.extended_error[3],
643 	    le->error_data.extended_error[4],
644 	    le->error_data.extended_error[5],
645 	    le->error_data.extended_error[6],
646 	    le->error_data.extended_error[7],
647 	    le->error_data.extended_error[8],
648 	    le->error_data.extended_error[9],
649 	    le->error_data.extended_error[10],
650 	    le->error_data.extended_error[11],
651 	    le->error_data.extended_error[12],
652 	    le->error_data.extended_error[13],
653 	    le->error_data.extended_error[14],
654 	    le->error_data.extended_error[15],
655 	    le->error_data.extended_error[15],
656 	    le->error_data.extended_error[17],
657 	    le->error_data.extended_error[18]);
658 }
659 
660 static void
661 print_error(const void *buf)
662 {
663 	const struct ata_smart_errorlog *erlog = buf;
664 	uint8_t checksum;
665 	int i;
666 
667 	for (i = checksum = 0; i < 512; i++)
668 		checksum += ((const uint8_t *) buf)[i];
669 	if (checksum != 0) {
670 		fprintf(stderr, "SMART error log checksum error\n");
671 		return;
672 	}
673 
674 	if (erlog->data_structure_revision != 1) {
675 		fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
676 		    erlog->data_structure_revision);
677 		return;
678 	}
679 
680 	if (erlog->mostrecenterror == 0) {
681 		printf("No errors have been logged\n");
682 		return;
683 	}
684 
685 	if (erlog->mostrecenterror > 5) {
686 		fprintf(stderr, "Most recent error is too large\n");
687 		return;
688 	}
689 
690 	for (i = erlog->mostrecenterror; i < 5; i++)
691 		print_error_entry(i, &erlog->log_entries[i]);
692 	for (i = 0; i < erlog->mostrecenterror; i++)
693 		print_error_entry(i, &erlog->log_entries[i]);
694 	printf("device error count: %d\n", erlog->device_error_count);
695 }
696 
697 static void
698 print_selftest_entry(int num, const struct ata_smart_selftest *le)
699 {
700 	const unsigned char *p;
701 	size_t i;
702 
703 	/* check if all zero */
704 	for (p = (const void *)le, i = 0; i < sizeof(*le); i++)
705 		if (p[i] != 0)
706 			break;
707 	if (i == sizeof(*le))
708 		return;
709 
710 	printf("Log entry: %d\n", num);
711 
712 	/* Get test name */
713 	for (i = 0; selftest_name[i].name != NULL; i++)
714 		if (selftest_name[i].number == le->number)
715 			break;
716 
717 	if (selftest_name[i].name == NULL)
718 		printf("\tName: (%d)\n", le->number);
719 	else
720 		printf("\tName: %s\n", selftest_name[i].name);
721 	printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
722 	/* XXX This generally should not be set when a self-test is completed,
723 	   and at any rate is useless.  - mycroft */
724 	if (le->status >> 4 == 15)
725 		printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
726 	else if (le->status >> 4 != 0)
727 		printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
728 }
729 
730 static void
731 print_selftest(const void *buf)
732 {
733 	const struct ata_smart_selftestlog *stlog = buf;
734 	uint8_t checksum;
735 	int i;
736 
737 	for (i = checksum = 0; i < 512; i++)
738 		checksum += ((const uint8_t *) buf)[i];
739 	if (checksum != 0) {
740 		fprintf(stderr, "SMART selftest log checksum error\n");
741 		return;
742 	}
743 
744 	if (le16toh(stlog->data_structure_revision) != 1) {
745 		fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
746 		    le16toh(stlog->data_structure_revision));
747 		return;
748 	}
749 
750 	if (stlog->mostrecenttest == 0) {
751 		printf("No self-tests have been logged\n");
752 		return;
753 	}
754 
755 	if (stlog->mostrecenttest > 22) {
756 		fprintf(stderr, "Most recent test is too large\n");
757 		return;
758 	}
759 
760 	for (i = stlog->mostrecenttest; i < 22; i++)
761 		print_selftest_entry(i, &stlog->log_entries[i]);
762 	for (i = 0; i < stlog->mostrecenttest; i++)
763 		print_selftest_entry(i, &stlog->log_entries[i]);
764 }
765 
766 static const struct ataparams *
767 getataparams(void)
768 {
769 	struct atareq req;
770 	static union {
771 		unsigned char inbuf[DEV_BSIZE];
772 		struct ataparams inqbuf;
773 	} inbuf;
774 
775 	memset(&inbuf, 0, sizeof(inbuf));
776 	memset(&req, 0, sizeof(req));
777 
778 	req.flags = ATACMD_READ;
779 	req.command = WDCC_IDENTIFY;
780 	req.databuf = &inbuf;
781 	req.datalen = sizeof(inbuf);
782 	req.timeout = 1000;
783 
784 	ata_command(&req);
785 
786 	return (&inbuf.inqbuf);
787 }
788 
789 /*
790  * is_smart:
791  *
792  *	Detect whether device supports SMART and SMART is enabled.
793  */
794 
795 static int
796 is_smart(void)
797 {
798 	int retval = 0;
799 	const struct ataparams *inqbuf;
800 	const char *status;
801 
802 	inqbuf = getataparams();
803 
804 	if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
805 		if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
806 			fprintf(stderr, "SMART unsupported\n");
807 		} else {
808 			if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
809 			    inqbuf->atap_cmd_set2 == 0xffff ||
810 			    inqbuf->atap_cmd_set2 == 0x0000) {
811 				status = "status unknown";
812 				retval = 2;
813 			} else {
814 				if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
815 					status = "enabled";
816 					retval = 1;
817 				} else {
818 					status = "disabled";
819 					retval = 3;
820 				}
821 			}
822 			printf("SMART supported, SMART %s\n", status);
823 		}
824 	}
825 	return retval;
826 }
827 
828 /*
829  * extract_string: copy a block of bytes out of ataparams and make
830  * a proper string out of it, truncating trailing spaces and preserving
831  * strict typing. And also, not doing unaligned accesses.
832  */
833 static void
834 extract_string(char *buf, size_t bufmax,
835 	       const uint8_t *bytes, size_t numbytes,
836 	       int needswap)
837 {
838 	unsigned i;
839 	size_t j;
840 	unsigned char ch1, ch2;
841 
842 	for (i = 0, j = 0; i < numbytes; i += 2) {
843 		ch1 = bytes[i];
844 		ch2 = bytes[i+1];
845 		if (needswap && j < bufmax-1) {
846 			buf[j++] = ch2;
847 		}
848 		if (j < bufmax-1) {
849 			buf[j++] = ch1;
850 		}
851 		if (!needswap && j < bufmax-1) {
852 			buf[j++] = ch2;
853 		}
854 	}
855 	while (j > 0 && buf[j-1] == ' ') {
856 		j--;
857 	}
858 	buf[j] = '\0';
859 }
860 
861 static void
862 compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp,
863     uint64_t *sectorsp, uint32_t *secsizep)
864 {
865 	uint64_t capacity;
866 	uint64_t sectors;
867 	uint32_t secsize;
868 
869 	if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
870 	    inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
871 		sectors =
872 		    ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
873 		    ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
874 		    ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
875 		    ((uint64_t)inqbuf->atap_max_lba[0] <<  0);
876 	} else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
877 		sectors = (inqbuf->atap_capacity[1] << 16) |
878 		    inqbuf->atap_capacity[0];
879 	} else {
880 		sectors = inqbuf->atap_cylinders *
881 		    inqbuf->atap_heads * inqbuf->atap_sectors;
882 	}
883 
884 	secsize = 512;
885 
886 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
887 		if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
888 			secsize = 2 *		/* words to bytes */
889 			    (inqbuf->atap_lls_secsz[1] << 16 |
890 			    inqbuf->atap_lls_secsz[0] <<  0);
891 		}
892 	}
893 
894 	capacity = sectors * secsize;
895 
896 	if (capacityp)
897 		*capacityp = capacity;
898 	if (sectorsp)
899 		*sectorsp = sectors;
900 	if (secsizep)
901 		*secsizep = secsize;
902 }
903 
904 /*
905  * DEVICE COMMANDS
906  */
907 
908 /*
909  * device_identify:
910  *
911  *	Display the identity of the device
912  */
913 static void
914 device_identify(int argc, char *argv[])
915 {
916 	const struct ataparams *inqbuf;
917 	char model[sizeof(inqbuf->atap_model)+1];
918 	char revision[sizeof(inqbuf->atap_revision)+1];
919 	char serial[sizeof(inqbuf->atap_serial)+1];
920 	char hnum[12];
921 	uint64_t capacity;
922 	uint64_t sectors;
923 	uint32_t secsize;
924 	int lb_per_pb;
925 	int needswap = 0;
926 	int i;
927 	uint8_t checksum;
928 
929 	/* No arguments. */
930 	if (argc != 0)
931 		usage();
932 
933 	inqbuf = getataparams();
934 
935 	if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) ==
936 	    WDC_INTEGRITY_MAGIC) {
937 		for (i = checksum = 0; i < 512; i++)
938 			checksum += ((const uint8_t *)inqbuf)[i];
939 		if (checksum != 0)
940 			puts("IDENTIFY DEVICE data checksum invalid\n");
941 	}
942 
943 #if BYTE_ORDER == LITTLE_ENDIAN
944 	/*
945 	 * On little endian machines, we need to shuffle the string
946 	 * byte order.  However, we don't have to do this for NEC or
947 	 * Mitsumi ATAPI devices
948 	 */
949 
950 	if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
951 	      ((inqbuf->atap_model[0] == 'N' &&
952 		  inqbuf->atap_model[1] == 'E') ||
953 	       (inqbuf->atap_model[0] == 'F' &&
954 		  inqbuf->atap_model[1] == 'X')))) {
955 		needswap = 1;
956 	}
957 #endif
958 
959 	/*
960 	 * Copy the info strings out, stripping off blanks.
961 	 */
962 	extract_string(model, sizeof(model),
963 		inqbuf->atap_model, sizeof(inqbuf->atap_model),
964 		needswap);
965 	extract_string(revision, sizeof(revision),
966 		inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
967 		needswap);
968 	extract_string(serial, sizeof(serial),
969 		inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
970 		needswap);
971 
972 	printf("Model: %s, Rev: %s, Serial #: %s\n",
973 		model, revision, serial);
974 
975 	if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff &&
976 	    inqbuf->atap_cmd_ext & ATA_CMDE_WWN)
977 		printf("World Wide Name: %016" PRIX64 "\n",
978 		    ((uint64_t)inqbuf->atap_wwn[0] << 48) |
979 		    ((uint64_t)inqbuf->atap_wwn[1] << 32) |
980 		    ((uint64_t)inqbuf->atap_wwn[2] << 16) |
981 		    ((uint64_t)inqbuf->atap_wwn[3] <<  0));
982 
983 	printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
984 	       "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
985 	       "removable");
986 
987 	compute_capacity(inqbuf, &capacity, &sectors, &secsize);
988 
989 	humanize_number(hnum, sizeof(hnum), capacity, "bytes",
990 		HN_AUTOSCALE, HN_DIVISOR_1000);
991 
992 	printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n",
993 		       hnum, sectors, secsize);
994 
995 	printf("Cylinders: %d, heads: %d, sec/track: %d\n",
996 		inqbuf->atap_cylinders, inqbuf->atap_heads,
997 		inqbuf->atap_sectors);
998 
999 	lb_per_pb = 1;
1000 
1001 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
1002 		if (inqbuf->atap_secsz & ATA_SECSZ_LPS) {
1003 			lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK;
1004 			printf("Physical sector size: %d bytes\n",
1005 			    lb_per_pb * secsize);
1006 			if ((inqbuf->atap_logical_align &
1007 			    ATA_LA_VALID_MASK) == ATA_LA_VALID) {
1008 				printf("First physically aligned sector: %d\n",
1009 				    lb_per_pb - (inqbuf->atap_logical_align &
1010 					ATA_LA_MASK));
1011 			}
1012 		}
1013 	}
1014 
1015 	if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) ||
1016 	    (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) &&
1017 	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
1018 		printf("Command queue depth: %d\n",
1019 		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
1020 
1021 	printf("Device capabilities:\n");
1022 	print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
1023 
1024 	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
1025 		printf("Device supports following standards:\n");
1026 		print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
1027 		printf("\n");
1028 	}
1029 
1030 	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
1031 	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
1032 		printf("Command set support:\n");
1033 		if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
1034 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
1035 			    inqbuf->atap_cmd1_en, ata_cmd_set1);
1036 		else
1037 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
1038 			    ata_cmd_set1);
1039 		if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
1040 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
1041 			    inqbuf->atap_cmd2_en, ata_cmd_set2);
1042 		else
1043 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
1044 			    ata_cmd_set2);
1045 		if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
1046 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
1047 			    ata_cmd_ext);
1048 	}
1049 
1050 	if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
1051 		printf("Serial ATA capabilities:\n");
1052 		print_bitinfo("\t", "\n",
1053 		    inqbuf->atap_sata_caps, ata_sata_caps);
1054 
1055 	}
1056 
1057 	if (inqbuf->atap_sata_features_supp != 0 &&
1058 	    inqbuf->atap_sata_features_supp != 0xffff) {
1059 		printf("Serial ATA features:\n");
1060 		if (inqbuf->atap_sata_features_en != 0 &&
1061 		    inqbuf->atap_sata_features_en != 0xffff)
1062 			print_bitinfo2("\t", "\n",
1063 			    inqbuf->atap_sata_features_supp,
1064 			    inqbuf->atap_sata_features_en, ata_sata_feat);
1065 		else
1066 			print_bitinfo("\t", "\n",
1067 			    inqbuf->atap_sata_features_supp, ata_sata_feat);
1068 	}
1069 
1070 	if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&
1071 	    (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
1072 		printf("TRIM supported\n");
1073 
1074 	return;
1075 }
1076 
1077 /*
1078  * device idle:
1079  *
1080  * issue the IDLE IMMEDIATE command to the drive
1081  */
1082 static void
1083 device_idle(int argc, char *argv[])
1084 {
1085 	struct atareq req;
1086 
1087 	/* No arguments. */
1088 	if (argc != 0)
1089 		usage();
1090 
1091 	memset(&req, 0, sizeof(req));
1092 
1093 	if (strcmp(cmdname, "idle") == 0)
1094 		req.command = WDCC_IDLE_IMMED;
1095 	else if (strcmp(cmdname, "standby") == 0)
1096 		req.command = WDCC_STANDBY_IMMED;
1097 	else
1098 		req.command = WDCC_SLEEP;
1099 
1100 	req.timeout = 1000;
1101 
1102 	ata_command(&req);
1103 
1104 	return;
1105 }
1106 
1107 /*
1108  * device apm:
1109  *
1110  * enable/disable/control the APM feature of the drive
1111  */
1112 static void
1113 device_apm(int argc, char *argv[])
1114 {
1115 	struct atareq req;
1116 	long l;
1117 
1118 	memset(&req, 0, sizeof(req));
1119 	if (argc >= 1) {
1120 		req.command = SET_FEATURES;
1121 		req.timeout = 1000;
1122 
1123 		if (strcmp(argv[0], "disable") == 0)
1124 			req.features = WDSF_APM_DS;
1125 		else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
1126 		         (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
1127 
1128 			req.features = WDSF_APM_EN;
1129 			req.sec_count = l + 1;
1130 		} else
1131 			usage();
1132 	} else
1133 		usage();
1134 
1135 	ata_command(&req);
1136 }
1137 
1138 
1139 /*
1140  * Set the idle timer on the disk.  Set it for either idle mode or
1141  * standby mode, depending on how we were invoked.
1142  */
1143 
1144 static void
1145 device_setidle(int argc, char *argv[])
1146 {
1147 	unsigned long idle;
1148 	struct atareq req;
1149 	char *end;
1150 
1151 	/* Only one argument */
1152 	if (argc != 1)
1153 		usage();
1154 
1155 	idle = strtoul(argv[0], &end, 0);
1156 
1157 	if (*end != '\0') {
1158 		fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1159 		exit(1);
1160 	}
1161 
1162 	if (idle > 19800) {
1163 		fprintf(stderr, "Idle time has a maximum value of 5.5 "
1164 			"hours\n");
1165 		exit(1);
1166 	}
1167 
1168 	if (idle != 0 && idle < 5) {
1169 		fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1170 		exit(1);
1171 	}
1172 
1173 	memset(&req, 0, sizeof(req));
1174 
1175 	if (idle <= 240*5)
1176 		req.sec_count = idle / 5;
1177 	else
1178 		req.sec_count = idle / (30*60) + 240;
1179 
1180 	req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1181 	req.timeout = 1000;
1182 
1183 	ata_command(&req);
1184 
1185 	return;
1186 }
1187 
1188 /*
1189  * Query the device for the current power mode
1190  */
1191 
1192 static void
1193 device_checkpower(int argc, char *argv[])
1194 {
1195 	struct atareq req;
1196 
1197 	/* No arguments. */
1198 	if (argc != 0)
1199 		usage();
1200 
1201 	memset(&req, 0, sizeof(req));
1202 
1203 	req.command = WDCC_CHECK_PWR;
1204 	req.timeout = 1000;
1205 	req.flags = ATACMD_READREG;
1206 
1207 	ata_command(&req);
1208 
1209 	printf("Current power status: ");
1210 
1211 	switch (req.sec_count) {
1212 	case 0x00:
1213 		printf("Standby mode\n");
1214 		break;
1215 	case 0x80:
1216 		printf("Idle mode\n");
1217 		break;
1218 	case 0xff:
1219 		printf("Active mode\n");
1220 		break;
1221 	default:
1222 		printf("Unknown power code (%02x)\n", req.sec_count);
1223 	}
1224 
1225 	return;
1226 }
1227 
1228 /*
1229  * device_smart:
1230  *
1231  *	Display SMART status
1232  */
1233 static void
1234 device_smart(int argc, char *argv[])
1235 {
1236 	struct atareq req;
1237 	unsigned char inbuf[DEV_BSIZE];
1238 	unsigned char inbuf2[DEV_BSIZE];
1239 
1240 	if (argc < 1)
1241 		usage();
1242 
1243 	if (strcmp(argv[0], "enable") == 0) {
1244 		memset(&req, 0, sizeof(req));
1245 
1246 		req.features = WDSM_ENABLE_OPS;
1247 		req.command = WDCC_SMART;
1248 		req.cylinder = WDSMART_CYL;
1249 		req.timeout = 1000;
1250 
1251 		ata_command(&req);
1252 
1253 		is_smart();
1254 	} else if (strcmp(argv[0], "disable") == 0) {
1255 		memset(&req, 0, sizeof(req));
1256 
1257 		req.features = WDSM_DISABLE_OPS;
1258 		req.command = WDCC_SMART;
1259 		req.cylinder = WDSMART_CYL;
1260 		req.timeout = 1000;
1261 
1262 		ata_command(&req);
1263 
1264 		is_smart();
1265 	} else if (strcmp(argv[0], "status") == 0) {
1266 		int rv;
1267 
1268 		rv = is_smart();
1269 
1270 		if (!rv) {
1271 			fprintf(stderr, "SMART not supported\n");
1272 			return;
1273 		} else if (rv == 3)
1274 			return;
1275 
1276 		memset(&inbuf, 0, sizeof(inbuf));
1277 		memset(&req, 0, sizeof(req));
1278 
1279 		req.features = WDSM_STATUS;
1280 		req.command = WDCC_SMART;
1281 		req.cylinder = WDSMART_CYL;
1282 		req.timeout = 1000;
1283 
1284 		ata_command(&req);
1285 
1286 		if (req.cylinder != WDSMART_CYL) {
1287 			fprintf(stderr, "Threshold exceeds condition\n");
1288 		}
1289 
1290 		/* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1291 		 * features, the following ata_command()'s may error
1292 		 * and exit().
1293 		 */
1294 
1295 		memset(&inbuf, 0, sizeof(inbuf));
1296 		memset(&req, 0, sizeof(req));
1297 
1298 		req.flags = ATACMD_READ;
1299 		req.features = WDSM_RD_DATA;
1300 		req.command = WDCC_SMART;
1301 		req.databuf = (caddr_t) inbuf;
1302 		req.datalen = sizeof(inbuf);
1303 		req.cylinder = WDSMART_CYL;
1304 		req.timeout = 1000;
1305 
1306 		ata_command(&req);
1307 
1308 		memset(&inbuf2, 0, sizeof(inbuf2));
1309 		memset(&req, 0, sizeof(req));
1310 
1311 		req.flags = ATACMD_READ;
1312 		req.features = WDSM_RD_THRESHOLDS;
1313 		req.command = WDCC_SMART;
1314 		req.databuf = (caddr_t) inbuf2;
1315 		req.datalen = sizeof(inbuf2);
1316 		req.cylinder = WDSMART_CYL;
1317 		req.timeout = 1000;
1318 
1319 		ata_command(&req);
1320 
1321 		print_smart_status(inbuf, inbuf2);
1322 
1323 	} else if (strcmp(argv[0], "offline") == 0) {
1324 		if (argc != 2)
1325 			usage();
1326 		if (!is_smart()) {
1327 			fprintf(stderr, "SMART not supported\n");
1328 			return;
1329 		}
1330 
1331 		memset(&req, 0, sizeof(req));
1332 
1333 		req.features = WDSM_EXEC_OFFL_IMM;
1334 		req.command = WDCC_SMART;
1335 		req.cylinder = WDSMART_CYL;
1336 		req.sec_num = atol(argv[1]);
1337 		req.timeout = 10000;
1338 
1339 		ata_command(&req);
1340 	} else if (strcmp(argv[0], "error-log") == 0) {
1341 		if (!is_smart()) {
1342 			fprintf(stderr, "SMART not supported\n");
1343 			return;
1344 		}
1345 
1346 		memset(&inbuf, 0, sizeof(inbuf));
1347 		memset(&req, 0, sizeof(req));
1348 
1349 		req.flags = ATACMD_READ;
1350 		req.features = WDSM_RD_LOG;
1351 		req.sec_count = 1;
1352 		req.sec_num = 1;
1353 		req.command = WDCC_SMART;
1354 		req.databuf = (caddr_t) inbuf;
1355 		req.datalen = sizeof(inbuf);
1356 		req.cylinder = WDSMART_CYL;
1357 		req.timeout = 1000;
1358 
1359 		ata_command(&req);
1360 
1361 		print_error(inbuf);
1362 	} else if (strcmp(argv[0], "selftest-log") == 0) {
1363 		if (!is_smart()) {
1364 			fprintf(stderr, "SMART not supported\n");
1365 			return;
1366 		}
1367 
1368 		memset(&inbuf, 0, sizeof(inbuf));
1369 		memset(&req, 0, sizeof(req));
1370 
1371 		req.flags = ATACMD_READ;
1372 		req.features = WDSM_RD_LOG;
1373 		req.sec_count = 1;
1374 		req.sec_num = 6;
1375 		req.command = WDCC_SMART;
1376 		req.databuf = (caddr_t) inbuf;
1377 		req.datalen = sizeof(inbuf);
1378 		req.cylinder = WDSMART_CYL;
1379 		req.timeout = 1000;
1380 
1381 		ata_command(&req);
1382 
1383 		print_selftest(inbuf);
1384 
1385 	} else {
1386 		usage();
1387 	}
1388 	return;
1389 }
1390 
1391 static void
1392 device_security(int argc, char *argv[])
1393 {
1394 	struct atareq req;
1395 	const struct ataparams *inqbuf;
1396 	unsigned char data[DEV_BSIZE];
1397 	char *pass;
1398 
1399 	/* need subcommand */
1400 	if (argc < 1)
1401 		usage();
1402 
1403 	memset(&req, 0, sizeof(req));
1404 	if (strcmp(argv[0], "status") == 0) {
1405 		inqbuf = getataparams();
1406 		print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1407 	} else if (strcmp(argv[0], "freeze") == 0) {
1408 		req.command = WDCC_SECURITY_FREEZE;
1409 		req.timeout = 1000;
1410 		ata_command(&req);
1411 	} else if ((strcmp(argv[0], "setpass") == 0) ||
1412 	    (strcmp(argv[0], "unlock") == 0) ||
1413 	    (strcmp(argv[0], "disable") == 0) ||
1414 	    (strcmp(argv[0], "erase") == 0)) {
1415 		if (argc != 2)
1416 			usage();
1417 		if (strcmp(argv[1], "user") != 0) {
1418 			if (strcmp(argv[1], "master") == 0) {
1419 				fprintf(stderr,
1420 				    "Master passwords not supported\n");
1421 				exit(1);
1422 			} else {
1423 				usage();
1424 			}
1425 		}
1426 
1427 		pass = getpass("Password:");
1428 		if (strlen(pass) > 32) {
1429 			fprintf(stderr, "Password must be <=32 characters\n");
1430 			exit(1);
1431 		}
1432 
1433 		req.flags |= ATACMD_WRITE;
1434 		req.timeout = 1000;
1435 		req.databuf = data;
1436 		req.datalen = sizeof(data);
1437 		memset(data, 0, sizeof(data));
1438 		strlcpy((void *)&data[2], pass, 32 + 1);
1439 
1440 		if (strcmp(argv[0], "setpass") == 0) {
1441 			char orig[32 + 1];
1442 			strlcpy(orig, pass, 32 + 1);
1443 			pass = getpass("Confirm password:");
1444 			if (0 != strcmp(orig, pass)) {
1445 				fprintf(stderr, "Passwords do not match\n");
1446 				exit(1);
1447 			}
1448 			req.command = WDCC_SECURITY_SET_PASSWORD;
1449 		} else if (strcmp(argv[0], "unlock") == 0) {
1450 			req.command = WDCC_SECURITY_UNLOCK;
1451 		} else if (strcmp(argv[0], "disable") == 0) {
1452 			req.command = WDCC_SECURITY_DISABLE_PASSWORD;
1453 		} else if (strcmp(argv[0], "erase") == 0) {
1454 			struct atareq prepare;
1455 
1456 			inqbuf = getataparams();
1457 
1458 			/*
1459 			 * XXX Any way to lock the device to make sure
1460 			 * this really is the command preceding the
1461 			 * SECURITY ERASE UNIT command?  This would
1462 			 * probably have to be moved into the kernel to
1463 			 * do that.
1464 			 */
1465 			memset(&prepare, 0, sizeof(prepare));
1466 			prepare.command = WDCC_SECURITY_ERASE_PREPARE;
1467 			prepare.timeout = 1000;
1468 			ata_command(&prepare);
1469 
1470 			req.command = WDCC_SECURITY_ERASE_UNIT;
1471 
1472 			/*
1473 			 * Enable enhanced erase if it's supported.
1474 			 *
1475 			 * XXX should be a command-line option
1476 			 */
1477 			if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {
1478 				data[0] |= 0x2;
1479 				req.timeout = (inqbuf->atap_eseu_time & 0xff)
1480 				    * 2 * 60 * 1000;
1481 			} else {
1482 				req.timeout = (inqbuf->atap_seu_time & 0xff)
1483 				    * 2 * 60 * 1000;
1484 			}
1485 
1486 			/*
1487 			 * If the estimated time was 0xff (* 2 * 60 *
1488 			 * 1000 = 30600000), that means `>508 minutes'.
1489 			 * Estimate that we can handle 16 MB/sec, a
1490 			 * rate I just pulled out of my arse.
1491 			 */
1492 			if (req.timeout == 30600000) {
1493 				uint64_t bytes, timeout;
1494 				compute_capacity(inqbuf, &bytes, NULL, NULL);
1495 				timeout = (bytes / (16 * 1024 * 1024)) * 1000;
1496 				if (timeout > (uint64_t)INT_MAX)
1497 					req.timeout = INT_MAX;
1498 				else
1499 					req.timeout = timeout;
1500 			}
1501 
1502 			printf("Erasing may take up to %dh %dm %ds...\n",
1503 			    (req.timeout / 1000 / 60) / 60,
1504 			    (req.timeout / 1000 / 60) % 60,
1505 			    req.timeout % 60);
1506 		} else {
1507 			abort();
1508 		}
1509 
1510 		ata_command(&req);
1511 	} else {
1512 		usage();
1513 	}
1514 }
1515 
1516 /*
1517  * bus_reset:
1518  *	Reset an ATA bus (will reset all devices on the bus)
1519  */
1520 static void
1521 bus_reset(int argc, char *argv[])
1522 {
1523 	int error;
1524 
1525 	/* no args */
1526 	if (argc != 0)
1527 		usage();
1528 
1529 	error = ioctl(fd, ATABUSIORESET, NULL);
1530 
1531 	if (error == -1)
1532 		err(1, "ATABUSIORESET failed");
1533 }
1534