1 /* $NetBSD: atactl.c,v 1.50 2008/04/28 20:23:07 martin 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.50 2008/04/28 20:23:07 martin 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 { 191, "Gsense error rate", NULL }, 269 { 192, "Power-off retract count", NULL }, 270 { 193, "Load cycle count", NULL }, 271 { 194, "Temperature", device_smart_temp}, 272 { 195, "Hardware ECC Recovered", NULL }, 273 { 196, "Reallocated event count", NULL }, 274 { 197, "Current pending sector", NULL }, 275 { 198, "Offline uncorrectable", NULL }, 276 { 199, "Ultra DMA CRC error count", NULL }, 277 { 200, "Write error rate", NULL }, 278 { 201, "Soft read error rate", NULL }, 279 { 202, "Data address mark errors", NULL }, 280 { 203, "Run out cancel", NULL }, 281 { 204, "Soft ECC correction", NULL }, 282 { 205, "Thermal asperity check", NULL }, 283 { 206, "Flying height", NULL }, 284 { 207, "Spin high current", NULL }, 285 { 208, "Spin buzz", NULL }, 286 { 209, "Offline seek performance", NULL }, 287 { 220, "Disk shift", NULL }, 288 { 221, "G-Sense error rate", NULL }, 289 { 222, "Loaded hours", NULL }, 290 { 223, "Load/unload retry count", NULL }, 291 { 224, "Load friction", NULL }, 292 { 225, "Load/unload cycle count", NULL }, 293 { 226, "Load-in time", NULL }, 294 { 227, "Torque amplification count", NULL }, 295 { 228, "Power-off retract count", NULL }, 296 { 230, "GMR head amplitude", NULL }, 297 { 231, "Temperature", device_smart_temp }, 298 { 240, "Head flying hours", NULL }, 299 { 250, "Read error retry rate", NULL }, 300 { 0, "Unknown", NULL }, 301 }; 302 303 struct bitinfo ata_sec_st[] = { 304 { WDC_SEC_SUPP, "supported" }, 305 { WDC_SEC_EN, "enabled" }, 306 { WDC_SEC_LOCKED, "locked" }, 307 { WDC_SEC_FROZEN, "frozen" }, 308 { WDC_SEC_EXP, "expired" }, 309 { WDC_SEC_ESE_SUPP, "enhanced erase support" }, 310 { WDC_SEC_LEV_MAX, "maximum level" }, 311 { 0, NULL }, 312 }; 313 314 int 315 main(int argc, char *argv[]) 316 { 317 int i; 318 struct command *commands = NULL; 319 320 /* Must have at least: device command */ 321 if (argc < 3) 322 usage(); 323 324 /* Skip program name, get and skip device name and command. */ 325 dvname = argv[1]; 326 cmdname = argv[2]; 327 argv += 3; 328 argc -= 3; 329 330 /* 331 * Open the device 332 */ 333 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0); 334 if (fd == -1) { 335 if (errno == ENOENT) { 336 /* 337 * Device doesn't exist. Probably trying to open 338 * a device which doesn't use disk semantics for 339 * device name. Try again, specifying "cooked", 340 * which leaves off the "r" in front of the device's 341 * name. 342 */ 343 fd = opendisk(dvname, O_RDWR, dvname_store, 344 sizeof(dvname_store), 1); 345 if (fd == -1) 346 err(1, "%s", dvname); 347 } else 348 err(1, "%s", dvname); 349 } 350 351 /* 352 * Point the dvname at the actual device name that opendisk() opened. 353 */ 354 dvname = dvname_store; 355 356 /* Look up and call the command. */ 357 for (i = 0; device_commands[i].cmd_name != NULL; i++) { 358 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) { 359 commands = &device_commands[i]; 360 break; 361 } 362 } 363 if (commands == NULL) { 364 for (i = 0; bus_commands[i].cmd_name != NULL; i++) { 365 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) { 366 commands = &bus_commands[i]; 367 break; 368 } 369 } 370 } 371 if (commands == NULL) 372 errx(1, "unknown command: %s", cmdname); 373 374 argnames = commands->arg_names; 375 376 (*commands->cmd_func)(argc, argv); 377 exit(0); 378 } 379 380 void 381 usage(void) 382 { 383 int i; 384 385 fprintf(stderr, "usage: %s device command [arg [...]]\n", 386 getprogname()); 387 388 fprintf(stderr, " Available device commands:\n"); 389 for (i=0; device_commands[i].cmd_name != NULL; i++) 390 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name, 391 device_commands[i].arg_names); 392 393 fprintf(stderr, " Available bus commands:\n"); 394 for (i=0; bus_commands[i].cmd_name != NULL; i++) 395 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name, 396 bus_commands[i].arg_names); 397 398 exit(1); 399 } 400 401 /* 402 * Wrapper that calls ATAIOCCOMMAND and checks for errors 403 */ 404 405 void 406 ata_command(struct atareq *req) 407 { 408 int error; 409 410 error = ioctl(fd, ATAIOCCOMMAND, req); 411 412 if (error == -1) 413 err(1, "ATAIOCCOMMAND failed"); 414 415 switch (req->retsts) { 416 417 case ATACMD_OK: 418 return; 419 case ATACMD_TIMEOUT: 420 fprintf(stderr, "ATA command timed out\n"); 421 exit(1); 422 case ATACMD_DF: 423 fprintf(stderr, "ATA device returned a Device Fault\n"); 424 exit(1); 425 case ATACMD_ERROR: 426 if (req->error & WDCE_ABRT) 427 fprintf(stderr, "ATA device returned Aborted " 428 "Command\n"); 429 else 430 fprintf(stderr, "ATA device returned error register " 431 "%0x\n", req->error); 432 exit(1); 433 default: 434 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code " 435 "%d\n", req->retsts); 436 exit(1); 437 } 438 } 439 440 /* 441 * Print out strings associated with particular bitmasks 442 */ 443 444 void 445 print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo) 446 { 447 448 for (; binfo->bitmask != 0; binfo++) 449 if (bits & binfo->bitmask) 450 printf("%s%s%s", bf, binfo->string, af); 451 } 452 453 void 454 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, struct bitinfo *binfo) 455 { 456 457 for (; binfo->bitmask != 0; binfo++) 458 if (bits & binfo->bitmask) 459 printf("%s%s (%s)%s", bf, binfo->string, 460 (enables & binfo->bitmask) ? "enabled" : "disabled", 461 af); 462 } 463 464 465 /* 466 * Try to print SMART temperature field 467 */ 468 469 void 470 device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value) 471 { 472 printf("%" PRIu8, attr->raw[0]); 473 if (attr->raw[0] != raw_value) 474 printf(" Lifetime max/min %" PRIu8 "/%" PRIu8, 475 attr->raw[2], attr->raw[4]); 476 } 477 478 479 /* 480 * Print out SMART attribute thresholds and values 481 */ 482 483 void 484 print_smart_status(void *vbuf, void *tbuf) 485 { 486 struct ata_smart_attributes *value_buf = vbuf; 487 struct ata_smart_thresholds *threshold_buf = tbuf; 488 struct ata_smart_attr *attr; 489 uint64_t raw_value; 490 int flags; 491 int i, j; 492 int aid; 493 u_int8_t checksum; 494 495 for (i = checksum = 0; i < 512; i++) 496 checksum += ((u_int8_t *) value_buf)[i]; 497 if (checksum != 0) { 498 fprintf(stderr, "SMART attribute values checksum error\n"); 499 return; 500 } 501 502 for (i = checksum = 0; i < 512; i++) 503 checksum += ((u_int8_t *) threshold_buf)[i]; 504 if (checksum != 0) { 505 fprintf(stderr, "SMART attribute thresholds checksum error\n"); 506 return; 507 } 508 509 printf("id value thresh crit collect reliability description\t\t\traw\n"); 510 for (i = 0; i < 256; i++) { 511 int thresh = 0; 512 513 attr = NULL; 514 515 for (j = 0; j < 30; j++) { 516 if (value_buf->attributes[j].id == i) 517 attr = &value_buf->attributes[j]; 518 if (threshold_buf->thresholds[j].id == i) 519 thresh = threshold_buf->thresholds[j].value; 520 } 521 522 if (thresh && attr == NULL) 523 errx(1, "threshold but not attr %d", i); 524 if (attr == NULL) 525 continue; 526 527 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF) 528 continue; 529 530 for (aid = 0; 531 smart_attrs[aid].id != i && smart_attrs[aid].id != 0; 532 aid++) 533 ; 534 535 flags = le16toh(attr->flags); 536 537 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t", 538 i, attr->value, thresh, 539 flags & WDSM_ATTR_ADVISORY ? "yes" : "no", 540 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline", 541 attr->value > thresh ? "posi" : "nega", 542 smart_attrs[aid].name); 543 544 for (j = 0, raw_value = 0; j < 6; j++) 545 raw_value += ((uint64_t)attr->raw[j]) << (8*j); 546 547 if (smart_attrs[aid].special) 548 (*smart_attrs[aid].special)(attr, raw_value); 549 else 550 printf("%" PRIu64, raw_value); 551 printf("\n"); 552 } 553 } 554 555 struct { 556 int number; 557 const char *name; 558 } selftest_name[] = { 559 { 0, "Off-line" }, 560 { 1, "Short off-line" }, 561 { 2, "Extended off-line" }, 562 { 127, "Abort off-line test" }, 563 { 129, "Short captive" }, 564 { 130, "Extended captive" }, 565 { 256, "Unknown test" }, /* larger then u_int8_t */ 566 { 0, NULL } 567 }; 568 569 const char *selftest_status[] = { 570 "No error", 571 "Aborted by the host", 572 "Interrupted by the host by reset", 573 "Fatal error or unknown test error", 574 "Unknown test element failed", 575 "Electrical test element failed", 576 "The Servo (and/or seek) test element failed", 577 "Read element of test failed", 578 "Reserved", 579 "Reserved", 580 "Reserved", 581 "Reserved", 582 "Reserved", 583 "Reserved", 584 "Reserved", 585 "Self-test in progress" 586 }; 587 588 void 589 print_error_entry(int num, struct ata_smart_error *le) 590 { 591 int i; 592 593 printf("Log entry: %d\n", num); 594 595 for (i = 0; i < 5; i++) 596 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, 597 le->command[i].device_control, 598 le->command[i].features, 599 le->command[i].sector_count, 600 le->command[i].sector_number, 601 le->command[i].cylinder_low, 602 le->command[i].cylinder_high, 603 le->command[i].device_head, 604 le->command[i].command, 605 le->command[i].timestamp[3], 606 le->command[i].timestamp[2], 607 le->command[i].timestamp[1], 608 le->command[i].timestamp[0]); 609 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x status=%02x state=%02x lifetime=%02x%02x\n", 610 le->error_data.error, 611 le->error_data.sector_count, 612 le->error_data.sector_number, 613 le->error_data.cylinder_low, 614 le->error_data.cylinder_high, 615 le->error_data.device_head, 616 le->error_data.status, 617 le->error_data.state, 618 le->error_data.lifetime[1], 619 le->error_data.lifetime[0]); 620 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 621 le->error_data.extended_error[0], 622 le->error_data.extended_error[1], 623 le->error_data.extended_error[2], 624 le->error_data.extended_error[3], 625 le->error_data.extended_error[4], 626 le->error_data.extended_error[5], 627 le->error_data.extended_error[6], 628 le->error_data.extended_error[7], 629 le->error_data.extended_error[8], 630 le->error_data.extended_error[9], 631 le->error_data.extended_error[10], 632 le->error_data.extended_error[11], 633 le->error_data.extended_error[12], 634 le->error_data.extended_error[13], 635 le->error_data.extended_error[14], 636 le->error_data.extended_error[15], 637 le->error_data.extended_error[15], 638 le->error_data.extended_error[17], 639 le->error_data.extended_error[18]); 640 } 641 642 void 643 print_error(void *buf) 644 { 645 struct ata_smart_errorlog *erlog = buf; 646 u_int8_t checksum; 647 int i; 648 649 for (i = checksum = 0; i < 512; i++) 650 checksum += ((u_int8_t *) buf)[i]; 651 if (checksum != 0) { 652 fprintf(stderr, "SMART error log checksum error\n"); 653 return; 654 } 655 656 if (erlog->data_structure_revision != 1) { 657 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n", 658 erlog->data_structure_revision); 659 return; 660 } 661 662 if (erlog->mostrecenterror == 0) { 663 printf("No errors have been logged\n"); 664 return; 665 } 666 667 if (erlog->mostrecenterror > 5) { 668 fprintf(stderr, "Most recent error is too large\n"); 669 return; 670 } 671 672 for (i = erlog->mostrecenterror; i < 5; i++) 673 print_error_entry(i, &erlog->log_entries[i]); 674 for (i = 0; i < erlog->mostrecenterror; i++) 675 print_error_entry(i, &erlog->log_entries[i]); 676 printf("device error count: %d\n", erlog->device_error_count); 677 } 678 679 void 680 print_selftest_entry(int num, struct ata_smart_selftest *le) 681 { 682 unsigned char *p; 683 int i; 684 685 /* check if all zero */ 686 for (p = (void *)le, i = 0; i < sizeof(*le); i++) 687 if (p[i] != 0) 688 break; 689 if (i == sizeof(*le)) 690 return; 691 692 printf("Log entry: %d\n", num); 693 694 /* Get test name */ 695 for (i = 0; selftest_name[i].name != NULL; i++) 696 if (selftest_name[i].number == le->number) 697 break; 698 699 if (selftest_name[i].name == NULL) 700 printf("\tName: (%d)\n", le->number); 701 else 702 printf("\tName: %s\n", selftest_name[i].name); 703 printf("\tStatus: %s\n", selftest_status[le->status >> 4]); 704 /* XXX This generally should not be set when a self-test is completed, 705 and at any rate is useless. - mycroft */ 706 if (le->status >> 4 == 15) 707 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf); 708 else if (le->status >> 4 != 0) 709 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error)); 710 } 711 712 void 713 print_selftest(void *buf) 714 { 715 struct ata_smart_selftestlog *stlog = buf; 716 u_int8_t checksum; 717 int i; 718 719 for (i = checksum = 0; i < 512; i++) 720 checksum += ((u_int8_t *) buf)[i]; 721 if (checksum != 0) { 722 fprintf(stderr, "SMART selftest log checksum error\n"); 723 return; 724 } 725 726 if (le16toh(stlog->data_structure_revision) != 1) { 727 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n", 728 le16toh(stlog->data_structure_revision)); 729 return; 730 } 731 732 if (stlog->mostrecenttest == 0) { 733 printf("No self-tests have been logged\n"); 734 return; 735 } 736 737 if (stlog->mostrecenttest > 22) { 738 fprintf(stderr, "Most recent test is too large\n"); 739 return; 740 } 741 742 for (i = stlog->mostrecenttest; i < 22; i++) 743 print_selftest_entry(i, &stlog->log_entries[i]); 744 for (i = 0; i < stlog->mostrecenttest; i++) 745 print_selftest_entry(i, &stlog->log_entries[i]); 746 } 747 748 struct ataparams * 749 getataparams() 750 { 751 struct atareq req; 752 static union { 753 unsigned char inbuf[DEV_BSIZE]; 754 struct ataparams inqbuf; 755 } inbuf; 756 757 memset(&inbuf, 0, sizeof(inbuf)); 758 memset(&req, 0, sizeof(req)); 759 760 req.flags = ATACMD_READ; 761 req.command = WDCC_IDENTIFY; 762 req.databuf = (caddr_t)&inbuf; 763 req.datalen = sizeof(inbuf); 764 req.timeout = 1000; 765 766 ata_command(&req); 767 768 return (&inbuf.inqbuf); 769 } 770 771 /* 772 * is_smart: 773 * 774 * Detect whether device supports SMART and SMART is enabled. 775 */ 776 777 int 778 is_smart(void) 779 { 780 int retval = 0; 781 struct ataparams *inqbuf; 782 const char *status; 783 784 inqbuf = getataparams(); 785 786 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 787 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) { 788 fprintf(stderr, "SMART unsupported\n"); 789 } else { 790 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 || 791 inqbuf->atap_cmd_set2 == 0xffff || 792 inqbuf->atap_cmd_set2 == 0x0000) { 793 status = "status unknown"; 794 retval = 2; 795 } else { 796 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) { 797 status = "enabled"; 798 retval = 1; 799 } else { 800 status = "disabled"; 801 retval = 3; 802 } 803 } 804 printf("SMART supported, SMART %s\n", status); 805 } 806 } 807 return retval; 808 } 809 810 /* 811 * DEVICE COMMANDS 812 */ 813 814 /* 815 * device_identify: 816 * 817 * Display the identity of the device 818 */ 819 void 820 device_identify(int argc, char *argv[]) 821 { 822 struct ataparams *inqbuf; 823 #if BYTE_ORDER == LITTLE_ENDIAN 824 int i; 825 u_int16_t *p; 826 #endif 827 828 /* No arguments. */ 829 if (argc != 0) 830 usage(); 831 832 inqbuf = getataparams(); 833 834 #if BYTE_ORDER == LITTLE_ENDIAN 835 /* 836 * On little endian machines, we need to shuffle the string 837 * byte order. However, we don't have to do this for NEC or 838 * Mitsumi ATAPI devices 839 */ 840 841 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 842 ((inqbuf->atap_model[0] == 'N' && 843 inqbuf->atap_model[1] == 'E') || 844 (inqbuf->atap_model[0] == 'F' && 845 inqbuf->atap_model[1] == 'X')))) { 846 for (i = 0 ; i < sizeof(inqbuf->atap_model); i += 2) { 847 p = (u_short *) (inqbuf->atap_model + i); 848 *p = ntohs(*p); 849 } 850 for (i = 0 ; i < sizeof(inqbuf->atap_serial); i += 2) { 851 p = (u_short *) (inqbuf->atap_serial + i); 852 *p = ntohs(*p); 853 } 854 for (i = 0 ; i < sizeof(inqbuf->atap_revision); i += 2) { 855 p = (u_short *) (inqbuf->atap_revision + i); 856 *p = ntohs(*p); 857 } 858 } 859 #endif 860 861 /* 862 * Strip blanks off of the info strings. Yuck, I wish this was 863 * cleaner. 864 */ 865 866 if (inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] == ' ') { 867 inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] = '\0'; 868 while (inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] == ' ') 869 inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] = '\0'; 870 } 871 872 if (inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] == ' ') { 873 inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] = '\0'; 874 while (inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] == ' ') 875 inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] = '\0'; 876 } 877 878 if (inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] == ' ') { 879 inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] = '\0'; 880 while (inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] == ' ') 881 inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] = '\0'; 882 } 883 884 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n", 885 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model, 886 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision, 887 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial); 888 889 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 890 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 891 "removable"); 892 893 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0) 894 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 895 "sectors: %d\n", inqbuf->atap_cylinders, 896 inqbuf->atap_heads, inqbuf->atap_sectors, 897 (inqbuf->atap_capacity[1] << 16) | 898 inqbuf->atap_capacity[0]); 899 900 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) 901 printf("Device supports command queue depth of %d\n", 902 inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK); 903 904 printf("Device capabilities:\n"); 905 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 906 907 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 908 printf("Device supports following standards:\n"); 909 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 910 printf("\n"); 911 } 912 913 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 914 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 915 printf("Command set support:\n"); 916 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 917 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 918 inqbuf->atap_cmd1_en, ata_cmd_set1); 919 else 920 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 921 ata_cmd_set1); 922 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 923 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 924 inqbuf->atap_cmd2_en, ata_cmd_set2); 925 else 926 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 927 ata_cmd_set2); 928 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 929 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 930 ata_cmd_ext); 931 } 932 933 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) { 934 printf("Serial ATA capabilities:\n"); 935 print_bitinfo("\t", "\n", inqbuf->atap_sata_caps, ata_sata_caps); 936 } 937 938 if (inqbuf->atap_sata_features_supp != 0 && inqbuf->atap_sata_features_supp != 0xffff) { 939 printf("Serial ATA features:\n"); 940 if (inqbuf->atap_sata_features_en != 0 && inqbuf->atap_sata_features_en != 0xffff) 941 print_bitinfo2("\t", "\n", inqbuf->atap_sata_features_supp, inqbuf->atap_sata_features_en, ata_sata_feat); 942 else 943 print_bitinfo("\t", "\n", inqbuf->atap_sata_features_supp, ata_sata_feat); 944 } 945 946 return; 947 } 948 949 /* 950 * device idle: 951 * 952 * issue the IDLE IMMEDIATE command to the drive 953 */ 954 void 955 device_idle(int argc, char *argv[]) 956 { 957 struct atareq req; 958 959 /* No arguments. */ 960 if (argc != 0) 961 usage(); 962 963 memset(&req, 0, sizeof(req)); 964 965 if (strcmp(cmdname, "idle") == 0) 966 req.command = WDCC_IDLE_IMMED; 967 else if (strcmp(cmdname, "standby") == 0) 968 req.command = WDCC_STANDBY_IMMED; 969 else 970 req.command = WDCC_SLEEP; 971 972 req.timeout = 1000; 973 974 ata_command(&req); 975 976 return; 977 } 978 979 /* 980 * device apm: 981 * 982 * enable/disable/control the APM feature of the drive 983 */ 984 void 985 device_apm(int argc, char *argv[]) 986 { 987 struct atareq req; 988 long l; 989 990 memset(&req, 0, sizeof(req)); 991 if (argc >= 1) { 992 req.command = SET_FEATURES; 993 req.timeout = 1000; 994 995 if (strcmp(argv[0], "disable") == 0) 996 req.features = WDSF_APM_DS; 997 else if (strcmp(argv[0], "set") == 0 && argc >= 2 && 998 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) { 999 1000 req.features = WDSF_APM_EN; 1001 req.sec_count = l + 1; 1002 } else 1003 usage(); 1004 } else 1005 usage(); 1006 1007 ata_command(&req); 1008 } 1009 1010 1011 /* 1012 * Set the idle timer on the disk. Set it for either idle mode or 1013 * standby mode, depending on how we were invoked. 1014 */ 1015 1016 void 1017 device_setidle(int argc, char *argv[]) 1018 { 1019 unsigned long idle; 1020 struct atareq req; 1021 char *end; 1022 1023 /* Only one argument */ 1024 if (argc != 1) 1025 usage(); 1026 1027 idle = strtoul(argv[0], &end, 0); 1028 1029 if (*end != '\0') { 1030 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 1031 exit(1); 1032 } 1033 1034 if (idle > 19800) { 1035 fprintf(stderr, "Idle time has a maximum value of 5.5 " 1036 "hours\n"); 1037 exit(1); 1038 } 1039 1040 if (idle != 0 && idle < 5) { 1041 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 1042 exit(1); 1043 } 1044 1045 memset(&req, 0, sizeof(req)); 1046 1047 if (idle <= 240*5) 1048 req.sec_count = idle / 5; 1049 else 1050 req.sec_count = idle / (30*60) + 240; 1051 1052 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 1053 req.timeout = 1000; 1054 1055 ata_command(&req); 1056 1057 return; 1058 } 1059 1060 /* 1061 * Query the device for the current power mode 1062 */ 1063 1064 void 1065 device_checkpower(int argc, char *argv[]) 1066 { 1067 struct atareq req; 1068 1069 /* No arguments. */ 1070 if (argc != 0) 1071 usage(); 1072 1073 memset(&req, 0, sizeof(req)); 1074 1075 req.command = WDCC_CHECK_PWR; 1076 req.timeout = 1000; 1077 req.flags = ATACMD_READREG; 1078 1079 ata_command(&req); 1080 1081 printf("Current power status: "); 1082 1083 switch (req.sec_count) { 1084 case 0x00: 1085 printf("Standby mode\n"); 1086 break; 1087 case 0x80: 1088 printf("Idle mode\n"); 1089 break; 1090 case 0xff: 1091 printf("Active mode\n"); 1092 break; 1093 default: 1094 printf("Unknown power code (%02x)\n", req.sec_count); 1095 } 1096 1097 return; 1098 } 1099 1100 /* 1101 * device_smart: 1102 * 1103 * Display SMART status 1104 */ 1105 void 1106 device_smart(int argc, char *argv[]) 1107 { 1108 struct atareq req; 1109 unsigned char inbuf[DEV_BSIZE]; 1110 unsigned char inbuf2[DEV_BSIZE]; 1111 1112 if (argc < 1) 1113 usage(); 1114 1115 if (strcmp(argv[0], "enable") == 0) { 1116 memset(&req, 0, sizeof(req)); 1117 1118 req.features = WDSM_ENABLE_OPS; 1119 req.command = WDCC_SMART; 1120 req.cylinder = WDSMART_CYL; 1121 req.timeout = 1000; 1122 1123 ata_command(&req); 1124 1125 is_smart(); 1126 } else if (strcmp(argv[0], "disable") == 0) { 1127 memset(&req, 0, sizeof(req)); 1128 1129 req.features = WDSM_DISABLE_OPS; 1130 req.command = WDCC_SMART; 1131 req.cylinder = WDSMART_CYL; 1132 req.timeout = 1000; 1133 1134 ata_command(&req); 1135 1136 is_smart(); 1137 } else if (strcmp(argv[0], "status") == 0) { 1138 int rv; 1139 1140 rv = is_smart(); 1141 1142 if (!rv) { 1143 fprintf(stderr, "SMART not supported\n"); 1144 return; 1145 } else if (rv == 3) 1146 return; 1147 1148 memset(&inbuf, 0, sizeof(inbuf)); 1149 memset(&req, 0, sizeof(req)); 1150 1151 req.features = WDSM_STATUS; 1152 req.command = WDCC_SMART; 1153 req.cylinder = WDSMART_CYL; 1154 req.timeout = 1000; 1155 1156 ata_command(&req); 1157 1158 if (req.cylinder != WDSMART_CYL) { 1159 fprintf(stderr, "Threshold exceeds condition\n"); 1160 } 1161 1162 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1163 * features, the following ata_command()'s may error 1164 * and exit(). 1165 */ 1166 1167 memset(&inbuf, 0, sizeof(inbuf)); 1168 memset(&req, 0, sizeof(req)); 1169 1170 req.flags = ATACMD_READ; 1171 req.features = WDSM_RD_DATA; 1172 req.command = WDCC_SMART; 1173 req.databuf = (caddr_t) inbuf; 1174 req.datalen = sizeof(inbuf); 1175 req.cylinder = WDSMART_CYL; 1176 req.timeout = 1000; 1177 1178 ata_command(&req); 1179 1180 memset(&inbuf2, 0, sizeof(inbuf2)); 1181 memset(&req, 0, sizeof(req)); 1182 1183 req.flags = ATACMD_READ; 1184 req.features = WDSM_RD_THRESHOLDS; 1185 req.command = WDCC_SMART; 1186 req.databuf = (caddr_t) inbuf2; 1187 req.datalen = sizeof(inbuf2); 1188 req.cylinder = WDSMART_CYL; 1189 req.timeout = 1000; 1190 1191 ata_command(&req); 1192 1193 print_smart_status(inbuf, inbuf2); 1194 1195 } else if (strcmp(argv[0], "offline") == 0) { 1196 if (argc != 2) 1197 usage(); 1198 if (!is_smart()) { 1199 fprintf(stderr, "SMART not supported\n"); 1200 return; 1201 } 1202 1203 memset(&req, 0, sizeof(req)); 1204 1205 req.features = WDSM_EXEC_OFFL_IMM; 1206 req.command = WDCC_SMART; 1207 req.cylinder = WDSMART_CYL; 1208 req.sec_num = atol(argv[1]); 1209 req.timeout = 10000; 1210 1211 ata_command(&req); 1212 } else if (strcmp(argv[0], "error-log") == 0) { 1213 if (!is_smart()) { 1214 fprintf(stderr, "SMART not supported\n"); 1215 return; 1216 } 1217 1218 memset(&inbuf, 0, sizeof(inbuf)); 1219 memset(&req, 0, sizeof(req)); 1220 1221 req.flags = ATACMD_READ; 1222 req.features = WDSM_RD_LOG; 1223 req.sec_count = 1; 1224 req.sec_num = 1; 1225 req.command = WDCC_SMART; 1226 req.databuf = (caddr_t) inbuf; 1227 req.datalen = sizeof(inbuf); 1228 req.cylinder = WDSMART_CYL; 1229 req.timeout = 1000; 1230 1231 ata_command(&req); 1232 1233 print_error(inbuf); 1234 } else if (strcmp(argv[0], "selftest-log") == 0) { 1235 if (!is_smart()) { 1236 fprintf(stderr, "SMART not supported\n"); 1237 return; 1238 } 1239 1240 memset(&inbuf, 0, sizeof(inbuf)); 1241 memset(&req, 0, sizeof(req)); 1242 1243 req.flags = ATACMD_READ; 1244 req.features = WDSM_RD_LOG; 1245 req.sec_count = 1; 1246 req.sec_num = 6; 1247 req.command = WDCC_SMART; 1248 req.databuf = (caddr_t) inbuf; 1249 req.datalen = sizeof(inbuf); 1250 req.cylinder = WDSMART_CYL; 1251 req.timeout = 1000; 1252 1253 ata_command(&req); 1254 1255 print_selftest(inbuf); 1256 1257 } else { 1258 usage(); 1259 } 1260 return; 1261 } 1262 1263 void 1264 device_security(int argc, char *argv[]) 1265 { 1266 struct atareq req; 1267 struct ataparams *inqbuf; 1268 1269 /* need subcommand */ 1270 if (argc < 1) 1271 usage(); 1272 1273 if (strcmp(argv[0], "freeze") == 0) { 1274 memset(&req, 0, sizeof(req)); 1275 req.command = WDCC_SECURITY_FREEZE; 1276 req.timeout = 1000; 1277 ata_command(&req); 1278 } else if (strcmp(argv[0], "status") == 0) { 1279 inqbuf = getataparams(); 1280 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1281 } else 1282 usage(); 1283 1284 return; 1285 } 1286 1287 /* 1288 * bus_reset: 1289 * Reset an ATA bus (will reset all devices on the bus) 1290 */ 1291 void 1292 bus_reset(int argc, char *argv[]) 1293 { 1294 int error; 1295 1296 /* no args */ 1297 if (argc != 0) 1298 usage(); 1299 1300 error = ioctl(fd, ATABUSIORESET, NULL); 1301 1302 if (error == -1) 1303 err(1, "ATABUSIORESET failed"); 1304 } 1305