xref: /netbsd-src/sbin/atactl/atactl.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: atactl.c,v 1.73 2013/12/09 09:35:16 wiz 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.73 2013/12/09 09:35:16 wiz 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 than 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_CFA_MAGIC &&
951 	      (inqbuf->atap_config & WDC_CFG_ATAPI) &&
952 	      ((inqbuf->atap_model[0] == 'N' &&
953 		  inqbuf->atap_model[1] == 'E') ||
954 	       (inqbuf->atap_model[0] == 'F' &&
955 		  inqbuf->atap_model[1] == 'X')))) {
956 		needswap = 1;
957 	}
958 #endif
959 
960 	/*
961 	 * Copy the info strings out, stripping off blanks.
962 	 */
963 	extract_string(model, sizeof(model),
964 		inqbuf->atap_model, sizeof(inqbuf->atap_model),
965 		needswap);
966 	extract_string(revision, sizeof(revision),
967 		inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
968 		needswap);
969 	extract_string(serial, sizeof(serial),
970 		inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
971 		needswap);
972 
973 	printf("Model: %s, Rev: %s, Serial #: %s\n",
974 		model, revision, serial);
975 
976 	if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff &&
977 	    inqbuf->atap_cmd_ext & ATA_CMDE_WWN)
978 		printf("World Wide Name: %016" PRIX64 "\n",
979 		    ((uint64_t)inqbuf->atap_wwn[0] << 48) |
980 		    ((uint64_t)inqbuf->atap_wwn[1] << 32) |
981 		    ((uint64_t)inqbuf->atap_wwn[2] << 16) |
982 		    ((uint64_t)inqbuf->atap_wwn[3] <<  0));
983 
984 	printf("Device type: %s",
985 		inqbuf->atap_config == WDC_CFG_CFA_MAGIC ? "CF-ATA" :
986 		 (inqbuf->atap_config & WDC_CFG_ATAPI ? "ATAPI" : "ATA"));
987 	if (inqbuf->atap_config != WDC_CFG_CFA_MAGIC)
988 		printf(", %s",
989 		 inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");
990 	printf("\n");
991 
992 	compute_capacity(inqbuf, &capacity, &sectors, &secsize);
993 
994 	humanize_number(hnum, sizeof(hnum), capacity, "bytes",
995 		HN_AUTOSCALE, HN_DIVISOR_1000);
996 
997 	printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n",
998 		       hnum, sectors, secsize);
999 
1000 	printf("Cylinders: %d, heads: %d, sec/track: %d\n",
1001 		inqbuf->atap_cylinders, inqbuf->atap_heads,
1002 		inqbuf->atap_sectors);
1003 
1004 	lb_per_pb = 1;
1005 
1006 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
1007 		if (inqbuf->atap_secsz & ATA_SECSZ_LPS) {
1008 			lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK;
1009 			printf("Physical sector size: %d bytes\n",
1010 			    lb_per_pb * secsize);
1011 			if ((inqbuf->atap_logical_align &
1012 			    ATA_LA_VALID_MASK) == ATA_LA_VALID) {
1013 				printf("First physically aligned sector: %d\n",
1014 				    lb_per_pb - (inqbuf->atap_logical_align &
1015 					ATA_LA_MASK));
1016 			}
1017 		}
1018 	}
1019 
1020 	if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) ||
1021 	    (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) &&
1022 	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
1023 		printf("Command queue depth: %d\n",
1024 		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
1025 
1026 	printf("Device capabilities:\n");
1027 	print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
1028 
1029 	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
1030 		printf("Device supports following standards:\n");
1031 		print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
1032 		printf("\n");
1033 	}
1034 
1035 	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
1036 	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
1037 		printf("Command set support:\n");
1038 		if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
1039 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
1040 			    inqbuf->atap_cmd1_en, ata_cmd_set1);
1041 		else
1042 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
1043 			    ata_cmd_set1);
1044 		if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
1045 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
1046 			    inqbuf->atap_cmd2_en, ata_cmd_set2);
1047 		else
1048 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
1049 			    ata_cmd_set2);
1050 		if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
1051 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
1052 			    ata_cmd_ext);
1053 	}
1054 
1055 	if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
1056 		printf("Serial ATA capabilities:\n");
1057 		print_bitinfo("\t", "\n",
1058 		    inqbuf->atap_sata_caps, ata_sata_caps);
1059 
1060 	}
1061 
1062 	if (inqbuf->atap_sata_features_supp != 0 &&
1063 	    inqbuf->atap_sata_features_supp != 0xffff) {
1064 		printf("Serial ATA features:\n");
1065 		if (inqbuf->atap_sata_features_en != 0 &&
1066 		    inqbuf->atap_sata_features_en != 0xffff)
1067 			print_bitinfo2("\t", "\n",
1068 			    inqbuf->atap_sata_features_supp,
1069 			    inqbuf->atap_sata_features_en, ata_sata_feat);
1070 		else
1071 			print_bitinfo("\t", "\n",
1072 			    inqbuf->atap_sata_features_supp, ata_sata_feat);
1073 	}
1074 
1075 	if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&
1076 	    (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
1077 		printf("TRIM supported\n");
1078 
1079 	return;
1080 }
1081 
1082 /*
1083  * device idle:
1084  *
1085  * issue the IDLE IMMEDIATE command to the drive
1086  */
1087 static void
1088 device_idle(int argc, char *argv[])
1089 {
1090 	struct atareq req;
1091 
1092 	/* No arguments. */
1093 	if (argc != 0)
1094 		usage();
1095 
1096 	memset(&req, 0, sizeof(req));
1097 
1098 	if (strcmp(cmdname, "idle") == 0)
1099 		req.command = WDCC_IDLE_IMMED;
1100 	else if (strcmp(cmdname, "standby") == 0)
1101 		req.command = WDCC_STANDBY_IMMED;
1102 	else
1103 		req.command = WDCC_SLEEP;
1104 
1105 	req.timeout = 1000;
1106 
1107 	ata_command(&req);
1108 
1109 	return;
1110 }
1111 
1112 /*
1113  * device apm:
1114  *
1115  * enable/disable/control the APM feature of the drive
1116  */
1117 static void
1118 device_apm(int argc, char *argv[])
1119 {
1120 	struct atareq req;
1121 	long l;
1122 
1123 	memset(&req, 0, sizeof(req));
1124 	if (argc >= 1) {
1125 		req.command = SET_FEATURES;
1126 		req.timeout = 1000;
1127 
1128 		if (strcmp(argv[0], "disable") == 0)
1129 			req.features = WDSF_APM_DS;
1130 		else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
1131 		         (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
1132 
1133 			req.features = WDSF_APM_EN;
1134 			req.sec_count = l + 1;
1135 		} else
1136 			usage();
1137 	} else
1138 		usage();
1139 
1140 	ata_command(&req);
1141 }
1142 
1143 
1144 /*
1145  * Set the idle timer on the disk.  Set it for either idle mode or
1146  * standby mode, depending on how we were invoked.
1147  */
1148 
1149 static void
1150 device_setidle(int argc, char *argv[])
1151 {
1152 	unsigned long idle;
1153 	struct atareq req;
1154 	char *end;
1155 
1156 	/* Only one argument */
1157 	if (argc != 1)
1158 		usage();
1159 
1160 	idle = strtoul(argv[0], &end, 0);
1161 
1162 	if (*end != '\0') {
1163 		fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1164 		exit(1);
1165 	}
1166 
1167 	if (idle > 19800) {
1168 		fprintf(stderr, "Idle time has a maximum value of 5.5 "
1169 			"hours\n");
1170 		exit(1);
1171 	}
1172 
1173 	if (idle != 0 && idle < 5) {
1174 		fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1175 		exit(1);
1176 	}
1177 
1178 	memset(&req, 0, sizeof(req));
1179 
1180 	if (idle <= 240*5)
1181 		req.sec_count = idle / 5;
1182 	else
1183 		req.sec_count = idle / (30*60) + 240;
1184 
1185 	req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1186 	req.timeout = 1000;
1187 
1188 	ata_command(&req);
1189 
1190 	return;
1191 }
1192 
1193 /*
1194  * Query the device for the current power mode
1195  */
1196 
1197 static void
1198 device_checkpower(int argc, char *argv[])
1199 {
1200 	struct atareq req;
1201 
1202 	/* No arguments. */
1203 	if (argc != 0)
1204 		usage();
1205 
1206 	memset(&req, 0, sizeof(req));
1207 
1208 	req.command = WDCC_CHECK_PWR;
1209 	req.timeout = 1000;
1210 	req.flags = ATACMD_READREG;
1211 
1212 	ata_command(&req);
1213 
1214 	printf("Current power status: ");
1215 
1216 	switch (req.sec_count) {
1217 	case 0x00:
1218 		printf("Standby mode\n");
1219 		break;
1220 	case 0x80:
1221 		printf("Idle mode\n");
1222 		break;
1223 	case 0xff:
1224 		printf("Active mode\n");
1225 		break;
1226 	default:
1227 		printf("Unknown power code (%02x)\n", req.sec_count);
1228 	}
1229 
1230 	return;
1231 }
1232 
1233 /*
1234  * device_smart:
1235  *
1236  *	Display SMART status
1237  */
1238 static void
1239 device_smart(int argc, char *argv[])
1240 {
1241 	struct atareq req;
1242 	unsigned char inbuf[DEV_BSIZE];
1243 	unsigned char inbuf2[DEV_BSIZE];
1244 
1245 	if (argc < 1)
1246 		usage();
1247 
1248 	if (strcmp(argv[0], "enable") == 0) {
1249 		memset(&req, 0, sizeof(req));
1250 
1251 		req.features = WDSM_ENABLE_OPS;
1252 		req.command = WDCC_SMART;
1253 		req.cylinder = WDSMART_CYL;
1254 		req.timeout = 1000;
1255 
1256 		ata_command(&req);
1257 
1258 		is_smart();
1259 	} else if (strcmp(argv[0], "disable") == 0) {
1260 		memset(&req, 0, sizeof(req));
1261 
1262 		req.features = WDSM_DISABLE_OPS;
1263 		req.command = WDCC_SMART;
1264 		req.cylinder = WDSMART_CYL;
1265 		req.timeout = 1000;
1266 
1267 		ata_command(&req);
1268 
1269 		is_smart();
1270 	} else if (strcmp(argv[0], "status") == 0) {
1271 		int rv;
1272 
1273 		rv = is_smart();
1274 
1275 		if (!rv) {
1276 			fprintf(stderr, "SMART not supported\n");
1277 			return;
1278 		} else if (rv == 3)
1279 			return;
1280 
1281 		memset(&inbuf, 0, sizeof(inbuf));
1282 		memset(&req, 0, sizeof(req));
1283 
1284 		req.features = WDSM_STATUS;
1285 		req.command = WDCC_SMART;
1286 		req.cylinder = WDSMART_CYL;
1287 		req.timeout = 1000;
1288 
1289 		ata_command(&req);
1290 
1291 		if (req.cylinder != WDSMART_CYL) {
1292 			fprintf(stderr, "Threshold exceeds condition\n");
1293 		}
1294 
1295 		/* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1296 		 * features, the following ata_command()'s may error
1297 		 * and exit().
1298 		 */
1299 
1300 		memset(&inbuf, 0, sizeof(inbuf));
1301 		memset(&req, 0, sizeof(req));
1302 
1303 		req.flags = ATACMD_READ;
1304 		req.features = WDSM_RD_DATA;
1305 		req.command = WDCC_SMART;
1306 		req.databuf = (caddr_t) inbuf;
1307 		req.datalen = sizeof(inbuf);
1308 		req.cylinder = WDSMART_CYL;
1309 		req.timeout = 1000;
1310 
1311 		ata_command(&req);
1312 
1313 		memset(&inbuf2, 0, sizeof(inbuf2));
1314 		memset(&req, 0, sizeof(req));
1315 
1316 		req.flags = ATACMD_READ;
1317 		req.features = WDSM_RD_THRESHOLDS;
1318 		req.command = WDCC_SMART;
1319 		req.databuf = (caddr_t) inbuf2;
1320 		req.datalen = sizeof(inbuf2);
1321 		req.cylinder = WDSMART_CYL;
1322 		req.timeout = 1000;
1323 
1324 		ata_command(&req);
1325 
1326 		print_smart_status(inbuf, inbuf2);
1327 
1328 	} else if (strcmp(argv[0], "offline") == 0) {
1329 		if (argc != 2)
1330 			usage();
1331 		if (!is_smart()) {
1332 			fprintf(stderr, "SMART not supported\n");
1333 			return;
1334 		}
1335 
1336 		memset(&req, 0, sizeof(req));
1337 
1338 		req.features = WDSM_EXEC_OFFL_IMM;
1339 		req.command = WDCC_SMART;
1340 		req.cylinder = WDSMART_CYL;
1341 		req.sec_num = atol(argv[1]);
1342 		req.timeout = 10000;
1343 
1344 		ata_command(&req);
1345 	} else if (strcmp(argv[0], "error-log") == 0) {
1346 		if (!is_smart()) {
1347 			fprintf(stderr, "SMART not supported\n");
1348 			return;
1349 		}
1350 
1351 		memset(&inbuf, 0, sizeof(inbuf));
1352 		memset(&req, 0, sizeof(req));
1353 
1354 		req.flags = ATACMD_READ;
1355 		req.features = WDSM_RD_LOG;
1356 		req.sec_count = 1;
1357 		req.sec_num = 1;
1358 		req.command = WDCC_SMART;
1359 		req.databuf = (caddr_t) inbuf;
1360 		req.datalen = sizeof(inbuf);
1361 		req.cylinder = WDSMART_CYL;
1362 		req.timeout = 1000;
1363 
1364 		ata_command(&req);
1365 
1366 		print_error(inbuf);
1367 	} else if (strcmp(argv[0], "selftest-log") == 0) {
1368 		if (!is_smart()) {
1369 			fprintf(stderr, "SMART not supported\n");
1370 			return;
1371 		}
1372 
1373 		memset(&inbuf, 0, sizeof(inbuf));
1374 		memset(&req, 0, sizeof(req));
1375 
1376 		req.flags = ATACMD_READ;
1377 		req.features = WDSM_RD_LOG;
1378 		req.sec_count = 1;
1379 		req.sec_num = 6;
1380 		req.command = WDCC_SMART;
1381 		req.databuf = (caddr_t) inbuf;
1382 		req.datalen = sizeof(inbuf);
1383 		req.cylinder = WDSMART_CYL;
1384 		req.timeout = 1000;
1385 
1386 		ata_command(&req);
1387 
1388 		print_selftest(inbuf);
1389 
1390 	} else {
1391 		usage();
1392 	}
1393 	return;
1394 }
1395 
1396 static void
1397 device_security(int argc, char *argv[])
1398 {
1399 	struct atareq req;
1400 	const struct ataparams *inqbuf;
1401 	unsigned char data[DEV_BSIZE];
1402 	char *pass;
1403 
1404 	/* need subcommand */
1405 	if (argc < 1)
1406 		usage();
1407 
1408 	memset(&req, 0, sizeof(req));
1409 	if (strcmp(argv[0], "status") == 0) {
1410 		inqbuf = getataparams();
1411 		print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1412 	} else if (strcmp(argv[0], "freeze") == 0) {
1413 		req.command = WDCC_SECURITY_FREEZE;
1414 		req.timeout = 1000;
1415 		ata_command(&req);
1416 	} else if ((strcmp(argv[0], "setpass") == 0) ||
1417 	    (strcmp(argv[0], "unlock") == 0) ||
1418 	    (strcmp(argv[0], "disable") == 0) ||
1419 	    (strcmp(argv[0], "erase") == 0)) {
1420 		if (argc != 2)
1421 			usage();
1422 		if (strcmp(argv[1], "user") != 0) {
1423 			if (strcmp(argv[1], "master") == 0) {
1424 				fprintf(stderr,
1425 				    "Master passwords not supported\n");
1426 				exit(1);
1427 			} else {
1428 				usage();
1429 			}
1430 		}
1431 
1432 		pass = getpass("Password:");
1433 		if (strlen(pass) > 32) {
1434 			fprintf(stderr, "Password must be <=32 characters\n");
1435 			exit(1);
1436 		}
1437 
1438 		req.flags |= ATACMD_WRITE;
1439 		req.timeout = 1000;
1440 		req.databuf = data;
1441 		req.datalen = sizeof(data);
1442 		memset(data, 0, sizeof(data));
1443 		strlcpy((void *)&data[2], pass, 32 + 1);
1444 
1445 		if (strcmp(argv[0], "setpass") == 0) {
1446 			char orig[32 + 1];
1447 			strlcpy(orig, pass, 32 + 1);
1448 			pass = getpass("Confirm password:");
1449 			if (0 != strcmp(orig, pass)) {
1450 				fprintf(stderr, "Passwords do not match\n");
1451 				exit(1);
1452 			}
1453 			req.command = WDCC_SECURITY_SET_PASSWORD;
1454 		} else if (strcmp(argv[0], "unlock") == 0) {
1455 			req.command = WDCC_SECURITY_UNLOCK;
1456 		} else if (strcmp(argv[0], "disable") == 0) {
1457 			req.command = WDCC_SECURITY_DISABLE_PASSWORD;
1458 		} else if (strcmp(argv[0], "erase") == 0) {
1459 			struct atareq prepare;
1460 
1461 			inqbuf = getataparams();
1462 
1463 			/*
1464 			 * XXX Any way to lock the device to make sure
1465 			 * this really is the command preceding the
1466 			 * SECURITY ERASE UNIT command?  This would
1467 			 * probably have to be moved into the kernel to
1468 			 * do that.
1469 			 */
1470 			memset(&prepare, 0, sizeof(prepare));
1471 			prepare.command = WDCC_SECURITY_ERASE_PREPARE;
1472 			prepare.timeout = 1000;
1473 			ata_command(&prepare);
1474 
1475 			req.command = WDCC_SECURITY_ERASE_UNIT;
1476 
1477 			/*
1478 			 * Enable enhanced erase if it's supported.
1479 			 *
1480 			 * XXX should be a command-line option
1481 			 */
1482 			if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {
1483 				data[0] |= 0x2;
1484 				req.timeout = (inqbuf->atap_eseu_time & 0xff)
1485 				    * 2 * 60 * 1000;
1486 			} else {
1487 				req.timeout = (inqbuf->atap_seu_time & 0xff)
1488 				    * 2 * 60 * 1000;
1489 			}
1490 
1491 			/*
1492 			 * If the estimated time was 0xff (* 2 * 60 *
1493 			 * 1000 = 30600000), that means `>508 minutes'.
1494 			 * Estimate that we can handle 16 MB/sec, a
1495 			 * rate I just pulled out of my arse.
1496 			 */
1497 			if (req.timeout == 30600000) {
1498 				uint64_t bytes, timeout;
1499 				compute_capacity(inqbuf, &bytes, NULL, NULL);
1500 				timeout = (bytes / (16 * 1024 * 1024)) * 1000;
1501 				if (timeout > (uint64_t)INT_MAX)
1502 					req.timeout = INT_MAX;
1503 				else
1504 					req.timeout = timeout;
1505 			}
1506 
1507 			printf("Erasing may take up to %dh %dm %ds...\n",
1508 			    (req.timeout / 1000 / 60) / 60,
1509 			    (req.timeout / 1000 / 60) % 60,
1510 			    req.timeout % 60);
1511 		} else {
1512 			abort();
1513 		}
1514 
1515 		ata_command(&req);
1516 	} else {
1517 		usage();
1518 	}
1519 }
1520 
1521 /*
1522  * bus_reset:
1523  *	Reset an ATA bus (will reset all devices on the bus)
1524  */
1525 static void
1526 bus_reset(int argc, char *argv[])
1527 {
1528 	int error;
1529 
1530 	/* no args */
1531 	if (argc != 0)
1532 		usage();
1533 
1534 	error = ioctl(fd, ATABUSIORESET, NULL);
1535 
1536 	if (error == -1)
1537 		err(1, "ATABUSIORESET failed");
1538 }
1539