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