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