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