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