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