Home | History | Annotate | Line # | Download | only in atactl
      1 /*	$NetBSD: atactl.c,v 1.86 2025/02/23 15:00:53 jakllsch Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998, 2019 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 and Matthew R. Green.
      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.86 2025/02/23 15:00:53 jakllsch Exp $");
     39 #endif
     40 
     41 
     42 #include <sys/param.h>
     43 #include <sys/ioctl.h>
     44 #include <err.h>
     45 #include <errno.h>
     46 #include <fcntl.h>
     47 #include <pwd.h>
     48 #include <stdio.h>
     49 #include <stdlib.h>
     50 #include <string.h>
     51 #include <unistd.h>
     52 #include <util.h>
     53 
     54 #include <dev/ata/atareg.h>
     55 #include <sys/ataio.h>
     56 
     57 #include <dev/scsipi/scsi_spc.h>
     58 #include <sys/scsiio.h>
     59 
     60 struct ata_smart_error {
     61 	struct {
     62 		uint8_t device_control;
     63 		uint8_t features;
     64 		uint8_t sector_count;
     65 		uint8_t sector_number;
     66 		uint8_t cylinder_low;
     67 		uint8_t cylinder_high;
     68 		uint8_t device_head;
     69 		uint8_t command;
     70 		uint8_t timestamp[4];
     71 	} command[5];
     72 	struct {
     73 		uint8_t reserved;
     74 		uint8_t error;
     75 		uint8_t sector_count;
     76 		uint8_t sector_number;
     77 		uint8_t cylinder_low;
     78 		uint8_t cylinder_high;
     79 		uint8_t device_head;
     80 		uint8_t status;
     81 		uint8_t extended_error[19];
     82 		uint8_t state;
     83 		uint8_t lifetime[2];
     84 	} error_data;
     85 } __packed;
     86 
     87 struct ata_smart_errorlog {
     88 	uint8_t			data_structure_revision;
     89 	uint8_t			mostrecenterror;
     90 	struct ata_smart_error	log_entries[5];
     91 	uint16_t		device_error_count;
     92 	uint8_t			reserved[57];
     93 	uint8_t			checksum;
     94 } __packed;
     95 
     96 #define SCSI_ATA_PASS_THROUGH_16	0x85
     97 struct scsi_ata_pass_through_16 {
     98 	uint8_t			opcode;
     99 	uint8_t			byte2;
    100 #define SATL_NODATA	0x06
    101 #define SATL_PIO_IN	0x08
    102 #define SATL_PIO_OUT	0x0a
    103 #define	SATL_EXTEND	0x01
    104 	uint8_t			byte3;
    105 #define SATL_CKCOND	0x20
    106 #define SATL_READ	0x08
    107 #define SATL_BLOCKS	0x04
    108 #define SATL_LEN(x)	((x) & 0x03)
    109 	uint8_t			features[2];
    110 	uint8_t			sector_count[2];
    111 	uint8_t			lba[6];
    112 	uint8_t			device;
    113 	uint8_t			ata_cmd;
    114 	uint8_t			control;
    115 } __packed;
    116 
    117 #define SCSI_ATA_PASS_THROUGH_12	0xa1
    118 struct scsi_ata_pass_through_12 {
    119 	uint8_t			opcode;
    120 	uint8_t			byte2;
    121 	uint8_t			byte3;
    122 	uint8_t			features[1];
    123 	uint8_t			sector_count[1];
    124 	uint8_t			lba[3];
    125 	uint8_t			device;
    126 	uint8_t			ata_cmd;
    127 	uint8_t			reserved;
    128 	uint8_t			control;
    129 } __packed;
    130 
    131 struct scsi_ata_return_descriptor {
    132 	uint8_t			descr;
    133 #define SCSI_ATA_RETURN_DESCRIPTOR	9
    134 	uint8_t			additional_length;
    135 	uint8_t			extend;
    136 	uint8_t			error;
    137 	uint8_t			sector_count[2];
    138 	uint8_t			lba[6];
    139 	uint8_t			device;
    140 	uint8_t			status;
    141 } __packed;
    142 
    143 struct command {
    144 	const char *cmd_name;
    145 	const char *arg_names;
    146 	void (*cmd_func)(int, char *[]);
    147 };
    148 
    149 struct bitinfo {
    150 	u_int bitmask;
    151 	const char *string;
    152 };
    153 
    154 __dead static void	usage(void);
    155 static void	ata_command(struct atareq *);
    156 static int	satl_command(struct atareq *, int);
    157 static const uint8_t *satl_return_desc(const uint8_t *, size_t, uint8_t);
    158 static void	print_bitinfo(const char *, const char *, u_int,
    159     const struct bitinfo *);
    160 static void	print_bitinfo2(const char *, const char *, u_int, u_int,
    161     const struct bitinfo *);
    162 static void	print_smart_status(void *, void *, const char *);
    163 static void	print_error_entry(int, const struct ata_smart_error *);
    164 static void	print_selftest_entry(int, const struct ata_smart_selftest *);
    165 
    166 static void	print_error(const void *);
    167 static void	print_selftest(const void *);
    168 
    169 static void	fillataparams(void);
    170 
    171 static int	is_smart(void);
    172 
    173 static int	fd;				/* file descriptor for device */
    174 static int	use_satl;			/* tunnel through SATL */
    175 static const	char *dvname;			/* device name */
    176 static char	dvname_store[MAXPATHLEN];	/* for opendisk(3) */
    177 static const	char *cmdname;			/* command user issued */
    178 static const	struct ataparams *inqbuf;	/* inquiry buffer */
    179 static char	model[sizeof(inqbuf->atap_model)+1];
    180 static char	revision[sizeof(inqbuf->atap_revision)+1];
    181 static char	serial[sizeof(inqbuf->atap_serial)+1];
    182 
    183 static void	device_identify(int, char *[]);
    184 static void	device_setidle(int, char *[]);
    185 static void	device_idle(int, char *[]);
    186 static void	device_apm(int, char *[]);
    187 static void	device_checkpower(int, char *[]);
    188 static void	device_smart(int, char *[]);
    189 static void	device_security(int, char *[]);
    190 
    191 static void	device_smart_temp(const struct ata_smart_attr *, uint64_t);
    192 
    193 static const struct command device_commands[] = {
    194 	{ "identify",	"",			device_identify },
    195 	{ "setidle",	"idle-timer",		device_setidle },
    196 	{ "apm",	"disable|set #",	device_apm },
    197 	{ "setstandby",	"standby-timer",	device_setidle },
    198 	{ "idle",	"",			device_idle },
    199 	{ "standby",	"",			device_idle },
    200 	{ "sleep",	"",			device_idle },
    201 	{ "checkpower",	"",			device_checkpower },
    202 	{ "smart",
    203 		"enable|disable|status [vendor]|offline #|error-log|selftest-log",
    204 						device_smart },
    205 	{ "security",
    206 		"status|freeze|[setpass|unlock|disable|erase] [user|master]",
    207 						device_security },
    208 	{ NULL,		NULL,			NULL },
    209 };
    210 
    211 static void	bus_reset(int, char *[]);
    212 
    213 static const struct command bus_commands[] = {
    214 	{ "reset",	"",			bus_reset },
    215 	{ NULL,		NULL,			NULL },
    216 };
    217 
    218 /*
    219  * Tables containing bitmasks used for error reporting and
    220  * device identification.
    221  */
    222 
    223 static const struct bitinfo ata_caps[] = {
    224 	{ WDC_CAP_DMA, "DMA" },
    225 	{ WDC_CAP_LBA, "LBA" },
    226 	{ ATA_CAP_STBY, "ATA standby timer values" },
    227 	{ WDC_CAP_IORDY, "IORDY operation" },
    228 	{ WDC_CAP_IORDY_DSBL, "IORDY disabling" },
    229 	{ 0, NULL },
    230 };
    231 
    232 static const struct bitinfo ata_vers[] = {
    233 	{ WDC_VER_ATA1,	"ATA-1" },
    234 	{ WDC_VER_ATA2,	"ATA-2" },
    235 	{ WDC_VER_ATA3,	"ATA-3" },
    236 	{ WDC_VER_ATA4,	"ATA-4" },
    237 	{ WDC_VER_ATA5,	"ATA-5" },
    238 	{ WDC_VER_ATA6,	"ATA-6" },
    239 	{ WDC_VER_ATA7,	"ATA-7" },
    240 	{ WDC_VER_ATA8, "ATA-8" },
    241 	{ 0, NULL },
    242 };
    243 
    244 static const struct bitinfo ata_cmd_set1[] = {
    245 	{ WDC_CMD1_NOP, "NOP command" },
    246 	{ WDC_CMD1_RB, "READ BUFFER command" },
    247 	{ WDC_CMD1_WB, "WRITE BUFFER command" },
    248 	{ WDC_CMD1_HPA, "Host Protected Area feature set" },
    249 	{ WDC_CMD1_DVRST, "DEVICE RESET command" },
    250 	{ WDC_CMD1_SRV, "SERVICE interrupt" },
    251 	{ WDC_CMD1_RLSE, "Release interrupt" },
    252 	{ WDC_CMD1_AHEAD, "Look-ahead" },
    253 	{ WDC_CMD1_CACHE, "Write cache" },
    254 	{ WDC_CMD1_PKT, "PACKET command feature set" },
    255 	{ WDC_CMD1_PM, "Power Management feature set" },
    256 	{ WDC_CMD1_REMOV, "Removable Media feature set" },
    257 	{ WDC_CMD1_SEC, "Security Mode feature set" },
    258 	{ WDC_CMD1_SMART, "SMART feature set" },
    259 	{ 0, NULL },
    260 };
    261 
    262 static const struct bitinfo ata_cmd_set2[] = {
    263 	{ ATA_CMD2_FCE, "FLUSH CACHE EXT command" },
    264 	{ WDC_CMD2_FC, "FLUSH CACHE command" },
    265 	{ WDC_CMD2_DCO, "Device Configuration Overlay feature set" },
    266 	{ ATA_CMD2_LBA48, "48-bit Address feature set" },
    267 	{ WDC_CMD2_AAM, "Automatic Acoustic Management feature set" },
    268 	{ WDC_CMD2_SM, "SET MAX security extension" },
    269 	{ WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" },
    270 	{ WDC_CMD2_PUIS, "Power-Up In Standby feature set" },
    271 	{ WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
    272 	{ ATA_CMD2_APM, "Advanced Power Management feature set" },
    273 	{ ATA_CMD2_CFA, "CFA feature set" },
    274 	{ ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
    275 	{ WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
    276 	{ 0, NULL },
    277 };
    278 
    279 static const struct bitinfo ata_cmd_ext[] = {
    280 	{ ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" },
    281 	{ ATA_CMDE_TL, "Time-limited Read/Write" },
    282 	{ ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" },
    283 	{ ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" },
    284 	{ ATA_CMDE_WWN, "World Wide Name" },
    285 	{ ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" },
    286 	{ ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" },
    287 	{ ATA_CMDE_GPL, "General Purpose Logging feature set" },
    288 	{ ATA_CMDE_STREAM, "Streaming feature set" },
    289 	{ ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" },
    290 	{ ATA_CMDE_MS, "Media serial number" },
    291 	{ ATA_CMDE_SST, "SMART self-test" },
    292 	{ ATA_CMDE_SEL, "SMART error logging" },
    293 	{ 0, NULL },
    294 };
    295 
    296 static const struct bitinfo ata_sata_caps[] = {
    297 	{ SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
    298 	{ SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
    299 	{ SATA_SIGNAL_GEN3, "6.0Gb/s signaling" },
    300 	{ SATA_NATIVE_CMDQ, "Native Command Queuing" },
    301 	{ SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
    302 	{ SATA_PHY_EVNT_CNT, "PHY Event Counters" },
    303 	{ 0, NULL },
    304 };
    305 
    306 static const struct bitinfo ata_sata_feat[] = {
    307 	{ SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" },
    308 	{ SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" },
    309 	{ SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Management" },
    310 	{ SATA_IN_ORDER_DATA, "In-order Data Delivery" },
    311 	{ SATA_SW_STTNGS_PRS, "Software Settings Preservation" },
    312 	{ 0, NULL },
    313 };
    314 
    315 /*
    316  * Global SMART attribute table.  All known attributes should be defined
    317  * here with overrides outside of the standard in a vendor specific table.
    318  *
    319  * XXX Some of these should be duplicated to vendor-specific tables now that
    320  * XXX they exist and have non generic names.
    321  */
    322 static const struct attr_table {
    323 	const unsigned	id;
    324 	const char	*name;
    325 	void (*special)(const struct ata_smart_attr *, uint64_t);
    326 } smart_attrs[] = {
    327 	{   1,		"Raw read error rate", NULL },
    328 	{   2,		"Throughput performance", NULL },
    329 	{   3,		"Spin-up time", NULL },
    330 	{   4,		"Start/stop count", NULL },
    331 	{   5,		"Reallocated sector count", NULL },
    332 	{   6,		"Read channel margin", NULL },
    333 	{   7,		"Seek error rate", NULL },
    334 	{   8,		"Seek time performance", NULL },
    335 	{   9,		"Power-on hours count", NULL },
    336 	{  10,		"Spin retry count", NULL },
    337 	{  11,		"Calibration retry count", NULL },
    338 	{  12,		"Device power cycle count", NULL },
    339 	{  13,		"Soft read error rate", NULL },
    340 	{ 100,          "Erase/Program Cycles", NULL },
    341 	{ 103,          "Translation Table Rebuild", NULL },
    342 	{ 170,          "Reserved Block Count", NULL },
    343 	{ 171,          "Program Fail Count", NULL },
    344 	{ 172,          "Erase Fail Count", NULL },
    345 	{ 173,          "Wear Leveller Worst Case Erase Count", NULL },
    346 	{ 174,          "Unexpected Power Loss Count", NULL },
    347 	{ 175,          "Program Fail Count", NULL },
    348 	{ 176,          "Erase Fail Count", NULL },
    349 	{ 177,          "Wear Leveling Count", NULL },
    350 	{ 178,          "Used Reserved Block Count", NULL },
    351 	{ 179,          "Used Reserved Block Count", NULL },
    352 	{ 180,          "Unused Reserved Block Count", NULL },
    353 	{ 181,          "Program Fail Count", NULL },
    354 	{ 182,          "Erase Fail Count", NULL },
    355 	{ 183,          "Runtime Bad Block", NULL },
    356 	{ 184,          "End-to-end error", NULL },
    357 	{ 185,          "Head Stability", NULL },
    358 	{ 186,          "Induced Op-Vibration Detection", NULL },
    359 	{ 187,          "Reported Uncorrectable Errors", NULL },
    360 	{ 188,          "Command Timeout", NULL },
    361 	{ 189,          "High Fly Writes", NULL },
    362 	{ 190,          "Airflow Temperature",		device_smart_temp },
    363 	{ 191,		"G-sense error rate", NULL },
    364 	{ 192,		"Power-off retract count", NULL },
    365 	{ 193,		"Load cycle count", NULL },
    366 	{ 194,		"Temperature",			device_smart_temp},
    367 	{ 195,		"Hardware ECC Recovered", NULL },
    368 	{ 196,		"Reallocated event count", NULL },
    369 	{ 197,		"Current pending sector", NULL },
    370 	{ 198,		"Offline uncorrectable", NULL },
    371 	{ 199,		"Ultra DMA CRC error count", NULL },
    372 	{ 200,		"Write error rate", NULL },
    373 	{ 201,		"Soft read error rate", NULL },
    374 	{ 202,		"Data address mark errors", NULL },
    375 	{ 203,		"Run out cancel", NULL },
    376 	{ 204,		"Soft ECC correction", NULL },
    377 	{ 205,		"Thermal asperity check", NULL },
    378 	{ 206,		"Flying height", NULL },
    379 	{ 207,		"Spin high current", NULL },
    380 	{ 208,		"Spin buzz", NULL },
    381 	{ 209,		"Offline seek performance", NULL },
    382 	{ 210,		"Successful RAIN Recovery Count", NULL },
    383 	{ 220,		"Disk shift", NULL },
    384 	{ 221,		"G-Sense error rate", NULL },
    385 	{ 222,		"Loaded hours", NULL },
    386 	{ 223,		"Load/unload retry count", NULL },
    387 	{ 224,		"Load friction", NULL },
    388 	{ 225,		"Load/unload cycle count", NULL },
    389 	{ 226,		"Load-in time", NULL },
    390 	{ 227,		"Torque amplification count", NULL },
    391 	{ 228,		"Power-off retract count", NULL },
    392 	{ 230,		"GMR head amplitude", NULL },
    393 	{ 231,		"Temperature",			device_smart_temp },
    394 	{ 232,		"Available reserved space", NULL },
    395 	{ 233,		"Media wearout indicator", NULL },
    396 	{ 240,		"Head flying hours", NULL },
    397 	{ 241,		"Total LBAs Written", NULL },
    398 	{ 242,		"Total LBAs Read", NULL },
    399 	{ 246,		"Total Host Sector Writes", NULL },
    400 	{ 247,		"Host Program NAND Pages Count", NULL },
    401 	{ 248,		"FTL Program Pages Count", NULL },
    402 	{ 249,		"Total Raw NAND Writes (1GiB units)", NULL },
    403 	{ 250,		"Read error retry rate", NULL },
    404 	{ 254,		"Free Fall Sensor", NULL },
    405 	{   0,		"Unknown", NULL },
    406 };
    407 
    408 /*
    409  * Micron specific SMART attributes published by Micron in:
    410  * "TN-FD-22: Client SATA SSD SMART Attribute Reference"
    411  */
    412 static const struct attr_table micron_smart_names[] = {
    413 	{   5,		"Reallocated NAND block count", NULL },
    414 	{ 173,          "Average block erase count", NULL },
    415 	{ 181,          "Non 4K aligned access count", NULL },
    416 	{ 183,          "SATA Downshift Error Count", NULL },
    417 	{ 184,          "Error correction count", NULL },
    418 	{ 189,          "Factory bad block count", NULL },
    419 	{ 197,		"Current pending ECC count", NULL },
    420 	{ 198,		"SMART offline scan uncorrectable error count", NULL },
    421 	{ 202,		"Percent lifetime used", NULL },
    422 	{ 206,		"Write error rate", NULL },
    423 	{ 247,		"Number of NAND pages of data written by the host", NULL },
    424 	{ 248,		"Number of NAND pages written by the FTL", NULL },
    425 	{   0,		"Unknown", NULL },
    426 };
    427 
    428 /*
    429  * Intel specific SMART attributes.  Fill me in with more.
    430  */
    431 static const struct attr_table intel_smart_names[] = {
    432 	{ 183,          "SATA Downshift Error Count", NULL },
    433 };
    434 
    435 /*
    436  * Samsung specific SMART attributes.  Fill me in with more.
    437  */
    438 static const struct attr_table samsung_smart_names[] = {
    439 	{ 235,          "POR Recovery Count", NULL },
    440 	{ 243,          "SATA Downshift Count", NULL },
    441 	{ 244,          "Thermal Throttle Status", NULL },
    442 	{ 245,          "Timed Workload Media Wear", NULL },
    443 	{ 251,          "NAND Writes", NULL },
    444 };
    445 
    446 
    447 /*
    448  * Vendor-specific SMART attribute table.  Can be used to override
    449  * a particular attribute name and special printer function, with the
    450  * default is the main table.
    451  */
    452 static const struct vendor_name_table {
    453 	const char *name;
    454 	const struct attr_table *table;
    455 } vendor_smart_names[] = {
    456 	{ "Micron",		micron_smart_names },
    457 	{ "Intel",		intel_smart_names },
    458 	{ "Samsung",		samsung_smart_names },
    459 };
    460 
    461 /*
    462  * Global model -> vendor table.  Extend this to regexp.
    463  */
    464 static const struct model_to_vendor_table {
    465 	const char *model;
    466 	const char *vendor;
    467 } model_to_vendor[] = {
    468 	{ "Crucial",		"Micron" },
    469 	{ "Micron",		"Micron" },
    470 	{ "C300-CT",		"Micron" },
    471 	{ "C400-MT",		"Micron" },
    472 	{ "M4-CT",		"Micron" },
    473 	{ "M500",		"Micron" },
    474 	{ "M510",		"Micron" },
    475 	{ "M550",		"Micron" },
    476 	{ "MTFDDA",		"Micron" },
    477 	{ "EEFDDA",		"Micron" },
    478 	{ "INTEL",		"Intel" },
    479 	{ "SAMSUNG",		"Samsung" },
    480 };
    481 
    482 static const struct bitinfo ata_sec_st[] = {
    483 	{ WDC_SEC_SUPP,		"supported" },
    484 	{ WDC_SEC_EN,		"enabled" },
    485 	{ WDC_SEC_LOCKED,	"locked" },
    486 	{ WDC_SEC_FROZEN,	"frozen" },
    487 	{ WDC_SEC_EXP,		"expired" },
    488 	{ WDC_SEC_ESE_SUPP,	"enhanced erase support" },
    489 	{ WDC_SEC_LEV_MAX,	"maximum level" },
    490 	{ 0,			NULL },
    491 };
    492 
    493 int
    494 main(int argc, char *argv[])
    495 {
    496 	int i;
    497 	const struct command *commands = NULL;
    498 
    499 	/* Must have at least: device command */
    500 	if (argc < 3)
    501 		usage();
    502 
    503 	/* Skip program name, get and skip device name and command. */
    504 	dvname = argv[1];
    505 	cmdname = argv[2];
    506 	argv += 3;
    507 	argc -= 3;
    508 
    509 	/*
    510 	 * Open the device
    511 	 */
    512 	fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
    513 	if (fd == -1) {
    514 		if (errno == ENOENT) {
    515 			/*
    516 			 * Device doesn't exist.  Probably trying to open
    517 			 * a device which doesn't use disk semantics for
    518 			 * device name.  Try again, specifying "cooked",
    519 			 * which leaves off the "r" in front of the device's
    520 			 * name.
    521 			 */
    522 			fd = opendisk(dvname, O_RDWR, dvname_store,
    523 			    sizeof(dvname_store), 1);
    524 			if (fd == -1)
    525 				err(1, "%s", dvname);
    526 		} else
    527 			err(1, "%s", dvname);
    528 	}
    529 
    530 	/*
    531 	 * Point the dvname at the actual device name that opendisk() opened.
    532 	 */
    533 	dvname = dvname_store;
    534 
    535 	/* Look up and call the command. */
    536 	for (i = 0; device_commands[i].cmd_name != NULL; i++) {
    537 		if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
    538 			commands = &device_commands[i];
    539 			break;
    540 		}
    541 	}
    542 	if (commands == NULL) {
    543 		for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
    544 			if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
    545 				commands = &bus_commands[i];
    546 				break;
    547 			}
    548 		}
    549 	}
    550 	if (commands == NULL)
    551 		errx(1, "unknown command: %s", cmdname);
    552 
    553 	(*commands->cmd_func)(argc, argv);
    554 	exit(0);
    555 }
    556 
    557 static void
    558 usage(void)
    559 {
    560 	int i;
    561 
    562 	fprintf(stderr, "usage: %s device command [arg [...]]\n",
    563 	    getprogname());
    564 
    565 	fprintf(stderr, "   Available device commands:\n");
    566 	for (i=0; device_commands[i].cmd_name != NULL; i++)
    567 		fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
    568 					    device_commands[i].arg_names);
    569 
    570 	fprintf(stderr, "   Available bus commands:\n");
    571 	for (i=0; bus_commands[i].cmd_name != NULL; i++)
    572 		fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
    573 					    bus_commands[i].arg_names);
    574 
    575 	exit(1);
    576 }
    577 
    578 /*
    579  * Wrapper that calls ATAIOCCOMMAND and checks for errors
    580  */
    581 
    582 static void
    583 ata_command(struct atareq *req)
    584 {
    585 	int error;
    586 
    587 	switch (use_satl) {
    588 	case 0:
    589 		error = ioctl(fd, ATAIOCCOMMAND, req);
    590 		if (error == 0)
    591 			break;
    592 		if (errno != ENOTTY)
    593 			err(1, "ATAIOCCOMMAND failed");
    594 		use_satl = 1;
    595 		/* FALLTHROUGH */
    596 	case 1:
    597 		error = satl_command(req, 16);
    598 		if (error == 0)
    599 			return;
    600 		use_satl = 2;
    601 		/* FALLTHROUGH */
    602 	case 2:
    603 		(void) satl_command(req, 12);
    604 		return;
    605 	}
    606 
    607 	switch (req->retsts) {
    608 
    609 	case ATACMD_OK:
    610 		return;
    611 	case ATACMD_TIMEOUT:
    612 		fprintf(stderr, "ATA command timed out\n");
    613 		exit(1);
    614 	case ATACMD_DF:
    615 		fprintf(stderr, "ATA device returned a Device Fault\n");
    616 		exit(1);
    617 	case ATACMD_ERROR:
    618 		if (req->error & WDCE_ABRT)
    619 			fprintf(stderr, "ATA device returned Aborted "
    620 				"Command\n");
    621 		else
    622 			fprintf(stderr, "ATA device returned error register "
    623 				"%0x\n", req->error);
    624 		exit(1);
    625 	default:
    626 		fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
    627 			"%d\n", req->retsts);
    628 		exit(1);
    629 	}
    630 }
    631 
    632 /*
    633  * Wrapper that calls SCIOCCOMMAND for a tunneled ATA command
    634  */
    635 static int
    636 satl_command(struct atareq *req, int cmdlen)
    637 {
    638 	scsireq_t sreq;
    639 	int error;
    640 	union {
    641 		struct scsi_ata_pass_through_12 cmd12;
    642 		struct scsi_ata_pass_through_16 cmd16;
    643 	} c;
    644 	uint8_t b2, b3;
    645 	const uint8_t *desc;
    646 
    647 	b2 = SATL_NODATA;
    648 	if (req->datalen > 0) {
    649 		if (req->flags & ATACMD_READ)
    650 			b2 = SATL_PIO_IN;
    651 		else
    652 			b2 = SATL_PIO_OUT;
    653 	}
    654 
    655 	b3 = SATL_BLOCKS;
    656 	if (req->datalen > 0) {
    657 		b3 |= 2; /* sector count holds count */
    658 	} else {
    659 		b3 |= SATL_CKCOND;
    660 	}
    661 	if (req->datalen == 0 || req->flags & ATACMD_READ)
    662 		b3 |= SATL_READ;
    663 
    664 	switch (cmdlen) {
    665 	case 16:
    666 		c.cmd16.opcode = SCSI_ATA_PASS_THROUGH_16;
    667 		c.cmd16.byte2 = b2;
    668 		c.cmd16.byte3 = b3;
    669 		c.cmd16.features[0] = 0;
    670 		c.cmd16.features[1] = req->features;
    671 		c.cmd16.sector_count[0] = 0;
    672 		c.cmd16.sector_count[1] = req->sec_count;
    673 		c.cmd16.lba[0] = 0;
    674 		c.cmd16.lba[1] = req->sec_num;
    675 		c.cmd16.lba[2] = 0;
    676 		c.cmd16.lba[3] = req->cylinder;
    677 		c.cmd16.lba[4] = 0;
    678 		c.cmd16.lba[5] = req->cylinder >> 8;
    679 		c.cmd16.device = 0;
    680 		c.cmd16.ata_cmd = req->command;
    681 		c.cmd16.control = 0;
    682 		break;
    683 	case 12:
    684 		c.cmd12.opcode = SCSI_ATA_PASS_THROUGH_12;
    685 		c.cmd12.byte2 = b2;
    686 		c.cmd12.byte3 = b3;
    687 		c.cmd12.features[0] = req->features;
    688 		c.cmd12.sector_count[0] = req->sec_count;
    689 		c.cmd12.lba[0] = req->sec_num;
    690 		c.cmd12.lba[1] = req->cylinder;
    691 		c.cmd12.lba[2] = req->cylinder >> 8;
    692 		c.cmd12.device = 0;
    693 		c.cmd12.reserved = 0;
    694 		c.cmd12.ata_cmd = req->command;
    695 		c.cmd12.control = 0;
    696 		break;
    697 	default:
    698 		fprintf(stderr, "ATA command with bad length\n");
    699 		exit(1);
    700 	}
    701 
    702 	memset(&sreq, 0, sizeof(sreq));
    703 	memcpy(sreq.cmd, &c, cmdlen);
    704 	sreq.cmdlen = cmdlen;
    705 	sreq.databuf = req->databuf;
    706 	sreq.datalen = req->datalen;
    707 	sreq.senselen = sizeof(sreq.sense);
    708 	sreq.timeout = req->timeout;
    709 
    710 	if (sreq.datalen > 0) {
    711 		if (req->flags & ATACMD_READ)
    712 			sreq.flags |= SCCMD_READ;
    713 		if (req->flags & ATACMD_WRITE)
    714 			sreq.flags |= SCCMD_WRITE;
    715 	}
    716 
    717 	error = ioctl(fd, SCIOCCOMMAND, &sreq);
    718 	if (error == -1)
    719 		err(1, "SCIOCCOMMAND failed");
    720 
    721 	req->datalen = sreq.datalen_used;
    722 	req->retsts = ATACMD_OK;
    723 	req->error = 0;
    724 
    725 	switch (sreq.retsts) {
    726 	case SCCMD_OK:
    727 		return 0;
    728 	case SCCMD_TIMEOUT:
    729 		fprintf(stderr, "SATL command timed out\n");
    730 		exit(1);
    731 	case SCCMD_BUSY:
    732 		fprintf(stderr, "SATL command returned busy\n");
    733 		exit(1);
    734 	case SCCMD_SENSE:
    735 		desc = NULL;
    736 		switch (SSD_RCODE(sreq.sense[0])) {
    737 		case 0x00:
    738 			return 0;
    739 		case 0x70:
    740 			if (sreq.sense[2] == SKEY_NO_SENSE)
    741 				return 0;
    742 			if (sreq.sense[2] == SKEY_ILLEGAL_REQUEST)
    743 				return 1;
    744 			break;
    745 		case 0x72:
    746 		case 0x73:
    747 			desc = satl_return_desc(sreq.sense, sreq.senselen_used,
    748 				SCSI_ATA_RETURN_DESCRIPTOR);
    749 			break;
    750 		default:
    751 			break;
    752 		}
    753 
    754 		if (desc && desc[1] >= 12) {
    755 			req->sec_count = desc[5];
    756 			req->sec_num = desc[7];
    757 			req->head = (desc[12] & 0xf0) |
    758 			            ((desc[7] >> 24) & 0x0f);
    759 			req->cylinder = desc[11] << 8 | desc[9];
    760 			req->retsts = desc[13];
    761 			req->error = desc[3];
    762 			return 0;
    763 		}
    764 
    765 		fprintf(stderr, "SATL command error: rcode %02x key %u\n",
    766 			SSD_RCODE(sreq.sense[0]),
    767 			SSD_SENSE_KEY(sreq.sense[2]));
    768 		if (desc) {
    769 			int i, n;
    770 			n = desc[1]+2;
    771 			printf("ATA Return Descriptor:");
    772 			for (i=0; i<n; ++i)
    773 				printf(" %02x",desc[i]);
    774 			printf("\n");
    775 		}
    776 		exit(1);
    777 	default:
    778 		fprintf(stderr, "SCSIIOCCOMMAND returned unknown result code "
    779 			"%d\n", sreq.retsts);
    780 		exit(1);
    781 	}
    782 }
    783 
    784 static const uint8_t *
    785 satl_return_desc(const uint8_t *sense, size_t len, uint8_t type)
    786 {
    787 	const uint8_t *p, *endp;
    788 	size_t l, extra;
    789 
    790 	if (len < 8)
    791 		return NULL;
    792 	extra = sense[7];
    793 	len -= 8;
    794 	if (extra < len)
    795 		len = extra;
    796 	if (len < 2)
    797 		return NULL;
    798 
    799 	switch (sense[0]) {
    800 	case 0x72:
    801 	case 0x73:
    802 		p = &sense[8];
    803 		endp = &p[len-1];
    804 		while (p < endp) {
    805 			if (p[0] == type)
    806 				return p;
    807 			l = p[1];
    808 			p += l + 2;
    809 		}
    810 		break;
    811 	}
    812 
    813 	return NULL;
    814 }
    815 
    816 
    817 /*
    818  * Print out strings associated with particular bitmasks
    819  */
    820 
    821 static void
    822 print_bitinfo(const char *bf, const char *af, u_int bits,
    823     const struct bitinfo *binfo)
    824 {
    825 
    826 	for (; binfo->bitmask != 0; binfo++)
    827 		if (bits & binfo->bitmask)
    828 			printf("%s%s%s", bf, binfo->string, af);
    829 }
    830 
    831 static void
    832 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables,
    833     const struct bitinfo *binfo)
    834 {
    835 
    836 	for (; binfo->bitmask != 0; binfo++)
    837 		if (bits & binfo->bitmask)
    838 			printf("%s%s (%s)%s", bf, binfo->string,
    839 			    (enables & binfo->bitmask) ? "enabled" : "disabled",
    840 			    af);
    841 }
    842 
    843 
    844 /*
    845  * Try to print SMART temperature field
    846  */
    847 
    848 static void
    849 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value)
    850 {
    851 	printf("%" PRIu8, attr->raw[0]);
    852 	if (attr->raw[0] != raw_value)
    853 		printf(" Lifetime min/max %" PRIu8 "/%" PRIu8,
    854 		    attr->raw[2], attr->raw[4]);
    855 }
    856 
    857 /*
    858  * Print out SMART attribute thresholds and values
    859  */
    860 
    861 static void
    862 print_smart_status(void *vbuf, void *tbuf, const char *vendor)
    863 {
    864 	const struct ata_smart_attributes *value_buf = vbuf;
    865 	const struct ata_smart_thresholds *threshold_buf = tbuf;
    866 	const struct ata_smart_attr *attr;
    867 	uint64_t raw_value;
    868 	int flags;
    869 	unsigned i, j;
    870 	unsigned aid, vid;
    871 	uint8_t checksum;
    872 	const struct attr_table *vendor_table = NULL;
    873 	void (*special)(const struct ata_smart_attr *, uint64_t);
    874 
    875 	if (vendor) {
    876 		for (i = 0; i < __arraycount(vendor_smart_names); i++) {
    877 			if (strcasecmp(vendor,
    878 			    vendor_smart_names[i].name) == 0) {
    879 				vendor_table = vendor_smart_names[i].table;
    880 				break;
    881 			}
    882 		}
    883 		if (vendor_table == NULL)
    884 			fprintf(stderr,
    885 			    "SMART vendor '%s' has no special table\n", vendor);
    886 	}
    887 
    888 	for (i = checksum = 0; i < 512; i++)
    889 		checksum += ((const uint8_t *) value_buf)[i];
    890 	if (checksum != 0) {
    891 		fprintf(stderr, "SMART attribute values checksum error\n");
    892 		return;
    893 	}
    894 
    895 	for (i = checksum = 0; i < 512; i++)
    896 		checksum += ((const uint8_t *) threshold_buf)[i];
    897 	if (checksum != 0) {
    898 		fprintf(stderr, "SMART attribute thresholds checksum error\n");
    899 		return;
    900 	}
    901 
    902 	printf("id value thresh crit collect reliability description"
    903 	    "                 raw\n");
    904 	for (i = 0; i < 256; i++) {
    905 		int thresh = 0;
    906 		const char *name = NULL;
    907 
    908 		attr = NULL;
    909 
    910 		for (j = 0; j < 30; j++) {
    911 			if (value_buf->attributes[j].id == i)
    912 				attr = &value_buf->attributes[j];
    913 			if (threshold_buf->thresholds[j].id == i)
    914 				thresh = threshold_buf->thresholds[j].value;
    915 		}
    916 
    917 		if (thresh && attr == NULL)
    918 			errx(1, "threshold but not attr %d", i);
    919 		if (attr == NULL)
    920 			continue;
    921 
    922 		if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
    923 			continue;
    924 
    925 		for (aid = 0;
    926 		     smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
    927 		     aid++)
    928 			;
    929 
    930 		if (vendor_table) {
    931 			for (vid = 0;
    932 			     vendor_table[vid].id != i && vendor_table[vid].id != 0;
    933 			     vid++)
    934 				;
    935 			if (vendor_table[vid].id != 0) {
    936 				name = vendor_table[vid].name;
    937 				special = vendor_table[vid].special;
    938 			}
    939 		}
    940 		if (name == NULL) {
    941 			name = smart_attrs[aid].name;
    942 			special = smart_attrs[aid].special;
    943 		}
    944 
    945 		flags = le16toh(attr->flags);
    946 
    947 		printf("%3d %3d  %3d     %-3s %-7s %stive    %-27s ",
    948 		    i, attr->value, thresh,
    949 		    flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
    950 		    flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
    951 		    attr->value > thresh ? "posi" : "nega", name);
    952 
    953 		for (j = 0, raw_value = 0; j < 6; j++)
    954 			raw_value += ((uint64_t)attr->raw[j]) << (8*j);
    955 
    956 		if (special)
    957 			(*special)(attr, raw_value);
    958 		else
    959 			printf("%" PRIu64, raw_value);
    960 		printf("\n");
    961 	}
    962 }
    963 
    964 static const struct {
    965 	int number;
    966 	const char *name;
    967 } selftest_name[] = {
    968 	{ 0, "Off-line" },
    969 	{ 1, "Short off-line" },
    970 	{ 2, "Extended off-line" },
    971 	{ 127, "Abort off-line test" },
    972 	{ 129, "Short captive" },
    973 	{ 130, "Extended captive" },
    974 	{ 256, "Unknown test" }, /* larger than uint8_t */
    975 	{ 0, NULL }
    976 };
    977 
    978 static const char *selftest_status[] = {
    979 	"No error",
    980 	"Aborted by the host",
    981 	"Interrupted by the host by reset",
    982 	"Fatal error or unknown test error",
    983 	"Unknown test element failed",
    984 	"Electrical test element failed",
    985 	"The Servo (and/or seek) test element failed",
    986 	"Read element of test failed",
    987 	"Reserved",
    988 	"Reserved",
    989 	"Reserved",
    990 	"Reserved",
    991 	"Reserved",
    992 	"Reserved",
    993 	"Reserved",
    994 	"Self-test in progress"
    995 };
    996 
    997 static void
    998 print_error_entry(int num, const struct ata_smart_error *le)
    999 {
   1000 	int i;
   1001 
   1002 	printf("Log entry: %d\n", num);
   1003 
   1004 	for (i = 0; i < 5; i++)
   1005 		printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x "
   1006 		    "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
   1007 		    le->command[i].device_control,
   1008 		    le->command[i].features,
   1009 		    le->command[i].sector_count,
   1010 		    le->command[i].sector_number,
   1011 		    le->command[i].cylinder_low,
   1012 		    le->command[i].cylinder_high,
   1013 		    le->command[i].device_head,
   1014 		    le->command[i].command,
   1015 		    le->command[i].timestamp[3],
   1016 		    le->command[i].timestamp[2],
   1017 		    le->command[i].timestamp[1],
   1018 		    le->command[i].timestamp[0]);
   1019 	printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x "
   1020 	    "status=%02x state=%02x lifetime=%02x%02x\n",
   1021 	    le->error_data.error,
   1022 	    le->error_data.sector_count,
   1023 	    le->error_data.sector_number,
   1024 	    le->error_data.cylinder_low,
   1025 	    le->error_data.cylinder_high,
   1026 	    le->error_data.device_head,
   1027 	    le->error_data.status,
   1028 	    le->error_data.state,
   1029 	    le->error_data.lifetime[1],
   1030 	    le->error_data.lifetime[0]);
   1031 	printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
   1032 	    "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
   1033 	    le->error_data.extended_error[0],
   1034 	    le->error_data.extended_error[1],
   1035 	    le->error_data.extended_error[2],
   1036 	    le->error_data.extended_error[3],
   1037 	    le->error_data.extended_error[4],
   1038 	    le->error_data.extended_error[5],
   1039 	    le->error_data.extended_error[6],
   1040 	    le->error_data.extended_error[7],
   1041 	    le->error_data.extended_error[8],
   1042 	    le->error_data.extended_error[9],
   1043 	    le->error_data.extended_error[10],
   1044 	    le->error_data.extended_error[11],
   1045 	    le->error_data.extended_error[12],
   1046 	    le->error_data.extended_error[13],
   1047 	    le->error_data.extended_error[14],
   1048 	    le->error_data.extended_error[15],
   1049 	    le->error_data.extended_error[15],
   1050 	    le->error_data.extended_error[17],
   1051 	    le->error_data.extended_error[18]);
   1052 }
   1053 
   1054 static void
   1055 print_error(const void *buf)
   1056 {
   1057 	const struct ata_smart_errorlog *erlog = buf;
   1058 	uint8_t checksum;
   1059 	int i;
   1060 
   1061 	for (i = checksum = 0; i < 512; i++)
   1062 		checksum += ((const uint8_t *) buf)[i];
   1063 	if (checksum != 0) {
   1064 		fprintf(stderr, "SMART error log checksum error\n");
   1065 		return;
   1066 	}
   1067 
   1068 	if (erlog->data_structure_revision != 1) {
   1069 		fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
   1070 		    erlog->data_structure_revision);
   1071 		return;
   1072 	}
   1073 
   1074 	if (erlog->mostrecenterror == 0) {
   1075 		printf("No errors have been logged\n");
   1076 		return;
   1077 	}
   1078 
   1079 	if (erlog->mostrecenterror > 5) {
   1080 		fprintf(stderr, "Most recent error is too large\n");
   1081 		return;
   1082 	}
   1083 
   1084 	for (i = erlog->mostrecenterror; i < 5; i++)
   1085 		print_error_entry(i, &erlog->log_entries[i]);
   1086 	for (i = 0; i < erlog->mostrecenterror; i++)
   1087 		print_error_entry(i, &erlog->log_entries[i]);
   1088 	printf("device error count: %d\n", erlog->device_error_count);
   1089 }
   1090 
   1091 static void
   1092 print_selftest_entry(int num, const struct ata_smart_selftest *le)
   1093 {
   1094 	const unsigned char *p;
   1095 	size_t i;
   1096 
   1097 	/* check if all zero */
   1098 	for (p = (const void *)le, i = 0; i < sizeof(*le); i++)
   1099 		if (p[i] != 0)
   1100 			break;
   1101 	if (i == sizeof(*le))
   1102 		return;
   1103 
   1104 	printf("Log entry: %d\n", num);
   1105 
   1106 	/* Get test name */
   1107 	for (i = 0; selftest_name[i].name != NULL; i++)
   1108 		if (selftest_name[i].number == le->number)
   1109 			break;
   1110 
   1111 	if (selftest_name[i].name == NULL)
   1112 		printf("\tName: (%d)\n", le->number);
   1113 	else
   1114 		printf("\tName: %s\n", selftest_name[i].name);
   1115 	printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
   1116 	/* XXX This generally should not be set when a self-test is completed,
   1117 	   and at any rate is useless.  - mycroft */
   1118 	if (le->status >> 4 == 15)
   1119 		printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
   1120 	else if (le->status >> 4 != 0)
   1121 		printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
   1122 }
   1123 
   1124 static void
   1125 print_selftest(const void *buf)
   1126 {
   1127 	const struct ata_smart_selftestlog *stlog = buf;
   1128 	uint8_t checksum;
   1129 	int i;
   1130 
   1131 	for (i = checksum = 0; i < 512; i++)
   1132 		checksum += ((const uint8_t *) buf)[i];
   1133 	if (checksum != 0) {
   1134 		fprintf(stderr, "SMART selftest log checksum error\n");
   1135 		return;
   1136 	}
   1137 
   1138 	if (le16toh(stlog->data_structure_revision) != 1) {
   1139 		fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
   1140 		    le16toh(stlog->data_structure_revision));
   1141 		return;
   1142 	}
   1143 
   1144 	if (stlog->mostrecenttest == 0) {
   1145 		printf("No self-tests have been logged\n");
   1146 		return;
   1147 	}
   1148 
   1149 	if (stlog->mostrecenttest > 22) {
   1150 		fprintf(stderr, "Most recent test is too large\n");
   1151 		return;
   1152 	}
   1153 
   1154 	for (i = stlog->mostrecenttest; i < 22; i++)
   1155 		print_selftest_entry(i, &stlog->log_entries[i]);
   1156 	for (i = 0; i < stlog->mostrecenttest; i++)
   1157 		print_selftest_entry(i, &stlog->log_entries[i]);
   1158 }
   1159 
   1160 static void
   1161 fillataparams(void)
   1162 {
   1163 	struct atareq req;
   1164 	static union {
   1165 		unsigned char inbuf[DEV_BSIZE];
   1166 		struct ataparams inqbuf;
   1167 	} inbuf;
   1168 	static int first = 1;
   1169 
   1170 	if (!first)
   1171 		return;
   1172 	first = 0;
   1173 
   1174 	memset(&inbuf, 0, sizeof(inbuf));
   1175 	memset(&req, 0, sizeof(req));
   1176 
   1177 	req.flags = ATACMD_READ;
   1178 	req.command = WDCC_IDENTIFY;
   1179 	req.databuf = &inbuf;
   1180 	req.datalen = sizeof(inbuf);
   1181 	req.timeout = 1000;
   1182 
   1183 	ata_command(&req);
   1184 
   1185 	inqbuf = &inbuf.inqbuf;
   1186 }
   1187 
   1188 /*
   1189  * is_smart:
   1190  *
   1191  *	Detect whether device supports SMART and SMART is enabled.
   1192  */
   1193 
   1194 static int
   1195 is_smart(void)
   1196 {
   1197 	int retval = 0;
   1198 	const char *status;
   1199 
   1200 	fillataparams();
   1201 
   1202 	if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
   1203 		if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
   1204 			fprintf(stderr, "SMART unsupported\n");
   1205 		} else {
   1206 			if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
   1207 			    inqbuf->atap_cmd_set2 == 0xffff ||
   1208 			    inqbuf->atap_cmd_set2 == 0x0000) {
   1209 				status = "status unknown";
   1210 				retval = 2;
   1211 			} else {
   1212 				if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
   1213 					status = "enabled";
   1214 					retval = 1;
   1215 				} else {
   1216 					status = "disabled";
   1217 					retval = 3;
   1218 				}
   1219 			}
   1220 			printf("SMART supported, SMART %s\n", status);
   1221 		}
   1222 	}
   1223 	return retval;
   1224 }
   1225 
   1226 /*
   1227  * extract_string: copy a block of bytes out of ataparams and make
   1228  * a proper string out of it, truncating trailing spaces and preserving
   1229  * strict typing. And also, not doing unaligned accesses.
   1230  */
   1231 static void
   1232 extract_string(char *buf, size_t bufmax,
   1233 	       const uint8_t *bytes, size_t numbytes,
   1234 	       int needswap)
   1235 {
   1236 	unsigned i;
   1237 	size_t j;
   1238 	unsigned char ch1, ch2;
   1239 
   1240 	for (i = 0, j = 0; i < numbytes; i += 2) {
   1241 		ch1 = bytes[i];
   1242 		ch2 = bytes[i+1];
   1243 		if (needswap && j < bufmax-1) {
   1244 			buf[j++] = ch2;
   1245 		}
   1246 		if (j < bufmax-1) {
   1247 			buf[j++] = ch1;
   1248 		}
   1249 		if (!needswap && j < bufmax-1) {
   1250 			buf[j++] = ch2;
   1251 		}
   1252 	}
   1253 	while (j > 0 && buf[j-1] == ' ') {
   1254 		j--;
   1255 	}
   1256 	buf[j] = '\0';
   1257 }
   1258 
   1259 static void
   1260 compute_capacity(uint64_t *capacityp, uint64_t *sectorsp, uint32_t *secsizep)
   1261 {
   1262 	uint64_t capacity;
   1263 	uint64_t sectors;
   1264 	uint32_t secsize;
   1265 
   1266 	if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
   1267 	    inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
   1268 		sectors =
   1269 		    ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
   1270 		    ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
   1271 		    ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
   1272 		    ((uint64_t)inqbuf->atap_max_lba[0] <<  0);
   1273 	} else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
   1274 		sectors = (inqbuf->atap_capacity[1] << 16) |
   1275 		    inqbuf->atap_capacity[0];
   1276 	} else {
   1277 		sectors = inqbuf->atap_cylinders *
   1278 		    inqbuf->atap_heads * inqbuf->atap_sectors;
   1279 	}
   1280 
   1281 	secsize = 512;
   1282 
   1283 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
   1284 		if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
   1285 			secsize = 2 *		/* words to bytes */
   1286 			    (inqbuf->atap_lls_secsz[1] << 16 |
   1287 			    inqbuf->atap_lls_secsz[0] <<  0);
   1288 		}
   1289 	}
   1290 
   1291 	capacity = sectors * secsize;
   1292 
   1293 	if (capacityp)
   1294 		*capacityp = capacity;
   1295 	if (sectorsp)
   1296 		*sectorsp = sectors;
   1297 	if (secsizep)
   1298 		*secsizep = secsize;
   1299 }
   1300 
   1301 /*
   1302  * Inspect the inqbuf and guess what vendor to use.  This list is fairly
   1303  * basic, and probably should be converted into a regexp scheme.
   1304  */
   1305 static const char *
   1306 guess_vendor(void)
   1307 {
   1308 
   1309 	unsigned i;
   1310 
   1311 	for (i = 0; i < __arraycount(model_to_vendor); i++)
   1312 		if (strncasecmp(model, model_to_vendor[i].model,
   1313 				strlen(model_to_vendor[i].model)) == 0)
   1314 			return model_to_vendor[i].vendor;
   1315 
   1316 	return NULL;
   1317 }
   1318 
   1319 /*
   1320  * identify_fixup() - Given an obtained ataparams, fix up the endian and
   1321  * other issues before using them.
   1322  */
   1323 static void
   1324 identify_fixup(void)
   1325 {
   1326 	int needswap = 0;
   1327 
   1328 	if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) ==
   1329 	    WDC_INTEGRITY_MAGIC) {
   1330 		int i;
   1331 		uint8_t checksum;
   1332 
   1333 		for (i = checksum = 0; i < 512; i++)
   1334 			checksum += ((const uint8_t *)inqbuf)[i];
   1335 		if (checksum != 0)
   1336 			puts("IDENTIFY DEVICE data checksum invalid\n");
   1337 	}
   1338 
   1339 #if BYTE_ORDER == LITTLE_ENDIAN
   1340 	/*
   1341 	 * On little endian machines, we need to shuffle the string
   1342 	 * byte order.  However, we don't have to do this for NEC or
   1343 	 * Mitsumi ATAPI devices
   1344 	 */
   1345 
   1346 	if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC &&
   1347 	      (inqbuf->atap_config & WDC_CFG_ATAPI) &&
   1348 	      ((inqbuf->atap_model[0] == 'N' &&
   1349 		  inqbuf->atap_model[1] == 'E') ||
   1350 	       (inqbuf->atap_model[0] == 'F' &&
   1351 		  inqbuf->atap_model[1] == 'X')))) {
   1352 		needswap = 1;
   1353 	}
   1354 #endif
   1355 
   1356 	/*
   1357 	 * Copy the info strings out, stripping off blanks.
   1358 	 */
   1359 	extract_string(model, sizeof(model),
   1360 		inqbuf->atap_model, sizeof(inqbuf->atap_model),
   1361 		needswap);
   1362 	extract_string(revision, sizeof(revision),
   1363 		inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
   1364 		needswap);
   1365 	extract_string(serial, sizeof(serial),
   1366 		inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
   1367 		needswap);
   1368 
   1369 }
   1370 
   1371 /*
   1372  * DEVICE COMMANDS
   1373  */
   1374 
   1375 /*
   1376  * device_identify:
   1377  *
   1378  *	Display the identity of the device
   1379  */
   1380 static void
   1381 device_identify(int argc, char *argv[])
   1382 {
   1383 	char hnum[12];
   1384 	uint64_t capacity;
   1385 	uint64_t sectors;
   1386 	uint32_t secsize;
   1387 	int lb_per_pb;
   1388 
   1389 	/* No arguments. */
   1390 	if (argc != 0)
   1391 		usage();
   1392 
   1393 	fillataparams();
   1394 	identify_fixup();
   1395 
   1396 	printf("Model: %s, Rev: %s, Serial #: %s\n",
   1397 		model, revision, serial);
   1398 
   1399 	if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff &&
   1400 	    inqbuf->atap_cmd_ext & ATA_CMDE_WWN)
   1401 		printf("World Wide Name: %016" PRIX64 "\n",
   1402 		    ((uint64_t)inqbuf->atap_wwn[0] << 48) |
   1403 		    ((uint64_t)inqbuf->atap_wwn[1] << 32) |
   1404 		    ((uint64_t)inqbuf->atap_wwn[2] << 16) |
   1405 		    ((uint64_t)inqbuf->atap_wwn[3] <<  0));
   1406 
   1407 	printf("Device type: %s",
   1408 		inqbuf->atap_config == WDC_CFG_CFA_MAGIC ? "CF-ATA" :
   1409 		 (inqbuf->atap_config & WDC_CFG_ATAPI ? "ATAPI" : "ATA"));
   1410 	if (inqbuf->atap_config != WDC_CFG_CFA_MAGIC)
   1411 		printf(", %s",
   1412 		 inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");
   1413 	printf("\n");
   1414 
   1415 	compute_capacity(&capacity, &sectors, &secsize);
   1416 
   1417 	humanize_number(hnum, sizeof(hnum), capacity, "bytes",
   1418 		HN_AUTOSCALE, HN_DIVISOR_1000);
   1419 
   1420 	printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n",
   1421 		       hnum, sectors, secsize);
   1422 
   1423 	printf("Cylinders: %d, heads: %d, sec/track: %d\n",
   1424 		inqbuf->atap_cylinders, inqbuf->atap_heads,
   1425 		inqbuf->atap_sectors);
   1426 
   1427 	lb_per_pb = 1;
   1428 
   1429 	if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
   1430 		if (inqbuf->atap_secsz & ATA_SECSZ_LPS) {
   1431 			lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK;
   1432 			printf("Physical sector size: %d bytes\n",
   1433 			    lb_per_pb * secsize);
   1434 			if ((inqbuf->atap_logical_align &
   1435 			    ATA_LA_VALID_MASK) == ATA_LA_VALID) {
   1436 				printf("First physically aligned sector: %d\n",
   1437 				    inqbuf->atap_logical_align & ATA_LA_MASK);
   1438 			}
   1439 		}
   1440 	}
   1441 
   1442 	if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) ||
   1443 	    (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) &&
   1444 	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
   1445 		printf("Command queue depth: %d\n",
   1446 		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
   1447 
   1448 	printf("Device capabilities:\n");
   1449 	print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
   1450 
   1451 	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
   1452 		printf("Device supports following standards:\n");
   1453 		print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
   1454 		printf("\n");
   1455 	}
   1456 
   1457 	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
   1458 	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
   1459 		printf("Command set support:\n");
   1460 		if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
   1461 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
   1462 			    inqbuf->atap_cmd1_en, ata_cmd_set1);
   1463 		else
   1464 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
   1465 			    ata_cmd_set1);
   1466 		if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
   1467 			print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
   1468 			    inqbuf->atap_cmd2_en, ata_cmd_set2);
   1469 		else
   1470 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
   1471 			    ata_cmd_set2);
   1472 		if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
   1473 			print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
   1474 			    ata_cmd_ext);
   1475 	}
   1476 
   1477 	if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
   1478 		printf("Serial ATA capabilities:\n");
   1479 		print_bitinfo("\t", "\n",
   1480 		    inqbuf->atap_sata_caps, ata_sata_caps);
   1481 
   1482 	}
   1483 
   1484 	if (inqbuf->atap_sata_features_supp != 0 &&
   1485 	    inqbuf->atap_sata_features_supp != 0xffff) {
   1486 		printf("Serial ATA features:\n");
   1487 		if (inqbuf->atap_sata_features_en != 0 &&
   1488 		    inqbuf->atap_sata_features_en != 0xffff)
   1489 			print_bitinfo2("\t", "\n",
   1490 			    inqbuf->atap_sata_features_supp,
   1491 			    inqbuf->atap_sata_features_en, ata_sata_feat);
   1492 		else
   1493 			print_bitinfo("\t", "\n",
   1494 			    inqbuf->atap_sata_features_supp, ata_sata_feat);
   1495 	}
   1496 
   1497 	if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&
   1498 	    (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
   1499 		printf("TRIM supported\n");
   1500 
   1501 	return;
   1502 }
   1503 
   1504 /*
   1505  * device idle:
   1506  *
   1507  * issue the IDLE IMMEDIATE command to the drive
   1508  */
   1509 static void
   1510 device_idle(int argc, char *argv[])
   1511 {
   1512 	struct atareq req;
   1513 
   1514 	/* No arguments. */
   1515 	if (argc != 0)
   1516 		usage();
   1517 
   1518 	memset(&req, 0, sizeof(req));
   1519 
   1520 	if (strcmp(cmdname, "idle") == 0)
   1521 		req.command = WDCC_IDLE_IMMED;
   1522 	else if (strcmp(cmdname, "standby") == 0)
   1523 		req.command = WDCC_STANDBY_IMMED;
   1524 	else
   1525 		req.command = WDCC_SLEEP;
   1526 
   1527 	req.timeout = 1000;
   1528 
   1529 	ata_command(&req);
   1530 
   1531 	return;
   1532 }
   1533 
   1534 /*
   1535  * device apm:
   1536  *
   1537  * enable/disable/control the APM feature of the drive
   1538  */
   1539 static void
   1540 device_apm(int argc, char *argv[])
   1541 {
   1542 	struct atareq req;
   1543 	long l;
   1544 
   1545 	memset(&req, 0, sizeof(req));
   1546 	if (argc >= 1) {
   1547 		req.command = SET_FEATURES;
   1548 		req.timeout = 1000;
   1549 
   1550 		if (strcmp(argv[0], "disable") == 0)
   1551 			req.features = WDSF_APM_DS;
   1552 		else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
   1553 		         (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
   1554 
   1555 			req.features = WDSF_APM_EN;
   1556 			req.sec_count = l + 1;
   1557 		} else
   1558 			usage();
   1559 	} else
   1560 		usage();
   1561 
   1562 	ata_command(&req);
   1563 }
   1564 
   1565 
   1566 /*
   1567  * Set the idle timer on the disk.  Set it for either idle mode or
   1568  * standby mode, depending on how we were invoked.
   1569  */
   1570 
   1571 static void
   1572 device_setidle(int argc, char *argv[])
   1573 {
   1574 	unsigned long idle;
   1575 	struct atareq req;
   1576 	char *end;
   1577 
   1578 	/* Only one argument */
   1579 	if (argc != 1)
   1580 		usage();
   1581 
   1582 	idle = strtoul(argv[0], &end, 0);
   1583 
   1584 	if (*end != '\0') {
   1585 		fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
   1586 		exit(1);
   1587 	}
   1588 
   1589 	if (idle > 19800) {
   1590 		fprintf(stderr, "Idle time has a maximum value of 5.5 "
   1591 			"hours\n");
   1592 		exit(1);
   1593 	}
   1594 
   1595 	if (idle != 0 && idle < 5) {
   1596 		fprintf(stderr, "Idle timer must be at least 5 seconds\n");
   1597 		exit(1);
   1598 	}
   1599 
   1600 	memset(&req, 0, sizeof(req));
   1601 
   1602 	if (idle <= 240*5)
   1603 		req.sec_count = idle / 5;
   1604 	else
   1605 		req.sec_count = idle / (30*60) + 240;
   1606 
   1607 	req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
   1608 	req.timeout = 1000;
   1609 
   1610 	ata_command(&req);
   1611 
   1612 	return;
   1613 }
   1614 
   1615 /*
   1616  * Query the device for the current power mode
   1617  */
   1618 
   1619 static void
   1620 device_checkpower(int argc, char *argv[])
   1621 {
   1622 	struct atareq req;
   1623 
   1624 	/* No arguments. */
   1625 	if (argc != 0)
   1626 		usage();
   1627 
   1628 	memset(&req, 0, sizeof(req));
   1629 
   1630 	req.command = WDCC_CHECK_PWR;
   1631 	req.timeout = 1000;
   1632 	req.flags = ATACMD_READREG;
   1633 
   1634 	ata_command(&req);
   1635 
   1636 	printf("Current power status: ");
   1637 
   1638 	switch (req.sec_count) {
   1639 	case 0x00:
   1640 		printf("Standby mode\n");
   1641 		break;
   1642 	case 0x80:
   1643 		printf("Idle mode\n");
   1644 		break;
   1645 	case 0xff:
   1646 		printf("Active mode\n");
   1647 		break;
   1648 	default:
   1649 		printf("Unknown power code (%02x)\n", req.sec_count);
   1650 	}
   1651 
   1652 	return;
   1653 }
   1654 
   1655 /*
   1656  * device_smart:
   1657  *
   1658  *	Display SMART status
   1659  */
   1660 static void
   1661 device_smart(int argc, char *argv[])
   1662 {
   1663 	struct atareq req;
   1664 	unsigned char inbuf[DEV_BSIZE];
   1665 	unsigned char inbuf2[DEV_BSIZE];
   1666 
   1667 	if (argc < 1)
   1668 		usage();
   1669 
   1670 	if (strcmp(argv[0], "enable") == 0) {
   1671 		memset(&req, 0, sizeof(req));
   1672 
   1673 		req.features = WDSM_ENABLE_OPS;
   1674 		req.command = WDCC_SMART;
   1675 		req.cylinder = WDSMART_CYL;
   1676 		req.timeout = 1000;
   1677 
   1678 		ata_command(&req);
   1679 
   1680 		is_smart();
   1681 	} else if (strcmp(argv[0], "disable") == 0) {
   1682 		memset(&req, 0, sizeof(req));
   1683 
   1684 		req.features = WDSM_DISABLE_OPS;
   1685 		req.command = WDCC_SMART;
   1686 		req.cylinder = WDSMART_CYL;
   1687 		req.timeout = 1000;
   1688 
   1689 		ata_command(&req);
   1690 
   1691 		is_smart();
   1692 	} else if (strcmp(argv[0], "status") == 0) {
   1693 		int rv;
   1694 		const char *vendor = argc > 1 ? argv[1] : NULL;
   1695 
   1696 		rv = is_smart();
   1697 
   1698 		if (!rv) {
   1699 			fprintf(stderr, "SMART not supported\n");
   1700 			return;
   1701 		} else if (rv == 3)
   1702 			return;
   1703 
   1704 		memset(&inbuf, 0, sizeof(inbuf));
   1705 		memset(&req, 0, sizeof(req));
   1706 
   1707 		req.features = WDSM_STATUS;
   1708 		req.command = WDCC_SMART;
   1709 		req.cylinder = WDSMART_CYL;
   1710 		req.timeout = 1000;
   1711 
   1712 		ata_command(&req);
   1713 
   1714 		if (req.cylinder != WDSMART_CYL) {
   1715 			fprintf(stderr, "Threshold exceeds condition\n");
   1716 		}
   1717 
   1718 		/* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
   1719 		 * features, the following ata_command()'s may error
   1720 		 * and exit().
   1721 		 */
   1722 
   1723 		memset(&inbuf, 0, sizeof(inbuf));
   1724 		memset(&req, 0, sizeof(req));
   1725 
   1726 		req.flags = ATACMD_READ;
   1727 		req.features = WDSM_RD_DATA;
   1728 		req.command = WDCC_SMART;
   1729 		req.databuf = (caddr_t) inbuf;
   1730 		req.datalen = sizeof(inbuf);
   1731 		req.cylinder = WDSMART_CYL;
   1732 		req.timeout = 1000;
   1733 
   1734 		ata_command(&req);
   1735 
   1736 		memset(&inbuf2, 0, sizeof(inbuf2));
   1737 		memset(&req, 0, sizeof(req));
   1738 
   1739 		req.flags = ATACMD_READ;
   1740 		req.features = WDSM_RD_THRESHOLDS;
   1741 		req.command = WDCC_SMART;
   1742 		req.databuf = (caddr_t) inbuf2;
   1743 		req.datalen = sizeof(inbuf2);
   1744 		req.cylinder = WDSMART_CYL;
   1745 		req.timeout = 1000;
   1746 
   1747 		ata_command(&req);
   1748 
   1749 		if (!vendor || strcmp(vendor, "noauto") == 0) {
   1750 			fillataparams();
   1751 			identify_fixup();
   1752 			vendor = guess_vendor();
   1753 		}
   1754 		print_smart_status(inbuf, inbuf2, vendor);
   1755 
   1756 	} else if (strcmp(argv[0], "offline") == 0) {
   1757 		if (argc != 2)
   1758 			usage();
   1759 		if (!is_smart()) {
   1760 			fprintf(stderr, "SMART not supported\n");
   1761 			return;
   1762 		}
   1763 
   1764 		memset(&req, 0, sizeof(req));
   1765 
   1766 		req.features = WDSM_EXEC_OFFL_IMM;
   1767 		req.command = WDCC_SMART;
   1768 		req.cylinder = WDSMART_CYL;
   1769 		req.sec_num = atol(argv[1]);
   1770 		req.timeout = 10000;
   1771 
   1772 		ata_command(&req);
   1773 	} else if (strcmp(argv[0], "error-log") == 0) {
   1774 		if (!is_smart()) {
   1775 			fprintf(stderr, "SMART not supported\n");
   1776 			return;
   1777 		}
   1778 
   1779 		memset(&inbuf, 0, sizeof(inbuf));
   1780 		memset(&req, 0, sizeof(req));
   1781 
   1782 		req.flags = ATACMD_READ;
   1783 		req.features = WDSM_RD_LOG;
   1784 		req.sec_count = 1;
   1785 		req.sec_num = 1;
   1786 		req.command = WDCC_SMART;
   1787 		req.databuf = (caddr_t) inbuf;
   1788 		req.datalen = sizeof(inbuf);
   1789 		req.cylinder = WDSMART_CYL;
   1790 		req.timeout = 1000;
   1791 
   1792 		ata_command(&req);
   1793 
   1794 		print_error(inbuf);
   1795 	} else if (strcmp(argv[0], "selftest-log") == 0) {
   1796 		if (!is_smart()) {
   1797 			fprintf(stderr, "SMART not supported\n");
   1798 			return;
   1799 		}
   1800 
   1801 		memset(&inbuf, 0, sizeof(inbuf));
   1802 		memset(&req, 0, sizeof(req));
   1803 
   1804 		req.flags = ATACMD_READ;
   1805 		req.features = WDSM_RD_LOG;
   1806 		req.sec_count = 1;
   1807 		req.sec_num = 6;
   1808 		req.command = WDCC_SMART;
   1809 		req.databuf = (caddr_t) inbuf;
   1810 		req.datalen = sizeof(inbuf);
   1811 		req.cylinder = WDSMART_CYL;
   1812 		req.timeout = 1000;
   1813 
   1814 		ata_command(&req);
   1815 
   1816 		print_selftest(inbuf);
   1817 
   1818 	} else {
   1819 		usage();
   1820 	}
   1821 	return;
   1822 }
   1823 
   1824 static void
   1825 device_security(int argc, char *argv[])
   1826 {
   1827 	struct atareq req;
   1828 	unsigned char data[DEV_BSIZE];
   1829 	char *pass;
   1830 
   1831 	/* need subcommand */
   1832 	if (argc < 1)
   1833 		usage();
   1834 
   1835 	memset(&req, 0, sizeof(req));
   1836 	if (strcmp(argv[0], "status") == 0) {
   1837 		fillataparams();
   1838 		print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
   1839 	} else if (strcmp(argv[0], "freeze") == 0) {
   1840 		req.command = WDCC_SECURITY_FREEZE;
   1841 		req.timeout = 1000;
   1842 		ata_command(&req);
   1843 	} else if ((strcmp(argv[0], "setpass") == 0) ||
   1844 	    (strcmp(argv[0], "unlock") == 0) ||
   1845 	    (strcmp(argv[0], "disable") == 0) ||
   1846 	    (strcmp(argv[0], "erase") == 0)) {
   1847 		if (argc != 2)
   1848 			usage();
   1849 		if (strcmp(argv[1], "user") != 0) {
   1850 			if (strcmp(argv[1], "master") == 0) {
   1851 				fprintf(stderr,
   1852 				    "Master passwords not supported\n");
   1853 				exit(1);
   1854 			} else {
   1855 				usage();
   1856 			}
   1857 		}
   1858 
   1859 		pass = getpass("Password:");
   1860 		if (strlen(pass) > 32) {
   1861 			fprintf(stderr, "Password must be <=32 characters\n");
   1862 			exit(1);
   1863 		}
   1864 
   1865 		req.flags |= ATACMD_WRITE;
   1866 		req.timeout = 1000;
   1867 		req.databuf = data;
   1868 		req.datalen = sizeof(data);
   1869 		memset(data, 0, sizeof(data));
   1870 		strlcpy((void *)&data[2], pass, 32 + 1);
   1871 
   1872 		if (strcmp(argv[0], "setpass") == 0) {
   1873 			char orig[32 + 1];
   1874 			strlcpy(orig, pass, 32 + 1);
   1875 			pass = getpass("Confirm password:");
   1876 			if (0 != strcmp(orig, pass)) {
   1877 				fprintf(stderr, "Passwords do not match\n");
   1878 				exit(1);
   1879 			}
   1880 			req.command = WDCC_SECURITY_SET_PASSWORD;
   1881 		} else if (strcmp(argv[0], "unlock") == 0) {
   1882 			req.command = WDCC_SECURITY_UNLOCK;
   1883 		} else if (strcmp(argv[0], "disable") == 0) {
   1884 			req.command = WDCC_SECURITY_DISABLE_PASSWORD;
   1885 		} else if (strcmp(argv[0], "erase") == 0) {
   1886 			struct atareq prepare;
   1887 
   1888 			fillataparams();
   1889 
   1890 			/*
   1891 			 * XXX Any way to lock the device to make sure
   1892 			 * this really is the command preceding the
   1893 			 * SECURITY ERASE UNIT command?  This would
   1894 			 * probably have to be moved into the kernel to
   1895 			 * do that.
   1896 			 */
   1897 			memset(&prepare, 0, sizeof(prepare));
   1898 			prepare.command = WDCC_SECURITY_ERASE_PREPARE;
   1899 			prepare.timeout = 1000;
   1900 			ata_command(&prepare);
   1901 
   1902 			req.command = WDCC_SECURITY_ERASE_UNIT;
   1903 
   1904 			/*
   1905 			 * Enable enhanced erase if it's supported.
   1906 			 *
   1907 			 * XXX should be a command-line option
   1908 			 */
   1909 			if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {
   1910 				data[0] |= 0x2;
   1911 				req.timeout = (inqbuf->atap_eseu_time & 0xff)
   1912 				    * 2 * 60 * 1000;
   1913 			} else {
   1914 				req.timeout = (inqbuf->atap_seu_time & 0xff)
   1915 				    * 2 * 60 * 1000;
   1916 			}
   1917 
   1918 			/*
   1919 			 * If the estimated time was 0xff (* 2 * 60 *
   1920 			 * 1000 = 30600000), that means `>508 minutes'.
   1921 			 * Estimate that we can handle 16 MB/sec, a
   1922 			 * rate I just pulled out of my arse.
   1923 			 */
   1924 			if (req.timeout == 30600000) {
   1925 				uint64_t bytes, timeout;
   1926 				compute_capacity(&bytes, NULL, NULL);
   1927 				timeout = (bytes / (16 * 1024 * 1024)) * 1000;
   1928 				if (timeout > (uint64_t)INT_MAX)
   1929 					req.timeout = INT_MAX;
   1930 				else
   1931 					req.timeout = timeout;
   1932 			}
   1933 
   1934 			printf("Erasing may take up to %dh %dm %ds...\n",
   1935 			    (req.timeout / 1000 / 60) / 60,
   1936 			    (req.timeout / 1000 / 60) % 60,
   1937 			    req.timeout % 60);
   1938 		} else {
   1939 			abort();
   1940 		}
   1941 
   1942 		ata_command(&req);
   1943 	} else {
   1944 		usage();
   1945 	}
   1946 }
   1947 
   1948 /*
   1949  * bus_reset:
   1950  *	Reset an ATA bus (will reset all devices on the bus)
   1951  */
   1952 static void
   1953 bus_reset(int argc, char *argv[])
   1954 {
   1955 	int error;
   1956 
   1957 	/* no args */
   1958 	if (argc != 0)
   1959 		usage();
   1960 
   1961 	error = ioctl(fd, ATABUSIORESET, NULL);
   1962 
   1963 	if (error == -1)
   1964 		err(1, "ATABUSIORESET failed");
   1965 }
   1966