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