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