xref: /netbsd-src/sbin/atactl/atactl.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: atactl.c,v 1.77 2016/10/04 21:37:46 mrg 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.77 2016/10/04 21:37:46 mrg 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 	{ 100,          "Erase/Program Cycles", NULL },
277 	{ 103,          "Translation Table Rebuild", NULL },
278 	{ 170,          "Reserved Block Count", NULL },
279 	{ 171,          "Program Fail Count", NULL },
280 	{ 172,          "Erase Fail Count", NULL },
281 	{ 173,          "Wear Leveller Worst Case Erase Count", NULL },
282 	{ 174,          "Unexpected Power Loss", NULL },
283 	{ 175,          "Program Fail Count", NULL },
284 	{ 176,          "Erase Fail Count", NULL },
285 	{ 177,          "Wear Leveling Count", NULL },
286 	{ 178,          "Used Reserved Block Count", NULL },
287 	{ 179,          "Used Reserved Block Count", NULL },
288 	{ 180,          "Unused Reserved Block Count", NULL },
289 	{ 181,          "Program Fail Count", NULL },
290 	{ 182,          "Erase Fail Count", NULL },
291 	{ 183,          "SATA Downshift Error Count", NULL },
292 	{ 184,          "End-to-end error", NULL },
293 	{ 185,          "Head Stability", NULL },
294 	{ 186,          "Induced Op-Vibration Detection", NULL },
295 	{ 187,          "Reported uncorrect", NULL },
296 	{ 188,          "Command Timeout", NULL },
297 	{ 189,          "High Fly Writes", NULL },
298 	{ 190,          "Airflow Temperature",		device_smart_temp },
299 	{ 191,		"G-sense error rate", NULL },
300 	{ 192,		"Power-off retract count", NULL },
301 	{ 193,		"Load cycle count", NULL },
302 	{ 194,		"Temperature",			device_smart_temp},
303 	{ 195,		"Hardware ECC Recovered", NULL },
304 	{ 196,		"Reallocated event count", NULL },
305 	{ 197,		"Current pending sector", NULL },
306 	{ 198,		"Offline uncorrectable", NULL },
307 	{ 199,		"Ultra DMA CRC error count", NULL },
308 	{ 200,		"Write error rate", NULL },
309 	{ 201,		"Soft read error rate", NULL },
310 	{ 202,		"Data address mark errors", NULL },
311 	{ 203,		"Run out cancel", NULL },
312 	{ 204,		"Soft ECC correction", NULL },
313 	{ 205,		"Thermal asperity check", NULL },
314 	{ 206,		"Flying height", NULL },
315 	{ 207,		"Spin high current", NULL },
316 	{ 208,		"Spin buzz", NULL },
317 	{ 209,		"Offline seek performance", NULL },
318 	{ 210,		"Successful RAIN Recovery Count", NULL },
319 	{ 220,		"Disk shift", NULL },
320 	{ 221,		"G-Sense error rate", NULL },
321 	{ 222,		"Loaded hours", NULL },
322 	{ 223,		"Load/unload retry count", NULL },
323 	{ 224,		"Load friction", NULL },
324 	{ 225,		"Load/unload cycle count", NULL },
325 	{ 226,		"Load-in time", NULL },
326 	{ 227,		"Torque amplification count", NULL },
327 	{ 228,		"Power-off retract count", NULL },
328 	{ 230,		"GMR head amplitude", NULL },
329 	{ 231,		"Temperature",			device_smart_temp },
330 	{ 232,		"Available reserved space", NULL },
331 	{ 233,		"Media wearout indicator", NULL },
332 	{ 240,		"Head flying hours", NULL },
333 	{ 241,		"Total LBAs Written", NULL },
334 	{ 242,		"Total LBAs Read", NULL },
335 	{ 246,		"Total Host Sector Writes", NULL },
336 	{ 247,		"Host Program NAND Pages Count", NULL },
337 	{ 248,		"FTL Program Pages Count ", NULL },
338 	{ 249,		"Total Raw NAND Writes (1GiB units)", NULL },
339 	{ 250,		"Read error retry rate", NULL },
340 	{ 254,		"Free Fall Sensor", NULL },
341 	{   0,		"Unknown", NULL },
342 };
343 
344 static const struct bitinfo ata_sec_st[] = {
345 	{ WDC_SEC_SUPP,		"supported" },
346 	{ WDC_SEC_EN,		"enabled" },
347 	{ WDC_SEC_LOCKED,	"locked" },
348 	{ WDC_SEC_FROZEN,	"frozen" },
349 	{ WDC_SEC_EXP,		"expired" },
350 	{ WDC_SEC_ESE_SUPP,	"enhanced erase support" },
351 	{ WDC_SEC_LEV_MAX,	"maximum level" },
352 	{ 0,			NULL },
353 };
354 
355 int
356 main(int argc, char *argv[])
357 {
358 	int i;
359 	const struct command *commands = NULL;
360 
361 	/* Must have at least: device command */
362 	if (argc < 3)
363 		usage();
364 
365 	/* Skip program name, get and skip device name and command. */
366 	dvname = argv[1];
367 	cmdname = argv[2];
368 	argv += 3;
369 	argc -= 3;
370 
371 	/*
372 	 * Open the device
373 	 */
374 	fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
375 	if (fd == -1) {
376 		if (errno == ENOENT) {
377 			/*
378 			 * Device doesn't exist.  Probably trying to open
379 			 * a device which doesn't use disk semantics for
380 			 * device name.  Try again, specifying "cooked",
381 			 * which leaves off the "r" in front of the device's
382 			 * name.
383 			 */
384 			fd = opendisk(dvname, O_RDWR, dvname_store,
385 			    sizeof(dvname_store), 1);
386 			if (fd == -1)
387 				err(1, "%s", dvname);
388 		} else
389 			err(1, "%s", dvname);
390 	}
391 
392 	/*
393 	 * Point the dvname at the actual device name that opendisk() opened.
394 	 */
395 	dvname = dvname_store;
396 
397 	/* Look up and call the command. */
398 	for (i = 0; device_commands[i].cmd_name != NULL; i++) {
399 		if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
400 			commands = &device_commands[i];
401 			break;
402 		}
403 	}
404 	if (commands == NULL) {
405 		for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
406 			if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
407 				commands = &bus_commands[i];
408 				break;
409 			}
410 		}
411 	}
412 	if (commands == NULL)
413 		errx(1, "unknown command: %s", cmdname);
414 
415 	(*commands->cmd_func)(argc, argv);
416 	exit(0);
417 }
418 
419 static void
420 usage(void)
421 {
422 	int i;
423 
424 	fprintf(stderr, "usage: %s device command [arg [...]]\n",
425 	    getprogname());
426 
427 	fprintf(stderr, "   Available device commands:\n");
428 	for (i=0; device_commands[i].cmd_name != NULL; i++)
429 		fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
430 					    device_commands[i].arg_names);
431 
432 	fprintf(stderr, "   Available bus commands:\n");
433 	for (i=0; bus_commands[i].cmd_name != NULL; i++)
434 		fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
435 					    bus_commands[i].arg_names);
436 
437 	exit(1);
438 }
439 
440 /*
441  * Wrapper that calls ATAIOCCOMMAND and checks for errors
442  */
443 
444 static void
445 ata_command(struct atareq *req)
446 {
447 	int error;
448 
449 	error = ioctl(fd, ATAIOCCOMMAND, req);
450 
451 	if (error == -1)
452 		err(1, "ATAIOCCOMMAND failed");
453 
454 	switch (req->retsts) {
455 
456 	case ATACMD_OK:
457 		return;
458 	case ATACMD_TIMEOUT:
459 		fprintf(stderr, "ATA command timed out\n");
460 		exit(1);
461 	case ATACMD_DF:
462 		fprintf(stderr, "ATA device returned a Device Fault\n");
463 		exit(1);
464 	case ATACMD_ERROR:
465 		if (req->error & WDCE_ABRT)
466 			fprintf(stderr, "ATA device returned Aborted "
467 				"Command\n");
468 		else
469 			fprintf(stderr, "ATA device returned error register "
470 				"%0x\n", req->error);
471 		exit(1);
472 	default:
473 		fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
474 			"%d\n", req->retsts);
475 		exit(1);
476 	}
477 }
478 
479 /*
480  * Print out strings associated with particular bitmasks
481  */
482 
483 static void
484 print_bitinfo(const char *bf, const char *af, u_int bits,
485     const struct bitinfo *binfo)
486 {
487 
488 	for (; binfo->bitmask != 0; binfo++)
489 		if (bits & binfo->bitmask)
490 			printf("%s%s%s", bf, binfo->string, af);
491 }
492 
493 static void
494 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables,
495     const struct bitinfo *binfo)
496 {
497 
498 	for (; binfo->bitmask != 0; binfo++)
499 		if (bits & binfo->bitmask)
500 			printf("%s%s (%s)%s", bf, binfo->string,
501 			    (enables & binfo->bitmask) ? "enabled" : "disabled",
502 			    af);
503 }
504 
505 
506 /*
507  * Try to print SMART temperature field
508  */
509 
510 static void
511 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value)
512 {
513 	printf("%" PRIu8, attr->raw[0]);
514 	if (attr->raw[0] != raw_value)
515 		printf(" Lifetime min/max %" PRIu8 "/%" PRIu8,
516 		    attr->raw[2], attr->raw[4]);
517 }
518 
519 
520 /*
521  * Print out SMART attribute thresholds and values
522  */
523 
524 static void
525 print_smart_status(void *vbuf, void *tbuf)
526 {
527 	const struct ata_smart_attributes *value_buf = vbuf;
528 	const struct ata_smart_thresholds *threshold_buf = tbuf;
529 	const struct ata_smart_attr *attr;
530 	uint64_t raw_value;
531 	int flags;
532 	int i, j;
533 	int aid;
534 	uint8_t checksum;
535 
536 	for (i = checksum = 0; i < 512; i++)
537 		checksum += ((const uint8_t *) value_buf)[i];
538 	if (checksum != 0) {
539 		fprintf(stderr, "SMART attribute values checksum error\n");
540 		return;
541 	}
542 
543 	for (i = checksum = 0; i < 512; i++)
544 		checksum += ((const uint8_t *) threshold_buf)[i];
545 	if (checksum != 0) {
546 		fprintf(stderr, "SMART attribute thresholds checksum error\n");
547 		return;
548 	}
549 
550 	printf("id value thresh crit collect reliability description"
551 	    "                 raw\n");
552 	for (i = 0; i < 256; i++) {
553 		int thresh = 0;
554 
555 		attr = NULL;
556 
557 		for (j = 0; j < 30; j++) {
558 			if (value_buf->attributes[j].id == i)
559 				attr = &value_buf->attributes[j];
560 			if (threshold_buf->thresholds[j].id == i)
561 				thresh = threshold_buf->thresholds[j].value;
562 		}
563 
564 		if (thresh && attr == NULL)
565 			errx(1, "threshold but not attr %d", i);
566 		if (attr == NULL)
567 			continue;
568 
569 		if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
570 			continue;
571 
572 		for (aid = 0;
573 		     smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
574 		     aid++)
575 			;
576 
577 		flags = le16toh(attr->flags);
578 
579 		printf("%3d %3d  %3d     %-3s %-7s %stive    %-27s ",
580 		    i, attr->value, thresh,
581 		    flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
582 		    flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
583 		    attr->value > thresh ? "posi" : "nega",
584 		    smart_attrs[aid].name);
585 
586 		for (j = 0, raw_value = 0; j < 6; j++)
587 			raw_value += ((uint64_t)attr->raw[j]) << (8*j);
588 
589 		if (smart_attrs[aid].special)
590 			(*smart_attrs[aid].special)(attr, raw_value);
591 		else
592 			printf("%" PRIu64, raw_value);
593 		printf("\n");
594 	}
595 }
596 
597 static const struct {
598 	int number;
599 	const char *name;
600 } selftest_name[] = {
601 	{ 0, "Off-line" },
602 	{ 1, "Short off-line" },
603 	{ 2, "Extended off-line" },
604 	{ 127, "Abort off-line test" },
605 	{ 129, "Short captive" },
606 	{ 130, "Extended captive" },
607 	{ 256, "Unknown test" }, /* larger than uint8_t */
608 	{ 0, NULL }
609 };
610 
611 static const char *selftest_status[] = {
612 	"No error",
613 	"Aborted by the host",
614 	"Interrupted by the host by reset",
615 	"Fatal error or unknown test error",
616 	"Unknown test element failed",
617 	"Electrical test element failed",
618 	"The Servo (and/or seek) test element failed",
619 	"Read element of test failed",
620 	"Reserved",
621 	"Reserved",
622 	"Reserved",
623 	"Reserved",
624 	"Reserved",
625 	"Reserved",
626 	"Reserved",
627 	"Self-test in progress"
628 };
629 
630 static void
631 print_error_entry(int num, const struct ata_smart_error *le)
632 {
633 	int i;
634 
635 	printf("Log entry: %d\n", num);
636 
637 	for (i = 0; i < 5; i++)
638 		printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x "
639 		    "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
640 		    le->command[i].device_control,
641 		    le->command[i].features,
642 		    le->command[i].sector_count,
643 		    le->command[i].sector_number,
644 		    le->command[i].cylinder_low,
645 		    le->command[i].cylinder_high,
646 		    le->command[i].device_head,
647 		    le->command[i].command,
648 		    le->command[i].timestamp[3],
649 		    le->command[i].timestamp[2],
650 		    le->command[i].timestamp[1],
651 		    le->command[i].timestamp[0]);
652 	printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x "
653 	    "status=%02x state=%02x lifetime=%02x%02x\n",
654 	    le->error_data.error,
655 	    le->error_data.sector_count,
656 	    le->error_data.sector_number,
657 	    le->error_data.cylinder_low,
658 	    le->error_data.cylinder_high,
659 	    le->error_data.device_head,
660 	    le->error_data.status,
661 	    le->error_data.state,
662 	    le->error_data.lifetime[1],
663 	    le->error_data.lifetime[0]);
664 	printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
665 	    "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
666 	    le->error_data.extended_error[0],
667 	    le->error_data.extended_error[1],
668 	    le->error_data.extended_error[2],
669 	    le->error_data.extended_error[3],
670 	    le->error_data.extended_error[4],
671 	    le->error_data.extended_error[5],
672 	    le->error_data.extended_error[6],
673 	    le->error_data.extended_error[7],
674 	    le->error_data.extended_error[8],
675 	    le->error_data.extended_error[9],
676 	    le->error_data.extended_error[10],
677 	    le->error_data.extended_error[11],
678 	    le->error_data.extended_error[12],
679 	    le->error_data.extended_error[13],
680 	    le->error_data.extended_error[14],
681 	    le->error_data.extended_error[15],
682 	    le->error_data.extended_error[15],
683 	    le->error_data.extended_error[17],
684 	    le->error_data.extended_error[18]);
685 }
686 
687 static void
688 print_error(const void *buf)
689 {
690 	const struct ata_smart_errorlog *erlog = buf;
691 	uint8_t checksum;
692 	int i;
693 
694 	for (i = checksum = 0; i < 512; i++)
695 		checksum += ((const uint8_t *) buf)[i];
696 	if (checksum != 0) {
697 		fprintf(stderr, "SMART error log checksum error\n");
698 		return;
699 	}
700 
701 	if (erlog->data_structure_revision != 1) {
702 		fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
703 		    erlog->data_structure_revision);
704 		return;
705 	}
706 
707 	if (erlog->mostrecenterror == 0) {
708 		printf("No errors have been logged\n");
709 		return;
710 	}
711 
712 	if (erlog->mostrecenterror > 5) {
713 		fprintf(stderr, "Most recent error is too large\n");
714 		return;
715 	}
716 
717 	for (i = erlog->mostrecenterror; i < 5; i++)
718 		print_error_entry(i, &erlog->log_entries[i]);
719 	for (i = 0; i < erlog->mostrecenterror; i++)
720 		print_error_entry(i, &erlog->log_entries[i]);
721 	printf("device error count: %d\n", erlog->device_error_count);
722 }
723 
724 static void
725 print_selftest_entry(int num, const struct ata_smart_selftest *le)
726 {
727 	const unsigned char *p;
728 	size_t i;
729 
730 	/* check if all zero */
731 	for (p = (const void *)le, i = 0; i < sizeof(*le); i++)
732 		if (p[i] != 0)
733 			break;
734 	if (i == sizeof(*le))
735 		return;
736 
737 	printf("Log entry: %d\n", num);
738 
739 	/* Get test name */
740 	for (i = 0; selftest_name[i].name != NULL; i++)
741 		if (selftest_name[i].number == le->number)
742 			break;
743 
744 	if (selftest_name[i].name == NULL)
745 		printf("\tName: (%d)\n", le->number);
746 	else
747 		printf("\tName: %s\n", selftest_name[i].name);
748 	printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
749 	/* XXX This generally should not be set when a self-test is completed,
750 	   and at any rate is useless.  - mycroft */
751 	if (le->status >> 4 == 15)
752 		printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
753 	else if (le->status >> 4 != 0)
754 		printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
755 }
756 
757 static void
758 print_selftest(const void *buf)
759 {
760 	const struct ata_smart_selftestlog *stlog = buf;
761 	uint8_t checksum;
762 	int i;
763 
764 	for (i = checksum = 0; i < 512; i++)
765 		checksum += ((const uint8_t *) buf)[i];
766 	if (checksum != 0) {
767 		fprintf(stderr, "SMART selftest log checksum error\n");
768 		return;
769 	}
770 
771 	if (le16toh(stlog->data_structure_revision) != 1) {
772 		fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
773 		    le16toh(stlog->data_structure_revision));
774 		return;
775 	}
776 
777 	if (stlog->mostrecenttest == 0) {
778 		printf("No self-tests have been logged\n");
779 		return;
780 	}
781 
782 	if (stlog->mostrecenttest > 22) {
783 		fprintf(stderr, "Most recent test is too large\n");
784 		return;
785 	}
786 
787 	for (i = stlog->mostrecenttest; i < 22; i++)
788 		print_selftest_entry(i, &stlog->log_entries[i]);
789 	for (i = 0; i < stlog->mostrecenttest; i++)
790 		print_selftest_entry(i, &stlog->log_entries[i]);
791 }
792 
793 static const struct ataparams *
794 getataparams(void)
795 {
796 	struct atareq req;
797 	static union {
798 		unsigned char inbuf[DEV_BSIZE];
799 		struct ataparams inqbuf;
800 	} inbuf;
801 
802 	memset(&inbuf, 0, sizeof(inbuf));
803 	memset(&req, 0, sizeof(req));
804 
805 	req.flags = ATACMD_READ;
806 	req.command = WDCC_IDENTIFY;
807 	req.databuf = &inbuf;
808 	req.datalen = sizeof(inbuf);
809 	req.timeout = 1000;
810 
811 	ata_command(&req);
812 
813 	return (&inbuf.inqbuf);
814 }
815 
816 /*
817  * is_smart:
818  *
819  *	Detect whether device supports SMART and SMART is enabled.
820  */
821 
822 static int
823 is_smart(void)
824 {
825 	int retval = 0;
826 	const struct ataparams *inqbuf;
827 	const char *status;
828 
829 	inqbuf = getataparams();
830 
831 	if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
832 		if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
833 			fprintf(stderr, "SMART unsupported\n");
834 		} else {
835 			if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
836 			    inqbuf->atap_cmd_set2 == 0xffff ||
837 			    inqbuf->atap_cmd_set2 == 0x0000) {
838 				status = "status unknown";
839 				retval = 2;
840 			} else {
841 				if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
842 					status = "enabled";
843 					retval = 1;
844 				} else {
845 					status = "disabled";
846 					retval = 3;
847 				}
848 			}
849 			printf("SMART supported, SMART %s\n", status);
850 		}
851 	}
852 	return retval;
853 }
854 
855 /*
856  * extract_string: copy a block of bytes out of ataparams and make
857  * a proper string out of it, truncating trailing spaces and preserving
858  * strict typing. And also, not doing unaligned accesses.
859  */
860 static void
861 extract_string(char *buf, size_t bufmax,
862 	       const uint8_t *bytes, size_t numbytes,
863 	       int needswap)
864 {
865 	unsigned i;
866 	size_t j;
867 	unsigned char ch1, ch2;
868 
869 	for (i = 0, j = 0; i < numbytes; i += 2) {
870 		ch1 = bytes[i];
871 		ch2 = bytes[i+1];
872 		if (needswap && j < bufmax-1) {
873 			buf[j++] = ch2;
874 		}
875 		if (j < bufmax-1) {
876 			buf[j++] = ch1;
877 		}
878 		if (!needswap && j < bufmax-1) {
879 			buf[j++] = ch2;
880 		}
881 	}
882 	while (j > 0 && buf[j-1] == ' ') {
883 		j--;
884 	}
885 	buf[j] = '\0';
886 }
887 
888 static void
889 compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp,
890     uint64_t *sectorsp, uint32_t *secsizep)
891 {
892 	uint64_t capacity;
893 	uint64_t sectors;
894 	uint32_t secsize;
895 
896 	if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
897 	    inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
898 		sectors =
899 		    ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
900 		    ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
901 		    ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
902 		    ((uint64_t)inqbuf->atap_max_lba[0] <<  0);
903 	} else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
904 		sectors = (inqbuf->atap_capacity[1] << 16) |
905 		    inqbuf->atap_capacity[0];
906 	} else {
907 		sectors = inqbuf->atap_cylinders *
908 		    inqbuf->atap_heads * inqbuf->atap_sectors;
909 	}
910 
911 	secsize = 512;
912 
913 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
914 		if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
915 			secsize = 2 *		/* words to bytes */
916 			    (inqbuf->atap_lls_secsz[1] << 16 |
917 			    inqbuf->atap_lls_secsz[0] <<  0);
918 		}
919 	}
920 
921 	capacity = sectors * secsize;
922 
923 	if (capacityp)
924 		*capacityp = capacity;
925 	if (sectorsp)
926 		*sectorsp = sectors;
927 	if (secsizep)
928 		*secsizep = secsize;
929 }
930 
931 /*
932  * DEVICE COMMANDS
933  */
934 
935 /*
936  * device_identify:
937  *
938  *	Display the identity of the device
939  */
940 static void
941 device_identify(int argc, char *argv[])
942 {
943 	const struct ataparams *inqbuf;
944 	char model[sizeof(inqbuf->atap_model)+1];
945 	char revision[sizeof(inqbuf->atap_revision)+1];
946 	char serial[sizeof(inqbuf->atap_serial)+1];
947 	char hnum[12];
948 	uint64_t capacity;
949 	uint64_t sectors;
950 	uint32_t secsize;
951 	int lb_per_pb;
952 	int needswap = 0;
953 	int i;
954 	uint8_t checksum;
955 
956 	/* No arguments. */
957 	if (argc != 0)
958 		usage();
959 
960 	inqbuf = getataparams();
961 
962 	if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) ==
963 	    WDC_INTEGRITY_MAGIC) {
964 		for (i = checksum = 0; i < 512; i++)
965 			checksum += ((const uint8_t *)inqbuf)[i];
966 		if (checksum != 0)
967 			puts("IDENTIFY DEVICE data checksum invalid\n");
968 	}
969 
970 #if BYTE_ORDER == LITTLE_ENDIAN
971 	/*
972 	 * On little endian machines, we need to shuffle the string
973 	 * byte order.  However, we don't have to do this for NEC or
974 	 * Mitsumi ATAPI devices
975 	 */
976 
977 	if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC &&
978 	      (inqbuf->atap_config & WDC_CFG_ATAPI) &&
979 	      ((inqbuf->atap_model[0] == 'N' &&
980 		  inqbuf->atap_model[1] == 'E') ||
981 	       (inqbuf->atap_model[0] == 'F' &&
982 		  inqbuf->atap_model[1] == 'X')))) {
983 		needswap = 1;
984 	}
985 #endif
986 
987 	/*
988 	 * Copy the info strings out, stripping off blanks.
989 	 */
990 	extract_string(model, sizeof(model),
991 		inqbuf->atap_model, sizeof(inqbuf->atap_model),
992 		needswap);
993 	extract_string(revision, sizeof(revision),
994 		inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
995 		needswap);
996 	extract_string(serial, sizeof(serial),
997 		inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
998 		needswap);
999 
1000 	printf("Model: %s, Rev: %s, Serial #: %s\n",
1001 		model, revision, serial);
1002 
1003 	if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff &&
1004 	    inqbuf->atap_cmd_ext & ATA_CMDE_WWN)
1005 		printf("World Wide Name: %016" PRIX64 "\n",
1006 		    ((uint64_t)inqbuf->atap_wwn[0] << 48) |
1007 		    ((uint64_t)inqbuf->atap_wwn[1] << 32) |
1008 		    ((uint64_t)inqbuf->atap_wwn[2] << 16) |
1009 		    ((uint64_t)inqbuf->atap_wwn[3] <<  0));
1010 
1011 	printf("Device type: %s",
1012 		inqbuf->atap_config == WDC_CFG_CFA_MAGIC ? "CF-ATA" :
1013 		 (inqbuf->atap_config & WDC_CFG_ATAPI ? "ATAPI" : "ATA"));
1014 	if (inqbuf->atap_config != WDC_CFG_CFA_MAGIC)
1015 		printf(", %s",
1016 		 inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");
1017 	printf("\n");
1018 
1019 	compute_capacity(inqbuf, &capacity, &sectors, &secsize);
1020 
1021 	humanize_number(hnum, sizeof(hnum), capacity, "bytes",
1022 		HN_AUTOSCALE, HN_DIVISOR_1000);
1023 
1024 	printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n",
1025 		       hnum, sectors, secsize);
1026 
1027 	printf("Cylinders: %d, heads: %d, sec/track: %d\n",
1028 		inqbuf->atap_cylinders, inqbuf->atap_heads,
1029 		inqbuf->atap_sectors);
1030 
1031 	lb_per_pb = 1;
1032 
1033 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
1034 		if (inqbuf->atap_secsz & ATA_SECSZ_LPS) {
1035 			lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK;
1036 			printf("Physical sector size: %d bytes\n",
1037 			    lb_per_pb * secsize);
1038 			if ((inqbuf->atap_logical_align &
1039 			    ATA_LA_VALID_MASK) == ATA_LA_VALID) {
1040 				printf("First physically aligned sector: %d\n",
1041 				    lb_per_pb - (inqbuf->atap_logical_align &
1042 					ATA_LA_MASK));
1043 			}
1044 		}
1045 	}
1046 
1047 	if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) ||
1048 	    (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) &&
1049 	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
1050 		printf("Command queue depth: %d\n",
1051 		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
1052 
1053 	printf("Device capabilities:\n");
1054 	print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
1055 
1056 	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
1057 		printf("Device supports following standards:\n");
1058 		print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
1059 		printf("\n");
1060 	}
1061 
1062 	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
1063 	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
1064 		printf("Command set support:\n");
1065 		if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
1066 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
1067 			    inqbuf->atap_cmd1_en, ata_cmd_set1);
1068 		else
1069 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
1070 			    ata_cmd_set1);
1071 		if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
1072 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
1073 			    inqbuf->atap_cmd2_en, ata_cmd_set2);
1074 		else
1075 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
1076 			    ata_cmd_set2);
1077 		if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
1078 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
1079 			    ata_cmd_ext);
1080 	}
1081 
1082 	if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
1083 		printf("Serial ATA capabilities:\n");
1084 		print_bitinfo("\t", "\n",
1085 		    inqbuf->atap_sata_caps, ata_sata_caps);
1086 
1087 	}
1088 
1089 	if (inqbuf->atap_sata_features_supp != 0 &&
1090 	    inqbuf->atap_sata_features_supp != 0xffff) {
1091 		printf("Serial ATA features:\n");
1092 		if (inqbuf->atap_sata_features_en != 0 &&
1093 		    inqbuf->atap_sata_features_en != 0xffff)
1094 			print_bitinfo2("\t", "\n",
1095 			    inqbuf->atap_sata_features_supp,
1096 			    inqbuf->atap_sata_features_en, ata_sata_feat);
1097 		else
1098 			print_bitinfo("\t", "\n",
1099 			    inqbuf->atap_sata_features_supp, ata_sata_feat);
1100 	}
1101 
1102 	if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&
1103 	    (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
1104 		printf("TRIM supported\n");
1105 
1106 	return;
1107 }
1108 
1109 /*
1110  * device idle:
1111  *
1112  * issue the IDLE IMMEDIATE command to the drive
1113  */
1114 static void
1115 device_idle(int argc, char *argv[])
1116 {
1117 	struct atareq req;
1118 
1119 	/* No arguments. */
1120 	if (argc != 0)
1121 		usage();
1122 
1123 	memset(&req, 0, sizeof(req));
1124 
1125 	if (strcmp(cmdname, "idle") == 0)
1126 		req.command = WDCC_IDLE_IMMED;
1127 	else if (strcmp(cmdname, "standby") == 0)
1128 		req.command = WDCC_STANDBY_IMMED;
1129 	else
1130 		req.command = WDCC_SLEEP;
1131 
1132 	req.timeout = 1000;
1133 
1134 	ata_command(&req);
1135 
1136 	return;
1137 }
1138 
1139 /*
1140  * device apm:
1141  *
1142  * enable/disable/control the APM feature of the drive
1143  */
1144 static void
1145 device_apm(int argc, char *argv[])
1146 {
1147 	struct atareq req;
1148 	long l;
1149 
1150 	memset(&req, 0, sizeof(req));
1151 	if (argc >= 1) {
1152 		req.command = SET_FEATURES;
1153 		req.timeout = 1000;
1154 
1155 		if (strcmp(argv[0], "disable") == 0)
1156 			req.features = WDSF_APM_DS;
1157 		else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
1158 		         (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
1159 
1160 			req.features = WDSF_APM_EN;
1161 			req.sec_count = l + 1;
1162 		} else
1163 			usage();
1164 	} else
1165 		usage();
1166 
1167 	ata_command(&req);
1168 }
1169 
1170 
1171 /*
1172  * Set the idle timer on the disk.  Set it for either idle mode or
1173  * standby mode, depending on how we were invoked.
1174  */
1175 
1176 static void
1177 device_setidle(int argc, char *argv[])
1178 {
1179 	unsigned long idle;
1180 	struct atareq req;
1181 	char *end;
1182 
1183 	/* Only one argument */
1184 	if (argc != 1)
1185 		usage();
1186 
1187 	idle = strtoul(argv[0], &end, 0);
1188 
1189 	if (*end != '\0') {
1190 		fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1191 		exit(1);
1192 	}
1193 
1194 	if (idle > 19800) {
1195 		fprintf(stderr, "Idle time has a maximum value of 5.5 "
1196 			"hours\n");
1197 		exit(1);
1198 	}
1199 
1200 	if (idle != 0 && idle < 5) {
1201 		fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1202 		exit(1);
1203 	}
1204 
1205 	memset(&req, 0, sizeof(req));
1206 
1207 	if (idle <= 240*5)
1208 		req.sec_count = idle / 5;
1209 	else
1210 		req.sec_count = idle / (30*60) + 240;
1211 
1212 	req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1213 	req.timeout = 1000;
1214 
1215 	ata_command(&req);
1216 
1217 	return;
1218 }
1219 
1220 /*
1221  * Query the device for the current power mode
1222  */
1223 
1224 static void
1225 device_checkpower(int argc, char *argv[])
1226 {
1227 	struct atareq req;
1228 
1229 	/* No arguments. */
1230 	if (argc != 0)
1231 		usage();
1232 
1233 	memset(&req, 0, sizeof(req));
1234 
1235 	req.command = WDCC_CHECK_PWR;
1236 	req.timeout = 1000;
1237 	req.flags = ATACMD_READREG;
1238 
1239 	ata_command(&req);
1240 
1241 	printf("Current power status: ");
1242 
1243 	switch (req.sec_count) {
1244 	case 0x00:
1245 		printf("Standby mode\n");
1246 		break;
1247 	case 0x80:
1248 		printf("Idle mode\n");
1249 		break;
1250 	case 0xff:
1251 		printf("Active mode\n");
1252 		break;
1253 	default:
1254 		printf("Unknown power code (%02x)\n", req.sec_count);
1255 	}
1256 
1257 	return;
1258 }
1259 
1260 /*
1261  * device_smart:
1262  *
1263  *	Display SMART status
1264  */
1265 static void
1266 device_smart(int argc, char *argv[])
1267 {
1268 	struct atareq req;
1269 	unsigned char inbuf[DEV_BSIZE];
1270 	unsigned char inbuf2[DEV_BSIZE];
1271 
1272 	if (argc < 1)
1273 		usage();
1274 
1275 	if (strcmp(argv[0], "enable") == 0) {
1276 		memset(&req, 0, sizeof(req));
1277 
1278 		req.features = WDSM_ENABLE_OPS;
1279 		req.command = WDCC_SMART;
1280 		req.cylinder = WDSMART_CYL;
1281 		req.timeout = 1000;
1282 
1283 		ata_command(&req);
1284 
1285 		is_smart();
1286 	} else if (strcmp(argv[0], "disable") == 0) {
1287 		memset(&req, 0, sizeof(req));
1288 
1289 		req.features = WDSM_DISABLE_OPS;
1290 		req.command = WDCC_SMART;
1291 		req.cylinder = WDSMART_CYL;
1292 		req.timeout = 1000;
1293 
1294 		ata_command(&req);
1295 
1296 		is_smart();
1297 	} else if (strcmp(argv[0], "status") == 0) {
1298 		int rv;
1299 
1300 		rv = is_smart();
1301 
1302 		if (!rv) {
1303 			fprintf(stderr, "SMART not supported\n");
1304 			return;
1305 		} else if (rv == 3)
1306 			return;
1307 
1308 		memset(&inbuf, 0, sizeof(inbuf));
1309 		memset(&req, 0, sizeof(req));
1310 
1311 		req.features = WDSM_STATUS;
1312 		req.command = WDCC_SMART;
1313 		req.cylinder = WDSMART_CYL;
1314 		req.timeout = 1000;
1315 
1316 		ata_command(&req);
1317 
1318 		if (req.cylinder != WDSMART_CYL) {
1319 			fprintf(stderr, "Threshold exceeds condition\n");
1320 		}
1321 
1322 		/* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1323 		 * features, the following ata_command()'s may error
1324 		 * and exit().
1325 		 */
1326 
1327 		memset(&inbuf, 0, sizeof(inbuf));
1328 		memset(&req, 0, sizeof(req));
1329 
1330 		req.flags = ATACMD_READ;
1331 		req.features = WDSM_RD_DATA;
1332 		req.command = WDCC_SMART;
1333 		req.databuf = (caddr_t) inbuf;
1334 		req.datalen = sizeof(inbuf);
1335 		req.cylinder = WDSMART_CYL;
1336 		req.timeout = 1000;
1337 
1338 		ata_command(&req);
1339 
1340 		memset(&inbuf2, 0, sizeof(inbuf2));
1341 		memset(&req, 0, sizeof(req));
1342 
1343 		req.flags = ATACMD_READ;
1344 		req.features = WDSM_RD_THRESHOLDS;
1345 		req.command = WDCC_SMART;
1346 		req.databuf = (caddr_t) inbuf2;
1347 		req.datalen = sizeof(inbuf2);
1348 		req.cylinder = WDSMART_CYL;
1349 		req.timeout = 1000;
1350 
1351 		ata_command(&req);
1352 
1353 		print_smart_status(inbuf, inbuf2);
1354 
1355 	} else if (strcmp(argv[0], "offline") == 0) {
1356 		if (argc != 2)
1357 			usage();
1358 		if (!is_smart()) {
1359 			fprintf(stderr, "SMART not supported\n");
1360 			return;
1361 		}
1362 
1363 		memset(&req, 0, sizeof(req));
1364 
1365 		req.features = WDSM_EXEC_OFFL_IMM;
1366 		req.command = WDCC_SMART;
1367 		req.cylinder = WDSMART_CYL;
1368 		req.sec_num = atol(argv[1]);
1369 		req.timeout = 10000;
1370 
1371 		ata_command(&req);
1372 	} else if (strcmp(argv[0], "error-log") == 0) {
1373 		if (!is_smart()) {
1374 			fprintf(stderr, "SMART not supported\n");
1375 			return;
1376 		}
1377 
1378 		memset(&inbuf, 0, sizeof(inbuf));
1379 		memset(&req, 0, sizeof(req));
1380 
1381 		req.flags = ATACMD_READ;
1382 		req.features = WDSM_RD_LOG;
1383 		req.sec_count = 1;
1384 		req.sec_num = 1;
1385 		req.command = WDCC_SMART;
1386 		req.databuf = (caddr_t) inbuf;
1387 		req.datalen = sizeof(inbuf);
1388 		req.cylinder = WDSMART_CYL;
1389 		req.timeout = 1000;
1390 
1391 		ata_command(&req);
1392 
1393 		print_error(inbuf);
1394 	} else if (strcmp(argv[0], "selftest-log") == 0) {
1395 		if (!is_smart()) {
1396 			fprintf(stderr, "SMART not supported\n");
1397 			return;
1398 		}
1399 
1400 		memset(&inbuf, 0, sizeof(inbuf));
1401 		memset(&req, 0, sizeof(req));
1402 
1403 		req.flags = ATACMD_READ;
1404 		req.features = WDSM_RD_LOG;
1405 		req.sec_count = 1;
1406 		req.sec_num = 6;
1407 		req.command = WDCC_SMART;
1408 		req.databuf = (caddr_t) inbuf;
1409 		req.datalen = sizeof(inbuf);
1410 		req.cylinder = WDSMART_CYL;
1411 		req.timeout = 1000;
1412 
1413 		ata_command(&req);
1414 
1415 		print_selftest(inbuf);
1416 
1417 	} else {
1418 		usage();
1419 	}
1420 	return;
1421 }
1422 
1423 static void
1424 device_security(int argc, char *argv[])
1425 {
1426 	struct atareq req;
1427 	const struct ataparams *inqbuf;
1428 	unsigned char data[DEV_BSIZE];
1429 	char *pass;
1430 
1431 	/* need subcommand */
1432 	if (argc < 1)
1433 		usage();
1434 
1435 	memset(&req, 0, sizeof(req));
1436 	if (strcmp(argv[0], "status") == 0) {
1437 		inqbuf = getataparams();
1438 		print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1439 	} else if (strcmp(argv[0], "freeze") == 0) {
1440 		req.command = WDCC_SECURITY_FREEZE;
1441 		req.timeout = 1000;
1442 		ata_command(&req);
1443 	} else if ((strcmp(argv[0], "setpass") == 0) ||
1444 	    (strcmp(argv[0], "unlock") == 0) ||
1445 	    (strcmp(argv[0], "disable") == 0) ||
1446 	    (strcmp(argv[0], "erase") == 0)) {
1447 		if (argc != 2)
1448 			usage();
1449 		if (strcmp(argv[1], "user") != 0) {
1450 			if (strcmp(argv[1], "master") == 0) {
1451 				fprintf(stderr,
1452 				    "Master passwords not supported\n");
1453 				exit(1);
1454 			} else {
1455 				usage();
1456 			}
1457 		}
1458 
1459 		pass = getpass("Password:");
1460 		if (strlen(pass) > 32) {
1461 			fprintf(stderr, "Password must be <=32 characters\n");
1462 			exit(1);
1463 		}
1464 
1465 		req.flags |= ATACMD_WRITE;
1466 		req.timeout = 1000;
1467 		req.databuf = data;
1468 		req.datalen = sizeof(data);
1469 		memset(data, 0, sizeof(data));
1470 		strlcpy((void *)&data[2], pass, 32 + 1);
1471 
1472 		if (strcmp(argv[0], "setpass") == 0) {
1473 			char orig[32 + 1];
1474 			strlcpy(orig, pass, 32 + 1);
1475 			pass = getpass("Confirm password:");
1476 			if (0 != strcmp(orig, pass)) {
1477 				fprintf(stderr, "Passwords do not match\n");
1478 				exit(1);
1479 			}
1480 			req.command = WDCC_SECURITY_SET_PASSWORD;
1481 		} else if (strcmp(argv[0], "unlock") == 0) {
1482 			req.command = WDCC_SECURITY_UNLOCK;
1483 		} else if (strcmp(argv[0], "disable") == 0) {
1484 			req.command = WDCC_SECURITY_DISABLE_PASSWORD;
1485 		} else if (strcmp(argv[0], "erase") == 0) {
1486 			struct atareq prepare;
1487 
1488 			inqbuf = getataparams();
1489 
1490 			/*
1491 			 * XXX Any way to lock the device to make sure
1492 			 * this really is the command preceding the
1493 			 * SECURITY ERASE UNIT command?  This would
1494 			 * probably have to be moved into the kernel to
1495 			 * do that.
1496 			 */
1497 			memset(&prepare, 0, sizeof(prepare));
1498 			prepare.command = WDCC_SECURITY_ERASE_PREPARE;
1499 			prepare.timeout = 1000;
1500 			ata_command(&prepare);
1501 
1502 			req.command = WDCC_SECURITY_ERASE_UNIT;
1503 
1504 			/*
1505 			 * Enable enhanced erase if it's supported.
1506 			 *
1507 			 * XXX should be a command-line option
1508 			 */
1509 			if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {
1510 				data[0] |= 0x2;
1511 				req.timeout = (inqbuf->atap_eseu_time & 0xff)
1512 				    * 2 * 60 * 1000;
1513 			} else {
1514 				req.timeout = (inqbuf->atap_seu_time & 0xff)
1515 				    * 2 * 60 * 1000;
1516 			}
1517 
1518 			/*
1519 			 * If the estimated time was 0xff (* 2 * 60 *
1520 			 * 1000 = 30600000), that means `>508 minutes'.
1521 			 * Estimate that we can handle 16 MB/sec, a
1522 			 * rate I just pulled out of my arse.
1523 			 */
1524 			if (req.timeout == 30600000) {
1525 				uint64_t bytes, timeout;
1526 				compute_capacity(inqbuf, &bytes, NULL, NULL);
1527 				timeout = (bytes / (16 * 1024 * 1024)) * 1000;
1528 				if (timeout > (uint64_t)INT_MAX)
1529 					req.timeout = INT_MAX;
1530 				else
1531 					req.timeout = timeout;
1532 			}
1533 
1534 			printf("Erasing may take up to %dh %dm %ds...\n",
1535 			    (req.timeout / 1000 / 60) / 60,
1536 			    (req.timeout / 1000 / 60) % 60,
1537 			    req.timeout % 60);
1538 		} else {
1539 			abort();
1540 		}
1541 
1542 		ata_command(&req);
1543 	} else {
1544 		usage();
1545 	}
1546 }
1547 
1548 /*
1549  * bus_reset:
1550  *	Reset an ATA bus (will reset all devices on the bus)
1551  */
1552 static void
1553 bus_reset(int argc, char *argv[])
1554 {
1555 	int error;
1556 
1557 	/* no args */
1558 	if (argc != 0)
1559 		usage();
1560 
1561 	error = ioctl(fd, ATABUSIORESET, NULL);
1562 
1563 	if (error == -1)
1564 		err(1, "ATABUSIORESET failed");
1565 }
1566