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