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