1 /* $NetBSD: atactl.c,v 1.39 2005/06/27 01:00:05 christos 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.39 2005/06/27 01:00:05 christos 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, "Log revision not 1"); 645 return; 646 } 647 648 if (erlog->mostrecenterror == 0) { 649 printf("No errors have been logged\n"); 650 return; 651 } 652 653 if (erlog->mostrecenterror > 5) { 654 fprintf(stderr, "Most recent error is too large\n"); 655 return; 656 } 657 658 for (i = erlog->mostrecenterror; i < 5; i++) 659 print_error_entry(i, &erlog->log_entries[i]); 660 for (i = 0; i < erlog->mostrecenterror; i++) 661 print_error_entry(i, &erlog->log_entries[i]); 662 printf("device error count: %d\n", erlog->device_error_count); 663 } 664 665 void 666 print_selftest_entry(int num, struct ata_smart_selftest *le) 667 { 668 unsigned char *p; 669 int i; 670 671 /* check if all zero */ 672 for (p = (void *)le, i = 0; i < sizeof(*le); i++) 673 if (p[i] != 0) 674 break; 675 if (i == sizeof(*le)) 676 return; 677 678 printf("Log entry: %d\n", num); 679 680 /* Get test name */ 681 for (i = 0; selftest_name[i].name != NULL; i++) 682 if (selftest_name[i].number == le->number) 683 break; 684 685 if (selftest_name[i].name == NULL) 686 printf("\tName: (%d)\n", le->number); 687 else 688 printf("\tName: %s\n", selftest_name[i].name); 689 printf("\tStatus: %s\n", selftest_status[le->status >> 4]); 690 /* XXX This generally should not be set when a self-test is completed, 691 and at any rate is useless. - mycroft */ 692 if (le->status >> 4 == 15) 693 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf); 694 else if (le->status >> 4 != 0) 695 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error)); 696 } 697 698 void 699 print_selftest(void *buf) 700 { 701 struct ata_smart_selftestlog *stlog = buf; 702 u_int8_t checksum; 703 int i; 704 705 for (i = checksum = 0; i < 512; i++) 706 checksum += ((u_int8_t *) buf)[i]; 707 if (checksum != 0) { 708 fprintf(stderr, "SMART selftest log checksum error\n"); 709 return; 710 } 711 712 if (le16toh(stlog->data_structure_revision != 1)) { 713 fprintf(stderr, "Log revision not 1"); 714 return; 715 } 716 717 if (stlog->mostrecenttest == 0) { 718 printf("No self-tests have been logged\n"); 719 return; 720 } 721 722 if (stlog->mostrecenttest > 22) { 723 fprintf(stderr, "Most recent test is too large\n"); 724 return; 725 } 726 727 for (i = stlog->mostrecenttest; i < 22; i++) 728 print_selftest_entry(i, &stlog->log_entries[i]); 729 for (i = 0; i < stlog->mostrecenttest; i++) 730 print_selftest_entry(i, &stlog->log_entries[i]); 731 } 732 733 struct ataparams * 734 getataparams() 735 { 736 struct atareq req; 737 static union { 738 unsigned char inbuf[DEV_BSIZE]; 739 struct ataparams inqbuf; 740 } inbuf; 741 742 memset(&inbuf, 0, sizeof(inbuf)); 743 memset(&req, 0, sizeof(req)); 744 745 req.flags = ATACMD_READ; 746 req.command = WDCC_IDENTIFY; 747 req.databuf = (caddr_t)&inbuf; 748 req.datalen = sizeof(inbuf); 749 req.timeout = 1000; 750 751 ata_command(&req); 752 753 return (&inbuf.inqbuf); 754 } 755 756 /* 757 * is_smart: 758 * 759 * Detect whether device supports SMART and SMART is enabled. 760 */ 761 762 int 763 is_smart(void) 764 { 765 int retval = 0; 766 struct ataparams *inqbuf; 767 const char *status; 768 769 inqbuf = getataparams(); 770 771 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 772 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) { 773 fprintf(stderr, "SMART unsupported\n"); 774 } else { 775 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 || 776 inqbuf->atap_cmd_set2 == 0xffff || 777 inqbuf->atap_cmd_set2 == 0x0000) { 778 status = "status unknown"; 779 retval = 2; 780 } else { 781 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) { 782 status = "enabled"; 783 retval = 1; 784 } else { 785 status = "disabled"; 786 } 787 } 788 printf("SMART supported, SMART %s\n", status); 789 } 790 } 791 return retval; 792 } 793 794 /* 795 * DEVICE COMMANDS 796 */ 797 798 /* 799 * device_identify: 800 * 801 * Display the identity of the device 802 */ 803 void 804 device_identify(int argc, char *argv[]) 805 { 806 struct ataparams *inqbuf; 807 #if BYTE_ORDER == LITTLE_ENDIAN 808 int i; 809 u_int16_t *p; 810 #endif 811 812 /* No arguments. */ 813 if (argc != 0) 814 usage(); 815 816 inqbuf = getataparams(); 817 818 #if BYTE_ORDER == LITTLE_ENDIAN 819 /* 820 * On little endian machines, we need to shuffle the string 821 * byte order. However, we don't have to do this for NEC or 822 * Mitsumi ATAPI devices 823 */ 824 825 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 826 ((inqbuf->atap_model[0] == 'N' && 827 inqbuf->atap_model[1] == 'E') || 828 (inqbuf->atap_model[0] == 'F' && 829 inqbuf->atap_model[1] == 'X')))) { 830 for (i = 0 ; i < sizeof(inqbuf->atap_model); i += 2) { 831 p = (u_short *) (inqbuf->atap_model + i); 832 *p = ntohs(*p); 833 } 834 for (i = 0 ; i < sizeof(inqbuf->atap_serial); i += 2) { 835 p = (u_short *) (inqbuf->atap_serial + i); 836 *p = ntohs(*p); 837 } 838 for (i = 0 ; i < sizeof(inqbuf->atap_revision); i += 2) { 839 p = (u_short *) (inqbuf->atap_revision + i); 840 *p = ntohs(*p); 841 } 842 } 843 #endif 844 845 /* 846 * Strip blanks off of the info strings. Yuck, I wish this was 847 * cleaner. 848 */ 849 850 if (inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] == ' ') { 851 inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] = '\0'; 852 while (inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] == ' ') 853 inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] = '\0'; 854 } 855 856 if (inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] == ' ') { 857 inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] = '\0'; 858 while (inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] == ' ') 859 inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] = '\0'; 860 } 861 862 if (inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] == ' ') { 863 inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] = '\0'; 864 while (inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] == ' ') 865 inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] = '\0'; 866 } 867 868 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n", 869 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model, 870 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision, 871 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial); 872 873 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 874 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 875 "removable"); 876 877 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0) 878 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 879 "sectors: %d\n", inqbuf->atap_cylinders, 880 inqbuf->atap_heads, inqbuf->atap_sectors, 881 (inqbuf->atap_capacity[1] << 16) | 882 inqbuf->atap_capacity[0]); 883 884 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) 885 printf("Device supports command queue depth of %d\n", 886 inqbuf->atap_queuedepth & 0xf); 887 888 printf("Device capabilities:\n"); 889 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 890 891 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 892 printf("Device supports following standards:\n"); 893 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 894 printf("\n"); 895 } 896 897 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 898 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 899 printf("Command set support:\n"); 900 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 901 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 902 inqbuf->atap_cmd1_en, ata_cmd_set1); 903 else 904 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 905 ata_cmd_set1); 906 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 907 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 908 inqbuf->atap_cmd2_en, ata_cmd_set2); 909 else 910 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 911 ata_cmd_set2); 912 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 913 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 914 ata_cmd_ext); 915 } 916 917 return; 918 } 919 920 /* 921 * device idle: 922 * 923 * issue the IDLE IMMEDIATE command to the drive 924 */ 925 926 void 927 device_idle(int argc, char *argv[]) 928 { 929 struct atareq req; 930 931 /* No arguments. */ 932 if (argc != 0) 933 usage(); 934 935 memset(&req, 0, sizeof(req)); 936 937 if (strcmp(cmdname, "idle") == 0) 938 req.command = WDCC_IDLE_IMMED; 939 else if (strcmp(cmdname, "standby") == 0) 940 req.command = WDCC_STANDBY_IMMED; 941 else 942 req.command = WDCC_SLEEP; 943 944 req.timeout = 1000; 945 946 ata_command(&req); 947 948 return; 949 } 950 951 /* 952 * Set the idle timer on the disk. Set it for either idle mode or 953 * standby mode, depending on how we were invoked. 954 */ 955 956 void 957 device_setidle(int argc, char *argv[]) 958 { 959 unsigned long idle; 960 struct atareq req; 961 char *end; 962 963 /* Only one argument */ 964 if (argc != 1) 965 usage(); 966 967 idle = strtoul(argv[0], &end, 0); 968 969 if (*end != '\0') { 970 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 971 exit(1); 972 } 973 974 if (idle > 19800) { 975 fprintf(stderr, "Idle time has a maximum value of 5.5 " 976 "hours\n"); 977 exit(1); 978 } 979 980 if (idle != 0 && idle < 5) { 981 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 982 exit(1); 983 } 984 985 memset(&req, 0, sizeof(req)); 986 987 if (idle <= 240*5) 988 req.sec_count = idle / 5; 989 else 990 req.sec_count = idle / (30*60) + 240; 991 992 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 993 req.timeout = 1000; 994 995 ata_command(&req); 996 997 return; 998 } 999 1000 /* 1001 * Query the device for the current power mode 1002 */ 1003 1004 void 1005 device_checkpower(int argc, char *argv[]) 1006 { 1007 struct atareq req; 1008 1009 /* No arguments. */ 1010 if (argc != 0) 1011 usage(); 1012 1013 memset(&req, 0, sizeof(req)); 1014 1015 req.command = WDCC_CHECK_PWR; 1016 req.timeout = 1000; 1017 req.flags = ATACMD_READREG; 1018 1019 ata_command(&req); 1020 1021 printf("Current power status: "); 1022 1023 switch (req.sec_count) { 1024 case 0x00: 1025 printf("Standby mode\n"); 1026 break; 1027 case 0x80: 1028 printf("Idle mode\n"); 1029 break; 1030 case 0xff: 1031 printf("Active mode\n"); 1032 break; 1033 default: 1034 printf("Unknown power code (%02x)\n", req.sec_count); 1035 } 1036 1037 return; 1038 } 1039 1040 /* 1041 * device_smart: 1042 * 1043 * Display SMART status 1044 */ 1045 void 1046 device_smart(int argc, char *argv[]) 1047 { 1048 struct atareq req; 1049 unsigned char inbuf[DEV_BSIZE]; 1050 unsigned char inbuf2[DEV_BSIZE]; 1051 1052 if (argc < 1) 1053 usage(); 1054 1055 if (strcmp(argv[0], "enable") == 0) { 1056 memset(&req, 0, sizeof(req)); 1057 1058 req.features = WDSM_ENABLE_OPS; 1059 req.command = WDCC_SMART; 1060 req.cylinder = WDSMART_CYL; 1061 req.timeout = 1000; 1062 1063 ata_command(&req); 1064 1065 is_smart(); 1066 } else if (strcmp(argv[0], "disable") == 0) { 1067 memset(&req, 0, sizeof(req)); 1068 1069 req.features = WDSM_DISABLE_OPS; 1070 req.command = WDCC_SMART; 1071 req.cylinder = WDSMART_CYL; 1072 req.timeout = 1000; 1073 1074 ata_command(&req); 1075 1076 is_smart(); 1077 } else if (strcmp(argv[0], "status") == 0) { 1078 if (!is_smart()) { 1079 fprintf(stderr, "SMART not supported\n"); 1080 return; 1081 } 1082 1083 memset(&inbuf, 0, sizeof(inbuf)); 1084 memset(&req, 0, sizeof(req)); 1085 1086 req.features = WDSM_STATUS; 1087 req.command = WDCC_SMART; 1088 req.cylinder = WDSMART_CYL; 1089 req.timeout = 1000; 1090 1091 ata_command(&req); 1092 1093 if (req.cylinder != WDSMART_CYL) { 1094 fprintf(stderr, "Threshold exceeds condition\n"); 1095 } 1096 1097 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1098 * features, the following ata_command()'s may error 1099 * and exit(). 1100 */ 1101 1102 memset(&inbuf, 0, sizeof(inbuf)); 1103 memset(&req, 0, sizeof(req)); 1104 1105 req.flags = ATACMD_READ; 1106 req.features = WDSM_RD_DATA; 1107 req.command = WDCC_SMART; 1108 req.databuf = (caddr_t) inbuf; 1109 req.datalen = sizeof(inbuf); 1110 req.cylinder = WDSMART_CYL; 1111 req.timeout = 1000; 1112 1113 ata_command(&req); 1114 1115 memset(&inbuf2, 0, sizeof(inbuf2)); 1116 memset(&req, 0, sizeof(req)); 1117 1118 req.flags = ATACMD_READ; 1119 req.features = WDSM_RD_THRESHOLDS; 1120 req.command = WDCC_SMART; 1121 req.databuf = (caddr_t) inbuf2; 1122 req.datalen = sizeof(inbuf2); 1123 req.cylinder = WDSMART_CYL; 1124 req.timeout = 1000; 1125 1126 ata_command(&req); 1127 1128 print_smart_status(inbuf, inbuf2); 1129 1130 } else if (strcmp(argv[0], "offline") == 0) { 1131 if (argc != 2) 1132 usage(); 1133 if (!is_smart()) { 1134 fprintf(stderr, "SMART not supported\n"); 1135 return; 1136 } 1137 1138 memset(&req, 0, sizeof(req)); 1139 1140 req.features = WDSM_EXEC_OFFL_IMM; 1141 req.command = WDCC_SMART; 1142 req.cylinder = WDSMART_CYL; 1143 req.sec_num = atol(argv[1]); 1144 req.timeout = 10000; 1145 1146 ata_command(&req); 1147 } else if (strcmp(argv[0], "error-log") == 0) { 1148 if (!is_smart()) { 1149 fprintf(stderr, "SMART not supported\n"); 1150 return; 1151 } 1152 1153 memset(&inbuf, 0, sizeof(inbuf)); 1154 memset(&req, 0, sizeof(req)); 1155 1156 req.flags = ATACMD_READ; 1157 req.features = WDSM_RD_LOG; 1158 req.sec_count = 1; 1159 req.sec_num = 1; 1160 req.command = WDCC_SMART; 1161 req.databuf = (caddr_t) inbuf; 1162 req.datalen = sizeof(inbuf); 1163 req.cylinder = WDSMART_CYL; 1164 req.timeout = 1000; 1165 1166 ata_command(&req); 1167 1168 print_error(inbuf); 1169 } else if (strcmp(argv[0], "selftest-log") == 0) { 1170 if (!is_smart()) { 1171 fprintf(stderr, "SMART not supported\n"); 1172 return; 1173 } 1174 1175 memset(&inbuf, 0, sizeof(inbuf)); 1176 memset(&req, 0, sizeof(req)); 1177 1178 req.flags = ATACMD_READ; 1179 req.features = WDSM_RD_LOG; 1180 req.sec_count = 1; 1181 req.sec_num = 6; 1182 req.command = WDCC_SMART; 1183 req.databuf = (caddr_t) inbuf; 1184 req.datalen = sizeof(inbuf); 1185 req.cylinder = WDSMART_CYL; 1186 req.timeout = 1000; 1187 1188 ata_command(&req); 1189 1190 print_selftest(inbuf); 1191 1192 } else { 1193 usage(); 1194 } 1195 return; 1196 } 1197 1198 void 1199 device_security(int argc, char *argv[]) 1200 { 1201 struct atareq req; 1202 struct ataparams *inqbuf; 1203 1204 /* need subcommand */ 1205 if (argc < 1) 1206 usage(); 1207 1208 if (strcmp(argv[0], "freeze") == 0) { 1209 memset(&req, 0, sizeof(req)); 1210 req.command = WCDD_SECURITY_FREEZE; 1211 req.timeout = 1000; 1212 ata_command(&req); 1213 } else if (strcmp(argv[0], "status") == 0) { 1214 inqbuf = getataparams(); 1215 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1216 } else 1217 usage(); 1218 1219 return; 1220 } 1221 1222 /* 1223 * bus_reset: 1224 * Reset an ATA bus (will reset all devices on the bus) 1225 */ 1226 void 1227 bus_reset(int argc, char *argv[]) 1228 { 1229 int error; 1230 1231 /* no args */ 1232 if (argc != 0) 1233 usage(); 1234 1235 error = ioctl(fd, ATABUSIORESET, NULL); 1236 1237 if (error == -1) 1238 err(1, "ATABUSIORESET failed"); 1239 } 1240