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