1 /* $NetBSD: atactl.c,v 1.53 2009/03/16 12:52:32 lukem 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.53 2009/03/16 12:52:32 lukem 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)]; 860 char revision[sizeof(inqbuf->atap_revision)]; 861 char serial[sizeof(inqbuf->atap_serial)]; 862 int needswap = 0; 863 864 /* No arguments. */ 865 if (argc != 0) 866 usage(); 867 868 inqbuf = getataparams(); 869 870 #if BYTE_ORDER == LITTLE_ENDIAN 871 /* 872 * On little endian machines, we need to shuffle the string 873 * byte order. However, we don't have to do this for NEC or 874 * Mitsumi ATAPI devices 875 */ 876 877 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 878 ((inqbuf->atap_model[0] == 'N' && 879 inqbuf->atap_model[1] == 'E') || 880 (inqbuf->atap_model[0] == 'F' && 881 inqbuf->atap_model[1] == 'X')))) { 882 needswap = 1; 883 } 884 #endif 885 886 /* 887 * Copy the info strings out, stripping off blanks. 888 */ 889 extract_string(model, sizeof(model), 890 inqbuf->atap_model, sizeof(inqbuf->atap_model), 891 needswap); 892 extract_string(revision, sizeof(revision), 893 inqbuf->atap_revision, sizeof(inqbuf->atap_revision), 894 needswap); 895 extract_string(serial, sizeof(serial), 896 inqbuf->atap_serial, sizeof(inqbuf->atap_serial), 897 needswap); 898 899 printf("Model: %s, Rev: %s, Serial #: %s\n", 900 model, revision, serial); 901 902 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 903 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 904 "removable"); 905 906 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0) 907 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 908 "sectors: %d\n", inqbuf->atap_cylinders, 909 inqbuf->atap_heads, inqbuf->atap_sectors, 910 (inqbuf->atap_capacity[1] << 16) | 911 inqbuf->atap_capacity[0]); 912 913 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) 914 printf("Device supports command queue depth of %d\n", 915 inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK); 916 917 printf("Device capabilities:\n"); 918 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 919 920 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 921 printf("Device supports following standards:\n"); 922 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 923 printf("\n"); 924 } 925 926 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 927 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 928 printf("Command set support:\n"); 929 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 930 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 931 inqbuf->atap_cmd1_en, ata_cmd_set1); 932 else 933 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 934 ata_cmd_set1); 935 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 936 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 937 inqbuf->atap_cmd2_en, ata_cmd_set2); 938 else 939 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 940 ata_cmd_set2); 941 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 942 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 943 ata_cmd_ext); 944 } 945 946 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) { 947 printf("Serial ATA capabilities:\n"); 948 print_bitinfo("\t", "\n", inqbuf->atap_sata_caps, ata_sata_caps); 949 } 950 951 if (inqbuf->atap_sata_features_supp != 0 && inqbuf->atap_sata_features_supp != 0xffff) { 952 printf("Serial ATA features:\n"); 953 if (inqbuf->atap_sata_features_en != 0 && inqbuf->atap_sata_features_en != 0xffff) 954 print_bitinfo2("\t", "\n", inqbuf->atap_sata_features_supp, inqbuf->atap_sata_features_en, ata_sata_feat); 955 else 956 print_bitinfo("\t", "\n", inqbuf->atap_sata_features_supp, ata_sata_feat); 957 } 958 959 return; 960 } 961 962 /* 963 * device idle: 964 * 965 * issue the IDLE IMMEDIATE command to the drive 966 */ 967 void 968 device_idle(int argc, char *argv[]) 969 { 970 struct atareq req; 971 972 /* No arguments. */ 973 if (argc != 0) 974 usage(); 975 976 memset(&req, 0, sizeof(req)); 977 978 if (strcmp(cmdname, "idle") == 0) 979 req.command = WDCC_IDLE_IMMED; 980 else if (strcmp(cmdname, "standby") == 0) 981 req.command = WDCC_STANDBY_IMMED; 982 else 983 req.command = WDCC_SLEEP; 984 985 req.timeout = 1000; 986 987 ata_command(&req); 988 989 return; 990 } 991 992 /* 993 * device apm: 994 * 995 * enable/disable/control the APM feature of the drive 996 */ 997 void 998 device_apm(int argc, char *argv[]) 999 { 1000 struct atareq req; 1001 long l; 1002 1003 memset(&req, 0, sizeof(req)); 1004 if (argc >= 1) { 1005 req.command = SET_FEATURES; 1006 req.timeout = 1000; 1007 1008 if (strcmp(argv[0], "disable") == 0) 1009 req.features = WDSF_APM_DS; 1010 else if (strcmp(argv[0], "set") == 0 && argc >= 2 && 1011 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) { 1012 1013 req.features = WDSF_APM_EN; 1014 req.sec_count = l + 1; 1015 } else 1016 usage(); 1017 } else 1018 usage(); 1019 1020 ata_command(&req); 1021 } 1022 1023 1024 /* 1025 * Set the idle timer on the disk. Set it for either idle mode or 1026 * standby mode, depending on how we were invoked. 1027 */ 1028 1029 void 1030 device_setidle(int argc, char *argv[]) 1031 { 1032 unsigned long idle; 1033 struct atareq req; 1034 char *end; 1035 1036 /* Only one argument */ 1037 if (argc != 1) 1038 usage(); 1039 1040 idle = strtoul(argv[0], &end, 0); 1041 1042 if (*end != '\0') { 1043 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 1044 exit(1); 1045 } 1046 1047 if (idle > 19800) { 1048 fprintf(stderr, "Idle time has a maximum value of 5.5 " 1049 "hours\n"); 1050 exit(1); 1051 } 1052 1053 if (idle != 0 && idle < 5) { 1054 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 1055 exit(1); 1056 } 1057 1058 memset(&req, 0, sizeof(req)); 1059 1060 if (idle <= 240*5) 1061 req.sec_count = idle / 5; 1062 else 1063 req.sec_count = idle / (30*60) + 240; 1064 1065 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 1066 req.timeout = 1000; 1067 1068 ata_command(&req); 1069 1070 return; 1071 } 1072 1073 /* 1074 * Query the device for the current power mode 1075 */ 1076 1077 void 1078 device_checkpower(int argc, char *argv[]) 1079 { 1080 struct atareq req; 1081 1082 /* No arguments. */ 1083 if (argc != 0) 1084 usage(); 1085 1086 memset(&req, 0, sizeof(req)); 1087 1088 req.command = WDCC_CHECK_PWR; 1089 req.timeout = 1000; 1090 req.flags = ATACMD_READREG; 1091 1092 ata_command(&req); 1093 1094 printf("Current power status: "); 1095 1096 switch (req.sec_count) { 1097 case 0x00: 1098 printf("Standby mode\n"); 1099 break; 1100 case 0x80: 1101 printf("Idle mode\n"); 1102 break; 1103 case 0xff: 1104 printf("Active mode\n"); 1105 break; 1106 default: 1107 printf("Unknown power code (%02x)\n", req.sec_count); 1108 } 1109 1110 return; 1111 } 1112 1113 /* 1114 * device_smart: 1115 * 1116 * Display SMART status 1117 */ 1118 void 1119 device_smart(int argc, char *argv[]) 1120 { 1121 struct atareq req; 1122 unsigned char inbuf[DEV_BSIZE]; 1123 unsigned char inbuf2[DEV_BSIZE]; 1124 1125 if (argc < 1) 1126 usage(); 1127 1128 if (strcmp(argv[0], "enable") == 0) { 1129 memset(&req, 0, sizeof(req)); 1130 1131 req.features = WDSM_ENABLE_OPS; 1132 req.command = WDCC_SMART; 1133 req.cylinder = WDSMART_CYL; 1134 req.timeout = 1000; 1135 1136 ata_command(&req); 1137 1138 is_smart(); 1139 } else if (strcmp(argv[0], "disable") == 0) { 1140 memset(&req, 0, sizeof(req)); 1141 1142 req.features = WDSM_DISABLE_OPS; 1143 req.command = WDCC_SMART; 1144 req.cylinder = WDSMART_CYL; 1145 req.timeout = 1000; 1146 1147 ata_command(&req); 1148 1149 is_smart(); 1150 } else if (strcmp(argv[0], "status") == 0) { 1151 int rv; 1152 1153 rv = is_smart(); 1154 1155 if (!rv) { 1156 fprintf(stderr, "SMART not supported\n"); 1157 return; 1158 } else if (rv == 3) 1159 return; 1160 1161 memset(&inbuf, 0, sizeof(inbuf)); 1162 memset(&req, 0, sizeof(req)); 1163 1164 req.features = WDSM_STATUS; 1165 req.command = WDCC_SMART; 1166 req.cylinder = WDSMART_CYL; 1167 req.timeout = 1000; 1168 1169 ata_command(&req); 1170 1171 if (req.cylinder != WDSMART_CYL) { 1172 fprintf(stderr, "Threshold exceeds condition\n"); 1173 } 1174 1175 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1176 * features, the following ata_command()'s may error 1177 * and exit(). 1178 */ 1179 1180 memset(&inbuf, 0, sizeof(inbuf)); 1181 memset(&req, 0, sizeof(req)); 1182 1183 req.flags = ATACMD_READ; 1184 req.features = WDSM_RD_DATA; 1185 req.command = WDCC_SMART; 1186 req.databuf = (caddr_t) inbuf; 1187 req.datalen = sizeof(inbuf); 1188 req.cylinder = WDSMART_CYL; 1189 req.timeout = 1000; 1190 1191 ata_command(&req); 1192 1193 memset(&inbuf2, 0, sizeof(inbuf2)); 1194 memset(&req, 0, sizeof(req)); 1195 1196 req.flags = ATACMD_READ; 1197 req.features = WDSM_RD_THRESHOLDS; 1198 req.command = WDCC_SMART; 1199 req.databuf = (caddr_t) inbuf2; 1200 req.datalen = sizeof(inbuf2); 1201 req.cylinder = WDSMART_CYL; 1202 req.timeout = 1000; 1203 1204 ata_command(&req); 1205 1206 print_smart_status(inbuf, inbuf2); 1207 1208 } else if (strcmp(argv[0], "offline") == 0) { 1209 if (argc != 2) 1210 usage(); 1211 if (!is_smart()) { 1212 fprintf(stderr, "SMART not supported\n"); 1213 return; 1214 } 1215 1216 memset(&req, 0, sizeof(req)); 1217 1218 req.features = WDSM_EXEC_OFFL_IMM; 1219 req.command = WDCC_SMART; 1220 req.cylinder = WDSMART_CYL; 1221 req.sec_num = atol(argv[1]); 1222 req.timeout = 10000; 1223 1224 ata_command(&req); 1225 } else if (strcmp(argv[0], "error-log") == 0) { 1226 if (!is_smart()) { 1227 fprintf(stderr, "SMART not supported\n"); 1228 return; 1229 } 1230 1231 memset(&inbuf, 0, sizeof(inbuf)); 1232 memset(&req, 0, sizeof(req)); 1233 1234 req.flags = ATACMD_READ; 1235 req.features = WDSM_RD_LOG; 1236 req.sec_count = 1; 1237 req.sec_num = 1; 1238 req.command = WDCC_SMART; 1239 req.databuf = (caddr_t) inbuf; 1240 req.datalen = sizeof(inbuf); 1241 req.cylinder = WDSMART_CYL; 1242 req.timeout = 1000; 1243 1244 ata_command(&req); 1245 1246 print_error(inbuf); 1247 } else if (strcmp(argv[0], "selftest-log") == 0) { 1248 if (!is_smart()) { 1249 fprintf(stderr, "SMART not supported\n"); 1250 return; 1251 } 1252 1253 memset(&inbuf, 0, sizeof(inbuf)); 1254 memset(&req, 0, sizeof(req)); 1255 1256 req.flags = ATACMD_READ; 1257 req.features = WDSM_RD_LOG; 1258 req.sec_count = 1; 1259 req.sec_num = 6; 1260 req.command = WDCC_SMART; 1261 req.databuf = (caddr_t) inbuf; 1262 req.datalen = sizeof(inbuf); 1263 req.cylinder = WDSMART_CYL; 1264 req.timeout = 1000; 1265 1266 ata_command(&req); 1267 1268 print_selftest(inbuf); 1269 1270 } else { 1271 usage(); 1272 } 1273 return; 1274 } 1275 1276 void 1277 device_security(int argc, char *argv[]) 1278 { 1279 struct atareq req; 1280 struct ataparams *inqbuf; 1281 1282 /* need subcommand */ 1283 if (argc < 1) 1284 usage(); 1285 1286 if (strcmp(argv[0], "freeze") == 0) { 1287 memset(&req, 0, sizeof(req)); 1288 req.command = WDCC_SECURITY_FREEZE; 1289 req.timeout = 1000; 1290 ata_command(&req); 1291 } else if (strcmp(argv[0], "status") == 0) { 1292 inqbuf = getataparams(); 1293 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1294 } else 1295 usage(); 1296 1297 return; 1298 } 1299 1300 /* 1301 * bus_reset: 1302 * Reset an ATA bus (will reset all devices on the bus) 1303 */ 1304 void 1305 bus_reset(int argc, char *argv[]) 1306 { 1307 int error; 1308 1309 /* no args */ 1310 if (argc != 0) 1311 usage(); 1312 1313 error = ioctl(fd, ATABUSIORESET, NULL); 1314 1315 if (error == -1) 1316 err(1, "ATABUSIORESET failed"); 1317 } 1318