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