1 /* $OpenBSD: atactl.c,v 1.44 2011/05/04 21:40:07 oga Exp $ */ 2 /* $NetBSD: atactl.c,v 1.4 1999/02/24 18:49:14 jwise Exp $ */ 3 4 /*- 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Ken Hornstein. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * atactl(8) - a program to control ATA devices. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/ioctl.h> 39 40 #include <err.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <util.h> 48 49 #include <dev/ata/atareg.h> 50 #include <dev/ic/wdcreg.h> 51 #include <dev/ic/wdcevent.h> 52 #include <sys/ataio.h> 53 54 #include "atasec.h" 55 #include "atasmart.h" 56 57 struct command { 58 const char *cmd_name; 59 void (*cmd_func)(int, char *[]); 60 }; 61 62 struct bitinfo { 63 u_int bitmask; 64 const char *string; 65 }; 66 67 struct valinfo { 68 int value; 69 const char *string; 70 }; 71 72 int main(int, char *[]); 73 __dead void usage(void); 74 void ata_command(struct atareq *); 75 void print_bitinfo(const char *, u_int, struct bitinfo *); 76 int strtoval(const char *, struct valinfo *); 77 const char *valtostr(int, struct valinfo *); 78 79 int fd; /* file descriptor for device */ 80 81 extern char *__progname; /* from crt0.o */ 82 83 void device_dump(int, char*[]); 84 void device_identify(int, char *[]); 85 void device_setidle(int, char *[]); 86 void device_idle(int, char *[]); 87 void device_checkpower(int, char *[]); 88 void device_acoustic(int, char *[]); 89 void device_apm(int, char *[]); 90 void device_feature(int, char *[]); 91 void device_sec_setpass(int, char *[]); 92 void device_sec_unlock(int, char *[]); 93 void device_sec_erase(int, char *[]); 94 void device_sec_freeze(int, char *[]); 95 void device_sec_disablepass(int, char *[]); 96 void device_smart_enable(int, char *[]); 97 void device_smart_disable(int, char *[]); 98 void device_smart_status(int, char *[]); 99 void device_smart_autosave(int, char *[]); 100 void device_smart_offline(int, char *[]); 101 void device_smart_read(int, char *[]); 102 void device_smart_readlog(int, char *[]); 103 void device_attr(int, char *[]); 104 105 void smart_print_errdata(struct smart_log_errdata *); 106 int smart_cksum(u_int8_t *, size_t); 107 108 char *sec_getpass(int, int); 109 110 struct command commands[] = { 111 { "dump", device_dump }, 112 { "identify", device_identify }, 113 { "setidle", device_setidle }, 114 { "setstandby", device_setidle }, 115 { "idle", device_idle }, 116 { "standby", device_idle }, 117 { "sleep", device_idle }, 118 { "checkpower", device_checkpower }, 119 { "acousticdisable", device_feature }, 120 { "acousticset", device_acoustic }, 121 { "apmdisable", device_feature }, 122 { "apmset", device_apm }, 123 { "poddisable", device_feature }, 124 { "podenable", device_feature }, 125 { "puisdisable", device_feature }, 126 { "puisenable", device_feature }, 127 { "puisspinup", device_feature }, 128 { "readaheaddisable", device_feature }, 129 { "readaheadenable", device_feature }, 130 { "secsetpass", device_sec_setpass }, 131 { "secunlock", device_sec_unlock }, 132 { "secerase", device_sec_erase }, 133 { "secfreeze", device_sec_freeze }, 134 { "secdisablepass", device_sec_disablepass }, 135 { "smartenable", device_smart_enable }, 136 { "smartdisable", device_smart_disable }, 137 { "smartstatus", device_smart_status }, 138 { "smartautosave", device_smart_autosave }, 139 { "smartoffline", device_smart_offline }, 140 { "smartread", device_smart_read }, 141 { "smartreadlog", device_smart_readlog }, 142 { "readattr", device_attr }, 143 { "writecachedisable", device_feature }, 144 { "writecacheenable", device_feature }, 145 { NULL, NULL }, 146 }; 147 148 /* 149 * Tables containing bitmasks used for error reporting and 150 * device identification. 151 */ 152 153 struct bitinfo ata_caps[] = { 154 { ATA_CAP_STBY, "ATA standby timer values" }, 155 { WDC_CAP_IORDY, "IORDY operation" }, 156 { WDC_CAP_IORDY_DSBL, "IORDY disabling" }, 157 { 0, NULL }, 158 }; 159 160 struct bitinfo ata_vers[] = { 161 { WDC_VER_ATA1, "ATA-1" }, 162 { WDC_VER_ATA2, "ATA-2" }, 163 { WDC_VER_ATA3, "ATA-3" }, 164 { WDC_VER_ATA4, "ATA-4" }, 165 { WDC_VER_ATA5, "ATA-5" }, 166 { WDC_VER_ATA6, "ATA-6" }, 167 { WDC_VER_ATA7, "ATA-7" }, 168 { WDC_VER_ATA8, "ATA-8" }, 169 { WDC_VER_ATA9, "ATA-9" }, 170 { WDC_VER_ATA10, "ATA-10" }, 171 { WDC_VER_ATA11, "ATA-11" }, 172 { WDC_VER_ATA12, "ATA-12" }, 173 { WDC_VER_ATA13, "ATA-13" }, 174 { WDC_VER_ATA14, "ATA-14" }, 175 { 0, NULL }, 176 }; 177 178 struct bitinfo ata_cmd_set1[] = { 179 { WDC_CMD1_NOP, "NOP command" }, 180 { WDC_CMD1_RB, "READ BUFFER command" }, 181 { WDC_CMD1_WB, "WRITE BUFFER command" }, 182 { WDC_CMD1_HPA, "Host Protected Area feature set" }, 183 { WDC_CMD1_DVRST, "DEVICE RESET command" }, 184 { WDC_CMD1_SRV, "SERVICE interrupt" }, 185 { WDC_CMD1_RLSE, "Release interrupt" }, 186 { WDC_CMD1_AHEAD, "Read look-ahead" }, 187 { WDC_CMD1_CACHE, "Write cache" }, 188 { WDC_CMD1_PKT, "PACKET command feature set" }, 189 { WDC_CMD1_PM, "Power Management feature set" }, 190 { WDC_CMD1_REMOV, "Removable Media feature set" }, 191 { WDC_CMD1_SEC, "Security Mode feature set" }, 192 { WDC_CMD1_SMART, "SMART feature set" }, 193 { 0, NULL }, 194 }; 195 196 struct bitinfo ata_cmd_set2[] = { 197 { ATAPI_CMD2_FCE, "Flush Cache Ext command" }, 198 { ATAPI_CMD2_FC, "Flush Cache command" }, 199 { ATAPI_CMD2_DCO, "Device Configuration Overlay feature set" }, 200 { ATAPI_CMD2_48AD, "48bit address feature set" }, 201 { ATAPI_CMD2_AAM, "Automatic Acoustic Management feature set" }, 202 { ATAPI_CMD2_SM, "Set Max security extension commands" }, 203 { ATAPI_CMD2_SF, "Set Features subcommand required" }, 204 { ATAPI_CMD2_PUIS, "Power-up in standby feature set" }, 205 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" }, 206 { ATA_CMD2_APM, "Advanced Power Management feature set" }, 207 { ATA_CMD2_CFA, "CFA feature set" }, 208 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" }, 209 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" }, 210 { 0, NULL }, 211 }; 212 213 struct bitinfo ata_cmd_ext[] = { 214 { ATAPI_CMDE_IIUF, "IDLE IMMEDIATE with UNLOAD FEATURE" }, 215 { ATAPI_CMDE_MSER, "Media serial number" }, 216 { ATAPI_CMDE_TEST, "SMART self-test" }, 217 { ATAPI_CMDE_SLOG, "SMART error logging" }, 218 { 0, NULL }, 219 }; 220 221 /* 222 * Tables containing bitmasks and values used for 223 * SMART commands. 224 */ 225 226 struct bitinfo smart_offcap[] = { 227 { SMART_OFFCAP_EXEC, "execute immediate" }, 228 { SMART_OFFCAP_ABORT, "abort/restart" }, 229 { SMART_OFFCAP_READSCAN, "read scanning" }, 230 { SMART_OFFCAP_SELFTEST, "self-test routines" }, 231 { 0, NULL} 232 }; 233 234 struct bitinfo smart_smartcap[] = { 235 { SMART_SMARTCAP_SAVE, "saving SMART data" }, 236 { SMART_SMARTCAP_AUTOSAVE, "enable/disable attribute autosave" }, 237 { 0, NULL } 238 }; 239 240 struct valinfo smart_autosave[] = { 241 { SMART_AUTOSAVE_EN, "enable" }, 242 { SMART_AUTOSAVE_DS, "disable" }, 243 { 0, NULL } 244 }; 245 246 struct valinfo smart_offline[] = { 247 { SMART_OFFLINE_COLLECT, "collect" }, 248 { SMART_OFFLINE_SHORTOFF, "shortoffline" }, 249 { SMART_OFFLINE_EXTENOFF, "extenoffline" }, 250 { SMART_OFFLINE_ABORT, "abort" }, 251 { SMART_OFFLINE_SHORTCAP, "shortcaptive" }, 252 { SMART_OFFLINE_EXTENCAP, "extencaptive" }, 253 { 0, NULL } 254 }; 255 256 struct valinfo smart_readlog[] = { 257 { SMART_READLOG_DIR, "directory" }, 258 { SMART_READLOG_SUM, "summary" }, 259 { SMART_READLOG_COMP, "comp" }, 260 { SMART_READLOG_SELF, "selftest" }, 261 { 0, NULL } 262 }; 263 264 struct valinfo smart_offstat[] = { 265 { SMART_OFFSTAT_NOTSTART, "never started" }, 266 { SMART_OFFSTAT_COMPLETE, "completed ok" }, 267 { SMART_OFFSTAT_SUSPEND, "suspended by an interrupting command" }, 268 { SMART_OFFSTAT_INTR, "aborted by an interrupting command" }, 269 { SMART_OFFSTAT_ERROR, "aborted due to fatal error" }, 270 { 0, NULL } 271 }; 272 273 struct valinfo smart_selfstat[] = { 274 { SMART_SELFSTAT_COMPLETE, "completed ok or not started" }, 275 { SMART_SELFSTAT_ABORT, "aborted" }, 276 { SMART_SELFSTAT_INTR, "hardware or software reset" }, 277 { SMART_SELFSTAT_ERROR, "fatal error" }, 278 { SMART_SELFSTAT_UNKFAIL, "unknown test element failed" }, 279 { SMART_SELFSTAT_ELFAIL, "electrical test element failed" }, 280 { SMART_SELFSTAT_SRVFAIL, "servo test element failed" }, 281 { SMART_SELFSTAT_RDFAIL, "read test element failed" }, 282 { 0, NULL } 283 }; 284 285 struct valinfo smart_logstat[] = { 286 { SMART_LOG_STATE_UNK, "unknown" }, 287 { SMART_LOG_STATE_SLEEP, "sleep" }, 288 { SMART_LOG_STATE_ACTIDL, "active/idle" }, 289 { SMART_LOG_STATE_OFFSELF, "off-line or self-test" }, 290 { 0, NULL } 291 }; 292 293 /* 294 * Tables containing values used for reading 295 * device attributes. 296 */ 297 298 struct valinfo ibm_attr_names[] = { 299 { 1, "Raw Read Error Rate" }, 300 { 2, "Throughput Performance" }, 301 { 3, "Spin Up Time" }, 302 { 4, "Start/Stop Count" }, 303 { 5, "Reallocated Sector Count" }, 304 { 6, "Read Channel Margin" }, 305 { 7, "Seek Error Rate" }, 306 { 8, "Seek Time Performance" }, 307 { 9, "Power-On Hours Count" }, 308 { 10, "Spin Retry Count" }, 309 { 11, "Calibration Retry Count" }, 310 { 12, "Device Power Cycle Count" }, 311 { 13, "Soft Read Error Rate" }, 312 { 189, "High Fly Writes" }, 313 { 190, "Airflow Temperature" }, 314 { 191, "G-Sense Error Rate" }, 315 { 192, "Power-Off Retract Count" }, 316 { 193, "Load Cycle Count" }, 317 { 194, "Temperature" }, 318 { 195, "Hardware ECC Recovered" }, 319 { 196, "Reallocation Event Count" }, 320 { 197, "Current Pending Sector Count" }, 321 { 198, "Off-Line Scan Uncorrectable Sector Count" }, 322 { 199, "Ultra DMA CRC Error Count" }, 323 { 200, "Write Error Rate" }, 324 { 201, "Soft Read Error Rate" }, 325 { 202, "Data Address Mark Errors" }, 326 { 203, "Run Out Cancel" }, 327 { 204, "Soft ECC Correction" }, 328 { 205, "Thermal Asperity Check" }, 329 { 206, "Flying Height" }, 330 { 207, "Spin High Current" }, 331 { 208, "Spin Buzz" }, 332 { 209, "Offline Seek Performance" }, 333 { 220, "Disk Shift" }, 334 { 221, "G-Sense Error Rate" }, 335 { 222, "Loaded Hours" }, 336 { 223, "Load/Unload Retry Count" }, 337 { 224, "Load Friction" }, 338 { 225, "Load/Unload Cycle Count" }, 339 { 226, "Load-In Time" }, 340 { 227, "Torque Amplification Count" }, 341 { 228, "Power-Off Retract Count" }, 342 { 230, "GMR Head Amplitude" }, 343 { 231, "Temperature" }, 344 { 240, "Head Flying Hours" }, 345 { 250, "Read Error Retry Rate" }, 346 { 0, NULL }, 347 }; 348 349 #define MAKEWORD(b1, b2) \ 350 (b2 << 8 | b1) 351 #define MAKEDWORD(b1, b2, b3, b4) \ 352 (b4 << 24 | b3 << 16 | b2 << 8 | b1) 353 354 int 355 main(int argc, char *argv[]) 356 { 357 struct command *cmdp; 358 359 if (argc < 2) 360 usage(); 361 362 /* 363 * Open the device 364 */ 365 if ((fd = opendev(argv[1], O_RDWR, OPENDEV_PART, NULL)) == -1) 366 err(1, "%s", argv[1]); 367 368 /* Skip program name and device name. */ 369 if (argc != 2) { 370 argv += 2; 371 argc -= 2; 372 } else { 373 argv[1] = "identify"; 374 argv += 1; 375 argc -= 1; 376 } 377 378 /* Look up and call the command. */ 379 for (cmdp = commands; cmdp->cmd_name != NULL; cmdp++) 380 if (strcmp(argv[0], cmdp->cmd_name) == 0) 381 break; 382 if (cmdp->cmd_name == NULL) 383 errx(1, "unknown command: %s", argv[0]); 384 385 (cmdp->cmd_func)(argc, argv); 386 387 return (0); 388 } 389 390 __dead void 391 usage(void) 392 { 393 394 fprintf(stderr, "usage: %s device [command [arg]]\n", __progname); 395 exit(1); 396 } 397 398 /* 399 * Wrapper that calls ATAIOCCOMMAND and checks for errors 400 */ 401 void 402 ata_command(struct atareq *req) 403 { 404 if (ioctl(fd, ATAIOCCOMMAND, req) == -1) 405 err(1, "ATAIOCCOMMAND failed"); 406 407 switch (req->retsts) { 408 409 case ATACMD_OK: 410 return; 411 case ATACMD_TIMEOUT: 412 errx(1, "ATA command timed out"); 413 case ATACMD_DF: 414 errx(1, "ATA device returned a Device Fault"); 415 case ATACMD_ERROR: 416 if (req->error & WDCE_ABRT) 417 errx(1, "ATA device returned Aborted Command"); 418 else 419 errx(1, "ATA device returned error register %0x", 420 req->error); 421 default: 422 errx(1, "ATAIOCCOMMAND returned unknown result code %d", 423 req->retsts); 424 } 425 } 426 427 /* 428 * Print out strings associated with particular bitmasks 429 */ 430 void 431 print_bitinfo(const char *f, u_int bits, struct bitinfo *binfo) 432 { 433 434 for (; binfo->bitmask != 0; binfo++) 435 if (bits & binfo->bitmask) 436 printf(f, binfo->string); 437 } 438 439 /* 440 * strtoval(): 441 * returns value associated with given string, 442 * if no value found -1 is returned. 443 */ 444 int 445 strtoval(const char *str, struct valinfo *vinfo) 446 { 447 for (; vinfo->string != NULL; vinfo++) 448 if (strcmp(str, vinfo->string) == 0) 449 return (vinfo->value); 450 return (-1); 451 } 452 453 /* 454 * valtostr(): 455 * returns string associated with given value, 456 * if no string found NULL is returned. 457 */ 458 const char * 459 valtostr(int val, struct valinfo *vinfo) 460 { 461 for (; vinfo->string != NULL; vinfo++) 462 if (val == vinfo->value) 463 return (vinfo->string); 464 return (NULL); 465 } 466 467 /* 468 * DEVICE COMMANDS 469 */ 470 471 /* 472 * device dump: 473 * 474 * extract issued ATA requests from the log buffer 475 */ 476 void 477 device_dump(int argc, char *argv[]) 478 { 479 unsigned char buf[131072]; 480 atagettrace_t agt; 481 unsigned int total; 482 unsigned int p = 0; 483 int type; 484 const char *types[] = { NULL, "status", "error", "ATAPI", 485 "ATAPI done", "ATA cmd", "ATA", "select slave", 486 "select master", "register read", "ATA LBA48" }; 487 int num_types = sizeof(types) / sizeof(types[0]); 488 int info; 489 int entrysize; 490 int i; 491 int flags; 492 493 if (argc != 1) 494 goto usage; 495 496 memset(&agt, 0, sizeof(agt)); 497 agt.buf_size = sizeof(buf); 498 agt.buf = buf; 499 500 if (ioctl(fd, ATAIOGETTRACE, &agt) == -1) 501 err(1, "ATAIOGETTRACE failed"); 502 503 total = agt.bytes_copied; 504 505 /* Parse entries */ 506 while (p < total) { 507 type = buf[p++]; 508 if (p >= total) 509 return; 510 if (type <= 0 || type >= num_types) 511 return; 512 513 info = buf[p++]; 514 if (p >= total) 515 return; 516 entrysize = (info & 0x1f); 517 518 printf ("ch %d", (info >> 5) & 0x7); 519 printf(": %s", types[type]); 520 521 switch (type) { 522 case WDCEVENT_STATUS: 523 if (entrysize != 1) 524 return; 525 526 printf(": 0x%x", buf[p]); 527 if (buf[p] & WDCS_BSY) 528 printf(" BSY"); 529 if (buf[p] & WDCS_DRDY) 530 printf(" DRDY"); 531 if (buf[p] & WDCS_DWF) 532 printf(" DWF"); 533 if (buf[p] & WDCS_DSC) 534 printf(" DSC"); 535 if (buf[p] & WDCS_DRQ) 536 printf(" DRQ"); 537 if (buf[p] & WDCS_CORR) 538 printf(" CORR"); 539 if (buf[p] & WDCS_IDX) 540 printf(" IDX"); 541 if (buf[p] & WDCS_ERR) 542 printf(" ERR"); 543 544 p++; 545 entrysize = 0; 546 break; 547 case WDCEVENT_ERROR: 548 if (entrysize != 1) 549 return; 550 551 printf(": 0x%x", buf[p]); 552 if (buf[p] & WDCE_BBK) 553 printf(" BBK/CRC"); 554 if (buf[p] & WDCE_UNC) 555 printf(" UNC"); 556 if (buf[p] & WDCE_MC) 557 printf(" MC"); 558 if (buf[p] & WDCE_IDNF) 559 printf(" IDNF"); 560 if (buf[p] & WDCE_MCR) 561 printf(" MCR"); 562 if (buf[p] & WDCE_ABRT) 563 printf(" ABRT"); 564 if (buf[p] & WDCE_TK0NF) 565 printf(" TK0NF"); 566 if (buf[p] & WDCE_AMNF) 567 printf(" AMNF"); 568 569 p++; 570 entrysize = 0; 571 break; 572 case WDCEVENT_ATAPI_CMD: 573 if (entrysize < 2 || p + 2 > total) 574 return; 575 576 flags = (buf[p] << 8) + buf[p + 1]; 577 printf(": flags 0x%x", flags); 578 if (flags & 0x0100) 579 printf(" MEDIA"); 580 if (flags & 0x0080) 581 printf(" SENSE"); 582 if (flags & 0x0040) 583 printf(" DMA"); 584 if (flags & 0x0020) 585 printf(" POLL"); 586 if (flags & 0x0004) 587 printf(" TIMEOUT"); 588 if (flags & 0x0002) 589 printf(" ATAPI"); 590 591 p += 2; 592 entrysize -= 2; 593 break; 594 case WDCEVENT_ATAPI_DONE: 595 if (entrysize != 3 || p + 3 > total) 596 return; 597 598 flags = (buf[p] << 8) + buf[p + 1]; 599 printf(": flags 0x%x", flags); 600 if (flags & 0x0100) 601 printf(" MEDIA"); 602 if (flags & 0x0080) 603 printf(" SENSE"); 604 if (flags & 0x0040) 605 printf(" DMA"); 606 if (flags & 0x0020) 607 printf(" POLL"); 608 if (flags & 0x0004) 609 printf(" TIMEOUT"); 610 if (flags & 0x0002) 611 printf(" ATAPI"); 612 613 printf(", error 0x%x", buf[p + 2]); 614 switch (buf[p + 2]) { 615 case 1: 616 printf(" (sense)"); 617 break; 618 case 2: 619 printf(" (driver failure)"); 620 break; 621 case 3: 622 printf(" (timeout)"); 623 break; 624 case 4: 625 printf(" (busy)"); 626 break; 627 case 5: 628 printf(" (ATAPI sense)"); 629 break; 630 case 8: 631 printf(" (reset)"); 632 break; 633 } 634 635 p += 3; 636 entrysize = 0; 637 break; 638 case WDCEVENT_ATA_LONG: 639 if (entrysize != 7 || p + 7 > total) 640 return; 641 642 printf(": "); 643 switch (buf[p + 6]) { 644 case WDCC_READDMA: 645 printf("READ DMA"); 646 break; 647 case WDCC_WRITEDMA: 648 printf("WRITE DMA"); 649 break; 650 default: 651 printf("CMD 0x%x", buf[p + 6]); 652 } 653 printf(" head %d, precomp %d, cyl_hi %d, " 654 "cyl_lo %d, sec %d, cnt %d", 655 buf[p], buf[p + 1], buf[p + 2], buf[p + 3], 656 buf[p + 4], buf[p + 5]); 657 658 p += 7; 659 entrysize = 0; 660 break; 661 case WDCEVENT_REG: 662 if (entrysize != 3 || p + 3 > total) 663 return; 664 665 switch (buf[p]) { 666 case 1: 667 printf(": error"); 668 break; 669 case 2: 670 printf(": ireason"); 671 break; 672 case 3: 673 printf(": lba_lo"); 674 break; 675 case 4: 676 printf(": lba_mi"); 677 break; 678 case 5: 679 printf(": lba_hi"); 680 break; 681 case 6: 682 printf(": sdh"); 683 break; 684 case 7: 685 printf(": status"); 686 break; 687 case 8: 688 printf(": altstatus"); 689 break; 690 default: 691 printf(": unknown register %d", buf[p]); 692 } 693 printf(": 0x%x", (buf[p + 1] << 8) + buf[p + 2]); 694 695 p += 3; 696 entrysize = 0; 697 break; 698 case WDCEVENT_ATA_EXT: 699 if (entrysize != 9 || p + 9 > total) 700 return; 701 702 printf(": "); 703 switch (buf[p + 8]) { 704 case WDCC_READDMA_EXT: 705 printf("READ DMA EXT"); 706 break; 707 case WDCC_WRITEDMA_EXT: 708 printf("WRITE DMA EXT"); 709 break; 710 default: 711 printf("CMD 0x%x", buf[p + 8]); 712 } 713 printf(" lba_hi1 %d, lba_hi2 %d, " 714 "lba_mi1 %d, lba_mi2 %d, lba_lo1 %d, lba_lo2 %d, " 715 "count1 %d, count2 %d", 716 buf[p], buf[p + 1], buf[p + 2], buf[p + 3], 717 buf[p + 4], buf[p + 5], buf[p + 6], 718 buf[p + 7]); 719 720 p += 9; 721 entrysize = 0; 722 break; 723 } 724 725 if (entrysize > 0) 726 printf(":"); 727 for (i = 0; i < entrysize; i++) { 728 printf (" 0x%02x", buf[p]); 729 if (++p >= total) 730 break; 731 } 732 printf("\n"); 733 } 734 735 return; 736 737 usage: 738 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 739 exit(1); 740 } 741 742 /* 743 * device_identify: 744 * 745 * Display the identity of the device 746 */ 747 void 748 device_identify(int argc, char *argv[]) 749 { 750 struct ataparams *inqbuf; 751 struct atareq req; 752 char inbuf[DEV_BSIZE]; 753 u_int64_t capacity; 754 u_int8_t *s; 755 756 if (argc != 1) 757 goto usage; 758 759 memset(&inbuf, 0, sizeof(inbuf)); 760 memset(&req, 0, sizeof(req)); 761 762 inqbuf = (struct ataparams *) inbuf; 763 764 req.flags = ATACMD_READ; 765 req.command = WDCC_IDENTIFY; 766 req.databuf = (caddr_t) inbuf; 767 req.datalen = sizeof(inbuf); 768 req.timeout = 1000; 769 770 ata_command(&req); 771 772 if (BYTE_ORDER == BIG_ENDIAN) { 773 swap16_multi((u_int16_t *)inbuf, 10); 774 swap16_multi(((u_int16_t *)inbuf) + 20, 3); 775 swap16_multi(((u_int16_t *)inbuf) + 47, sizeof(inbuf) / 2 - 47); 776 } 777 778 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 779 ((inqbuf->atap_model[0] == 'N' && 780 inqbuf->atap_model[1] == 'E') || 781 (inqbuf->atap_model[0] == 'F' && 782 inqbuf->atap_model[1] == 'X')))) { 783 swap16_multi((u_int16_t *)(inqbuf->atap_model), 784 sizeof(inqbuf->atap_model) / 2); 785 swap16_multi((u_int16_t *)(inqbuf->atap_serial), 786 sizeof(inqbuf->atap_serial) / 2); 787 swap16_multi((u_int16_t *)(inqbuf->atap_revision), 788 sizeof(inqbuf->atap_revision) / 2); 789 } 790 791 /* 792 * Strip blanks off of the info strings. 793 */ 794 795 for (s = &inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1]; 796 s >= inqbuf->atap_model && *s == ' '; s--) 797 *s = '\0'; 798 799 for (s = &inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1]; 800 s >= inqbuf->atap_revision && *s == ' '; s--) 801 *s = '\0'; 802 803 for (s = &inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1]; 804 s >= inqbuf->atap_serial && *s == ' '; s--) 805 *s = '\0'; 806 807 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n", 808 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model, 809 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision, 810 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial); 811 812 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 813 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 814 "removable"); 815 816 if (inqbuf->atap_cmd2_en & ATAPI_CMD2_48AD) 817 capacity = ((u_int64_t)inqbuf->atap_max_lba[3] << 48) | 818 ((u_int64_t)inqbuf->atap_max_lba[2] << 32) | 819 ((u_int64_t)inqbuf->atap_max_lba[1] << 16) | 820 (u_int64_t)inqbuf->atap_max_lba[0]; 821 else 822 capacity = (inqbuf->atap_capacity[1] << 16) | 823 inqbuf->atap_capacity[0]; 824 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 825 "sectors: %llu\n", inqbuf->atap_cylinders, 826 inqbuf->atap_heads, inqbuf->atap_sectors, capacity); 827 828 if ((inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ) && 829 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)) 830 printf("Device supports command queue depth of %d\n", 831 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1); 832 833 printf("Device capabilities:\n"); 834 print_bitinfo("\t%s\n", inqbuf->atap_capabilities1, ata_caps); 835 836 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 837 printf("Device supports the following standards:\n"); 838 print_bitinfo("%s ", inqbuf->atap_ata_major, ata_vers); 839 printf("\n"); 840 } 841 842 if ((inqbuf->atap_cmd_set1 & WDC_CMD1_SEC) && 843 inqbuf->atap_mpasswd_rev != 0 && 844 inqbuf->atap_mpasswd_rev != 0xffff) 845 printf("Master password revision code 0x%04x\n", 846 inqbuf->atap_mpasswd_rev); 847 848 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 849 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 850 printf("Device supports the following command sets:\n"); 851 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set1, ata_cmd_set1); 852 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set2, ata_cmd_set2); 853 print_bitinfo("\t%s\n", inqbuf->atap_cmd_ext, ata_cmd_ext); 854 } 855 856 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 857 printf("Device has enabled the following command " 858 "sets/features:\n"); 859 print_bitinfo("\t%s\n", inqbuf->atap_cmd1_en, ata_cmd_set1); 860 print_bitinfo("\t%s\n", inqbuf->atap_cmd2_en, ata_cmd_set2); 861 } 862 863 return; 864 865 usage: 866 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 867 exit(1); 868 } 869 870 /* 871 * device idle: 872 * 873 * issue the IDLE IMMEDIATE command to the drive 874 */ 875 void 876 device_idle(int argc, char *argv[]) 877 { 878 struct atareq req; 879 880 if (argc != 1) 881 goto usage; 882 883 memset(&req, 0, sizeof(req)); 884 885 if (strcmp(argv[0], "idle") == 0) 886 req.command = WDCC_IDLE_IMMED; 887 else if (strcmp(argv[0], "standby") == 0) 888 req.command = WDCC_STANDBY_IMMED; 889 else 890 req.command = WDCC_SLEEP; 891 892 req.timeout = 1000; 893 894 ata_command(&req); 895 896 return; 897 usage: 898 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 899 exit(1); 900 } 901 902 /* 903 * SECURITY SET PASSWORD command 904 */ 905 void 906 device_sec_setpass(int argc, char *argv[]) 907 { 908 struct atareq req; 909 struct sec_password pwd; 910 char *pass, inbuf[DEV_BSIZE]; 911 struct ataparams *inqbuf = (struct ataparams *)inbuf; 912 913 if (argc < 2) 914 goto usage; 915 916 memset(&pwd, 0, sizeof(pwd)); 917 918 if (strcmp(argv[1], "user") == 0 && argc == 3) 919 pwd.ctrl |= SEC_PASSWORD_USER; 920 else if (strcmp(argv[1], "master") == 0 && argc == 2) 921 pwd.ctrl |= SEC_PASSWORD_MASTER; 922 else 923 goto usage; 924 if (argc == 3) { 925 if (strcmp(argv[2], "high") == 0) 926 pwd.ctrl |= SEC_LEVEL_HIGH; 927 else if (strcmp(argv[2], "maximum") == 0) 928 pwd.ctrl |= SEC_LEVEL_MAX; 929 else 930 goto usage; 931 } 932 933 /* 934 * Issue IDENTIFY command to obtain master password 935 * revision code and decrement its value. 936 * The valid revision codes are 0x0001 through 0xfffe. 937 * If the device returns 0x0000 or 0xffff as a revision 938 * code then the master password revision code is not 939 * supported so don't touch it. 940 */ 941 memset(&inbuf, 0, sizeof(inbuf)); 942 memset(&req, 0, sizeof(req)); 943 944 req.command = WDCC_IDENTIFY; 945 req.timeout = 1000; 946 req.flags = ATACMD_READ; 947 req.databuf = (caddr_t)inbuf; 948 req.datalen = sizeof(inbuf); 949 950 ata_command(&req); 951 952 pwd.revision = inqbuf->atap_mpasswd_rev; 953 if (pwd.revision != 0 && pwd.revision != 0xffff && --pwd.revision == 0) 954 pwd.revision = 0xfffe; 955 956 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 1); 957 memcpy(pwd.password, pass, strlen(pass)); 958 959 memset(&req, 0, sizeof(req)); 960 961 req.command = ATA_SEC_SET_PASSWORD; 962 req.timeout = 1000; 963 req.flags = ATACMD_WRITE; 964 req.databuf = (caddr_t)&pwd; 965 req.datalen = sizeof(pwd); 966 967 ata_command(&req); 968 969 return; 970 usage: 971 fprintf(stderr, "usage: %s device %s user high | maximum\n", 972 __progname, argv[0]); 973 fprintf(stderr, " %s device %s master\n", __progname, argv[0]); 974 exit(1); 975 } 976 977 /* 978 * SECURITY UNLOCK command 979 */ 980 void 981 device_sec_unlock(int argc, char *argv[]) 982 { 983 struct atareq req; 984 struct sec_password pwd; 985 char *pass; 986 987 if (argc != 2) 988 goto usage; 989 990 memset(&pwd, 0, sizeof(pwd)); 991 992 if (strcmp(argv[1], "user") == 0) 993 pwd.ctrl |= SEC_PASSWORD_USER; 994 else if (strcmp(argv[1], "master") == 0) 995 pwd.ctrl |= SEC_PASSWORD_MASTER; 996 else 997 goto usage; 998 999 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 1000 memcpy(pwd.password, pass, strlen(pass)); 1001 1002 memset(&req, 0, sizeof(req)); 1003 1004 req.command = ATA_SEC_UNLOCK; 1005 req.timeout = 1000; 1006 req.flags = ATACMD_WRITE; 1007 req.databuf = (caddr_t)&pwd; 1008 req.datalen = sizeof(pwd); 1009 1010 ata_command(&req); 1011 1012 return; 1013 usage: 1014 fprintf(stderr, "usage: %s device %s user | master\n", __progname, 1015 argv[0]); 1016 exit(1); 1017 } 1018 1019 /* 1020 * SECURITY ERASE UNIT command 1021 */ 1022 void 1023 device_sec_erase(int argc, char *argv[]) 1024 { 1025 struct atareq req; 1026 struct sec_password pwd; 1027 char *pass; 1028 1029 if (argc < 2) 1030 goto usage; 1031 1032 memset(&pwd, 0, sizeof(pwd)); 1033 1034 if (strcmp(argv[1], "user") == 0) 1035 pwd.ctrl |= SEC_PASSWORD_USER; 1036 else if (strcmp(argv[1], "master") == 0) 1037 pwd.ctrl |= SEC_PASSWORD_MASTER; 1038 else 1039 goto usage; 1040 if (argc == 2) 1041 pwd.ctrl |= SEC_ERASE_NORMAL; 1042 else if (argc == 3 && strcmp(argv[2], "enhanced") == 0) 1043 pwd.ctrl |= SEC_ERASE_ENHANCED; 1044 else 1045 goto usage; 1046 1047 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 1048 memcpy(pwd.password, pass, strlen(pass)); 1049 1050 /* Issue SECURITY ERASE PREPARE command before */ 1051 memset(&req, 0, sizeof(req)); 1052 1053 req.command = ATA_SEC_ERASE_PREPARE; 1054 req.timeout = 1000; 1055 1056 ata_command(&req); 1057 1058 memset(&req, 0, sizeof(req)); 1059 1060 req.command = ATA_SEC_ERASE_UNIT; 1061 req.timeout = 1000; 1062 req.flags = ATACMD_WRITE; 1063 req.databuf = (caddr_t)&pwd; 1064 req.datalen = sizeof(pwd); 1065 1066 ata_command(&req); 1067 1068 return; 1069 usage: 1070 fprintf(stderr, "usage: %s device %s user | master [enhanced]\n", 1071 __progname, argv[0]); 1072 exit(1); 1073 } 1074 1075 /* 1076 * SECURITY FREEZE LOCK command 1077 */ 1078 void 1079 device_sec_freeze(int argc, char *argv[]) 1080 { 1081 struct atareq req; 1082 1083 if (argc != 1) 1084 goto usage; 1085 1086 memset(&req, 0, sizeof(req)); 1087 1088 req.command = ATA_SEC_FREEZE_LOCK; 1089 req.timeout = 1000; 1090 1091 ata_command(&req); 1092 1093 return; 1094 usage: 1095 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1096 exit(1); 1097 } 1098 1099 /* 1100 * SECURITY DISABLE PASSWORD command 1101 */ 1102 void 1103 device_sec_disablepass(int argc, char *argv[]) 1104 { 1105 struct atareq req; 1106 struct sec_password pwd; 1107 char *pass; 1108 1109 if (argc != 2) 1110 goto usage; 1111 1112 memset(&pwd, 0, sizeof(pwd)); 1113 1114 if (strcmp(argv[1], "user") == 0) 1115 pwd.ctrl |= SEC_PASSWORD_USER; 1116 else if (strcmp(argv[1], "master") == 0) 1117 pwd.ctrl |= SEC_PASSWORD_MASTER; 1118 else 1119 goto usage; 1120 1121 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 1122 memcpy(pwd.password, pass, strlen(pass)); 1123 1124 memset(&req, 0, sizeof(req)); 1125 1126 req.command = ATA_SEC_DISABLE_PASSWORD; 1127 req.timeout = 1000; 1128 req.flags = ATACMD_WRITE; 1129 req.databuf = (caddr_t)&pwd; 1130 req.datalen = sizeof(pwd); 1131 1132 ata_command(&req); 1133 1134 return; 1135 usage: 1136 fprintf(stderr, "usage: %s device %s user | master\n", __progname, 1137 argv[0]); 1138 exit(1); 1139 } 1140 1141 char * 1142 sec_getpass(int ident, int confirm) 1143 { 1144 char *pass, buf[33]; 1145 1146 if ((pass = getpass(ident ? "Master password:" : 1147 "User password:")) == NULL) 1148 err(1, "getpass()"); 1149 if (strlen(pass) > 32) 1150 errx(1, "password too long"); 1151 if (confirm) { 1152 strlcpy(buf, pass, sizeof(buf)); 1153 if ((pass = getpass(ident ? "Retype master password:" : 1154 "Retype user password:")) == NULL) 1155 err(1, "getpass()"); 1156 if (strcmp(pass, buf) != 0) 1157 errx(1, "password mismatch"); 1158 } 1159 1160 return (pass); 1161 } 1162 1163 /* 1164 * SMART ENABLE OPERATIONS command 1165 */ 1166 void 1167 device_smart_enable(int argc, char *argv[]) 1168 { 1169 struct atareq req; 1170 1171 if (argc != 1) 1172 goto usage; 1173 1174 memset(&req, 0, sizeof(req)); 1175 1176 req.command = ATAPI_SMART; 1177 req.cylinder = 0xc24f; 1178 req.timeout = 1000; 1179 req.features = ATA_SMART_EN; 1180 1181 ata_command(&req); 1182 1183 return; 1184 usage: 1185 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1186 exit(1); 1187 } 1188 1189 /* 1190 * SMART DISABLE OPERATIONS command 1191 */ 1192 void 1193 device_smart_disable(int argc, char *argv[]) 1194 { 1195 struct atareq req; 1196 1197 if (argc != 1) 1198 goto usage; 1199 1200 memset(&req, 0, sizeof(req)); 1201 1202 req.command = ATAPI_SMART; 1203 req.cylinder = 0xc24f; 1204 req.timeout = 1000; 1205 req.features = ATA_SMART_DS; 1206 1207 ata_command(&req); 1208 1209 return; 1210 usage: 1211 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1212 exit(1); 1213 } 1214 1215 /* 1216 * SMART STATUS command 1217 */ 1218 void 1219 device_smart_status(int argc, char *argv[]) 1220 { 1221 struct atareq req; 1222 1223 if (argc != 1) 1224 goto usage; 1225 1226 memset(&req, 0, sizeof(req)); 1227 1228 req.command = ATAPI_SMART; 1229 req.cylinder = 0xc24f; 1230 req.timeout = 1000; 1231 req.features = ATA_SMART_STATUS; 1232 1233 ata_command(&req); 1234 1235 if (req.cylinder == 0xc24f) 1236 printf("No SMART threshold exceeded\n"); 1237 else if (req.cylinder == 0x2cf4) { 1238 errx(2, "SMART threshold exceeded!"); 1239 } else { 1240 errx(1, "Unknown response %02x!", req.cylinder); 1241 } 1242 1243 return; 1244 usage: 1245 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1246 exit(1); 1247 } 1248 1249 /* 1250 * SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE command 1251 */ 1252 void 1253 device_smart_autosave(int argc, char *argv[]) 1254 { 1255 struct atareq req; 1256 int val; 1257 1258 if (argc != 2) 1259 goto usage; 1260 1261 memset(&req, 0, sizeof(req)); 1262 1263 req.command = ATAPI_SMART; 1264 req.cylinder = 0xc24f; 1265 req.timeout = 1000; 1266 req.features = ATA_SMART_AUTOSAVE; 1267 if ((val = strtoval(argv[1], smart_autosave)) == -1) 1268 goto usage; 1269 req.sec_num = val; 1270 1271 ata_command(&req); 1272 1273 return; 1274 usage: 1275 fprintf(stderr, "usage: %s device %s enable | disable\n", __progname, 1276 argv[0]); 1277 exit(1); 1278 } 1279 1280 /* 1281 * SMART EXECUTE OFF-LINE IMMEDIATE command 1282 */ 1283 void 1284 device_smart_offline(int argc, char *argv[]) 1285 { 1286 struct atareq req; 1287 int val; 1288 1289 if (argc != 2) 1290 goto usage; 1291 1292 memset(&req, 0, sizeof(req)); 1293 1294 req.command = ATAPI_SMART; 1295 req.cylinder = 0xc24f; 1296 req.timeout = 1000; 1297 req.features = ATA_SMART_OFFLINE; 1298 if ((val = strtoval(argv[1], smart_offline)) == -1) 1299 goto usage; 1300 req.sec_num = val; 1301 1302 ata_command(&req); 1303 1304 return; 1305 usage: 1306 fprintf(stderr, "usage: %s device %s subcommand\n", __progname, 1307 argv[0]); 1308 exit(1); 1309 } 1310 1311 /* 1312 * SMART READ DATA command 1313 */ 1314 void 1315 device_smart_read(int argc, char *argv[]) 1316 { 1317 struct atareq req; 1318 struct smart_read data; 1319 1320 if (argc != 1) 1321 goto usage; 1322 1323 memset(&req, 0, sizeof(req)); 1324 memset(&data, 0, sizeof(data)); 1325 1326 req.command = ATAPI_SMART; 1327 req.cylinder = 0xc24f; 1328 req.timeout = 1000; 1329 req.features = ATA_SMART_READ; 1330 req.flags = ATACMD_READ; 1331 req.databuf = (caddr_t)&data; 1332 req.datalen = sizeof(data); 1333 1334 ata_command(&req); 1335 1336 if (smart_cksum((u_int8_t *)&data, sizeof(data)) != 0) 1337 errx(1, "Checksum mismatch"); 1338 1339 printf("Off-line data collection:\n"); 1340 printf(" status: %s\n", 1341 valtostr(data.offstat & 0x7f, smart_offstat)); 1342 printf(" activity completion time: %d seconds\n", 1343 letoh16(data.time)); 1344 printf(" capabilities:\n"); 1345 print_bitinfo("\t%s\n", data.offcap, smart_offcap); 1346 printf("Self-test execution:\n"); 1347 printf(" status: %s\n", valtostr(SMART_SELFSTAT_STAT(data.selfstat), 1348 smart_selfstat)); 1349 if (SMART_SELFSTAT_STAT(data.selfstat) == SMART_SELFSTAT_PROGRESS) 1350 printf("remains %d%% of total time\n", 1351 SMART_SELFSTAT_PCNT(data.selfstat)); 1352 printf(" recommended polling time:\n"); 1353 printf("\tshort routine: %d minutes\n", data.shtime); 1354 printf("\textended routine: %d minutes\n", data.extime); 1355 printf("SMART capabilities:\n"); 1356 print_bitinfo(" %s\n", letoh16(data.smartcap), smart_smartcap); 1357 printf("Error logging: "); 1358 if (data.errcap & SMART_ERRCAP_ERRLOG) 1359 printf("supported\n"); 1360 else 1361 printf("not supported\n"); 1362 1363 return; 1364 usage: 1365 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1366 exit(1); 1367 } 1368 1369 /* 1370 * SMART READ LOG command 1371 */ 1372 void 1373 device_smart_readlog(int argc, char *argv[]) 1374 { 1375 struct atareq req; 1376 int val; 1377 u_int8_t inbuf[DEV_BSIZE]; 1378 1379 if (argc != 2) 1380 goto usage; 1381 1382 memset(&req, 0, sizeof(req)); 1383 memset(&inbuf, 0, sizeof(inbuf)); 1384 1385 req.command = ATAPI_SMART; 1386 req.cylinder = 0xc24f; 1387 req.timeout = 1000; 1388 req.features = ATA_SMART_READLOG; 1389 req.flags = ATACMD_READ; 1390 req.sec_count = 1; 1391 req.databuf = (caddr_t)inbuf; 1392 req.datalen = sizeof(inbuf); 1393 if ((val = strtoval(argv[1], smart_readlog)) == -1) 1394 goto usage; 1395 req.sec_num = val; 1396 1397 ata_command(&req); 1398 1399 if (strcmp(argv[1], "directory") == 0) { 1400 struct smart_log_dir *data = (struct smart_log_dir *)inbuf; 1401 int i; 1402 1403 if (data->version != SMART_LOG_MSECT) { 1404 printf("Device doesn't support multi-sector logs\n"); 1405 return; 1406 } 1407 1408 for (i = 0; i < 255; i++) 1409 printf("Log address %d: %d sectors\n", i + 1, 1410 data->entry[i].sec_num); 1411 } else if (strcmp(argv[1], "summary") == 0) { 1412 struct smart_log_sum *data = (struct smart_log_sum *)inbuf; 1413 int i, n, nerr; 1414 1415 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1416 errx(1, "Checksum mismatch"); 1417 1418 if (data->index == 0) { 1419 printf("No log entries\n"); 1420 return; 1421 } 1422 1423 nerr = letoh16(data->err_cnt); 1424 printf("Error count: %d\n\n", nerr); 1425 /* 1426 * Five error log data structures form a circular 1427 * buffer. data->index points to the most recent 1428 * record and err_cnt contains total error number. 1429 * We pass from the most recent record to the 1430 * latest one. 1431 */ 1432 i = data->index - 1; 1433 n = 0; 1434 do { 1435 printf("Error %d:\n", n + 1); 1436 smart_print_errdata(&data->errdata[i--]); 1437 if (i == -1) 1438 i = 4; 1439 } while (++n < (nerr > 5 ? 5 : nerr)); 1440 } else if (strcmp(argv[1], "comp") == 0) { 1441 struct smart_log_comp *data = (struct smart_log_comp *)inbuf; 1442 u_int8_t *newbuf; 1443 int i, n, nerr, nsect; 1444 1445 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1446 errx(1, "Checksum mismatch"); 1447 1448 if (data->index == 0) { 1449 printf("No log entries\n"); 1450 return; 1451 } 1452 1453 i = data->index - 1; 1454 nerr = letoh16(data->err_cnt); 1455 printf("Error count: %d\n", nerr); 1456 /* 1457 * From the first sector we obtain total error number 1458 * and calculate necessary number of sectors to read. 1459 * All read error data structures form a circular 1460 * buffer and we pass from the most recent record to 1461 * the latest one. 1462 */ 1463 nsect = nerr / 5 + (nerr % 5 != 0 ? 1 : 0); 1464 if ((newbuf = (u_int8_t *)calloc(nsect, DEV_BSIZE)) == NULL) 1465 err(1, "calloc()"); 1466 memset(&req, 0, sizeof(req)); 1467 req.flags = ATACMD_READ; 1468 req.command = ATAPI_SMART; 1469 req.features = ATA_SMART_READLOG; 1470 req.sec_count = nsect; 1471 req.sec_num = SMART_READLOG_COMP; 1472 req.cylinder = 0xc24f; 1473 req.databuf = (caddr_t)newbuf; 1474 req.datalen = nsect * DEV_BSIZE; 1475 req.timeout = 1000; 1476 ata_command(&req); 1477 1478 n = 0; 1479 data = (struct smart_log_comp *) 1480 (newbuf + (nsect - 1) * DEV_BSIZE); 1481 do { 1482 printf("Error %d:\n", n + 1); 1483 smart_print_errdata(&data->errdata[i-- % 5]); 1484 if (i == -1) 1485 i = 254; 1486 if (i % 5 == 4) 1487 data = (struct smart_log_comp *) 1488 (newbuf + (i / 5) * DEV_BSIZE); 1489 } while (++n < nerr); 1490 } else if (strcmp(argv[1], "selftest") == 0) { 1491 struct smart_log_self *data = (struct smart_log_self *)inbuf; 1492 int i, n; 1493 1494 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1495 errx(1, "Checksum mismatch"); 1496 1497 if (data->index == 0) { 1498 printf("No log entries\n"); 1499 return; 1500 } 1501 1502 /* circular buffer of 21 entries */ 1503 i = data->index - 1; 1504 n = 0; 1505 do { 1506 /* don't print empty entries */ 1507 if ((data->desc[i].time1 | data->desc[i].time2) == 0) 1508 break; 1509 printf("Test %d\n", n + 1); 1510 printf(" LBA Low: 0x%x\n", data->desc[i].reg_lbalo); 1511 printf(" status: %s\n", 1512 valtostr(SMART_SELFSTAT_STAT( 1513 data->desc[i].selfstat), 1514 smart_selfstat)); 1515 printf(" timestamp: %d\n", 1516 MAKEWORD(data->desc[i].time1, 1517 data->desc[i].time2)); 1518 printf(" failure checkpoint byte: 0x%x\n", 1519 data->desc[i].chkpnt); 1520 printf(" failing LBA: 0x%x\n", 1521 MAKEDWORD(data->desc[i].lbafail1, 1522 data->desc[i].lbafail2, 1523 data->desc[i].lbafail3, 1524 data->desc[i].lbafail4)); 1525 if (--i == -1) 1526 i = 20; 1527 } while (++n < 21); 1528 } 1529 1530 return; 1531 usage: 1532 fprintf(stderr, "usage: %s device %s log\n", __progname, argv[0]); 1533 exit(1); 1534 } 1535 1536 #define SMART_PRINTREG(str, reg) \ 1537 printf(str "0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n", \ 1538 data->cmd[0].reg, \ 1539 data->cmd[1].reg, \ 1540 data->cmd[2].reg, \ 1541 data->cmd[3].reg, \ 1542 data->cmd[4].reg) 1543 1544 void 1545 smart_print_errdata(struct smart_log_errdata *data) 1546 { 1547 printf(" error register: 0x%x\n", data->err.reg_err); 1548 printf(" sector count register: 0x%x\n", data->err.reg_seccnt); 1549 printf(" LBA Low register: 0x%x\n", data->err.reg_lbalo); 1550 printf(" LBA Mid register: 0x%x\n", data->err.reg_lbamid); 1551 printf(" LBA High register: 0x%x\n", data->err.reg_lbahi); 1552 printf(" device register: 0x%x\n", data->err.reg_dev); 1553 printf(" status register: 0x%x\n", data->err.reg_stat); 1554 printf(" state: %s\n", valtostr(data->err.state, smart_logstat)); 1555 printf(" timestamp: %d\n", MAKEWORD(data->err.time1, 1556 data->err.time2)); 1557 printf(" history:\n"); 1558 SMART_PRINTREG("\tcontrol register:\t", reg_ctl); 1559 SMART_PRINTREG("\tfeatures register:\t", reg_feat); 1560 SMART_PRINTREG("\tsector count register:\t", reg_seccnt); 1561 SMART_PRINTREG("\tLBA Low register:\t", reg_lbalo); 1562 SMART_PRINTREG("\tLBA Mid register:\t", reg_lbamid); 1563 SMART_PRINTREG("\tLBA High register:\t", reg_lbahi); 1564 SMART_PRINTREG("\tdevice register:\t", reg_dev); 1565 SMART_PRINTREG("\tcommand register:\t", reg_cmd); 1566 printf("\ttimestamp:\t\t" 1567 "%d\t%d\t%d\t%d\t%d\n", 1568 MAKEDWORD(data->cmd[0].time1, data->cmd[0].time2, 1569 data->cmd[0].time3, data->cmd[0].time4), 1570 MAKEDWORD(data->cmd[1].time1, data->cmd[1].time2, 1571 data->cmd[1].time3, data->cmd[1].time4), 1572 MAKEDWORD(data->cmd[2].time1, data->cmd[2].time2, 1573 data->cmd[2].time3, data->cmd[2].time4), 1574 MAKEDWORD(data->cmd[3].time1, data->cmd[3].time2, 1575 data->cmd[3].time3, data->cmd[3].time4), 1576 MAKEDWORD(data->cmd[4].time1, data->cmd[4].time2, 1577 data->cmd[4].time3, data->cmd[4].time4)); 1578 } 1579 1580 int 1581 smart_cksum(u_int8_t *data, size_t len) 1582 { 1583 u_int8_t sum = 0; 1584 size_t i; 1585 1586 for (i = 0; i < len; i++) 1587 sum += data[i]; 1588 1589 return (sum); 1590 } 1591 1592 /* 1593 * Read device attributes 1594 */ 1595 void 1596 device_attr(int argc, char *argv[]) 1597 { 1598 struct atareq req; 1599 struct smart_read attr_val; 1600 struct smart_threshold attr_thr; 1601 struct attribute *attr; 1602 struct threshold *thr; 1603 const char *attr_name; 1604 static const char hex[]="0123456789abcdef"; 1605 char raw[13], *format; 1606 int i, k, threshold_exceeded = 0; 1607 1608 if (argc != 1) 1609 goto usage; 1610 1611 memset(&req, 0, sizeof(req)); 1612 memset(&attr_val, 0, sizeof(attr_val)); /* XXX */ 1613 memset(&attr_thr, 0, sizeof(attr_thr)); /* XXX */ 1614 1615 req.command = ATAPI_SMART; 1616 req.cylinder = 0xc24f; /* LBA High = C2h, LBA Mid = 4Fh */ 1617 req.timeout = 1000; 1618 1619 req.features = ATA_SMART_READ; 1620 req.flags = ATACMD_READ; 1621 req.databuf = (caddr_t)&attr_val; 1622 req.datalen = sizeof(attr_val); 1623 ata_command(&req); 1624 1625 req.features = ATA_SMART_THRESHOLD; 1626 req.flags = ATACMD_READ; 1627 req.databuf = (caddr_t)&attr_thr; 1628 req.datalen = sizeof(attr_thr); 1629 ata_command(&req); 1630 1631 if (attr_val.revision != attr_thr.revision) { 1632 /* 1633 * Non standard vendor implementation. 1634 * Return, since we don't know how to use this. 1635 */ 1636 return; 1637 } 1638 1639 attr = attr_val.attribute; 1640 thr = attr_thr.threshold; 1641 1642 printf("Attributes table revision: %d\n", attr_val.revision); 1643 printf("ID\tAttribute name\t\t\tThreshold\tValue\tRaw\n"); 1644 for (i = 0; i < 30; i++) { 1645 if (thr[i].id != 0 && thr[i].id == attr[i].id) { 1646 attr_name = valtostr(thr[i].id, ibm_attr_names); 1647 if (attr_name == NULL) 1648 attr_name = "Unknown"; 1649 1650 for (k = 0; k < 6; k++) { 1651 u_int8_t b; 1652 b = attr[i].raw[6 - k]; 1653 raw[k + k] = hex[b >> 4]; 1654 raw[k + k + 1] = hex[b & 0x0f]; 1655 } 1656 raw[k + k] = '\0'; 1657 if (thr[i].value >= attr[i].value) { 1658 ++threshold_exceeded; 1659 format = "%3d *%-32.32s %3d\t\t%3d\t0x%s\n"; 1660 } else { 1661 format = "%3d\t%-32.32s %3d\t\t%3d\t0x%s\n"; 1662 } 1663 printf(format, thr[i].id, attr_name, 1664 thr[i].value, attr[i].value, raw); 1665 } 1666 } 1667 if (threshold_exceeded) 1668 fprintf(stderr, "One or more threshold values exceeded!\n"); 1669 1670 return; 1671 1672 usage: 1673 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1674 exit(1); 1675 } 1676 1677 /* 1678 * Set the automatic acoustic management on the disk. 1679 */ 1680 void 1681 device_acoustic(int argc, char *argv[]) 1682 { 1683 u_char acoustic; 1684 struct atareq req; 1685 const char *errstr; 1686 1687 if (argc != 2) 1688 goto usage; 1689 1690 acoustic = strtonum(argv[1], 0, 126, &errstr); 1691 if (errstr) 1692 errx(1, "Acoustic management value \"%s\" is %s " 1693 "(valid values: 0 - 126)", argv[1], errstr); 1694 1695 memset(&req, 0, sizeof(req)); 1696 1697 req.sec_count = acoustic + 0x80; 1698 1699 req.command = SET_FEATURES ; 1700 req.features = WDSF_AAM_EN ; 1701 req.timeout = 1000; 1702 1703 ata_command(&req); 1704 1705 return; 1706 1707 usage: 1708 fprintf(stderr, "usage: %s device %s acoustic-management-level\n", 1709 __progname, argv[0]); 1710 exit(1); 1711 } 1712 1713 /* 1714 * Set the advanced power managmement on the disk. Power management 1715 * levels are translated from user-range 0-253 to ATAPI levels 1-0xFD 1716 * to keep a uniform interface to the user. 1717 */ 1718 void 1719 device_apm(int argc, char *argv[]) 1720 { 1721 u_char power; 1722 struct atareq req; 1723 const char *errstr; 1724 1725 if (argc != 2) 1726 goto usage; 1727 1728 power = strtonum(argv[1], 0, 253, &errstr); 1729 if (errstr) 1730 errx(1, "Advanced power management value \"%s\" is %s " 1731 "(valid values: 0 - 253)", argv[1], errstr); 1732 1733 memset(&req, 0, sizeof(req)); 1734 1735 req.sec_count = power + 0x01; 1736 1737 req.command = SET_FEATURES ; 1738 req.features = WDSF_APM_EN ; 1739 req.timeout = 1000; 1740 1741 ata_command(&req); 1742 1743 return; 1744 1745 usage: 1746 fprintf(stderr, "usage: %s device %s power-management-level\n", 1747 __progname, argv[0]); 1748 exit(1); 1749 } 1750 1751 /* 1752 * En/disable features (the automatic acoustic managmement, Advanced Power 1753 * Management) on the disk. 1754 */ 1755 void 1756 device_feature(int argc, char *argv[]) 1757 { 1758 struct atareq req; 1759 1760 if (argc != 1) 1761 goto usage; 1762 1763 memset(&req, 0, sizeof(req)); 1764 1765 req.command = SET_FEATURES ; 1766 1767 if (strcmp(argv[0], "acousticdisable") == 0) 1768 req.features = WDSF_AAM_DS; 1769 else if (strcmp(argv[0], "readaheadenable") == 0) 1770 req.features = WDSF_READAHEAD_EN; 1771 else if (strcmp(argv[0], "readaheaddisable") == 0) 1772 req.features = WDSF_READAHEAD_DS; 1773 else if (strcmp(argv[0], "writecacheenable") == 0) 1774 req.features = WDSF_EN_WR_CACHE; 1775 else if (strcmp(argv[0], "writecachedisable") == 0) 1776 req.features = WDSF_WRITE_CACHE_DS; 1777 else if (strcmp(argv[0], "apmdisable") == 0) 1778 req.features = WDSF_APM_DS; 1779 else if (strcmp(argv[0], "podenable") == 0) 1780 req.features = WDSF_POD_EN; 1781 else if (strcmp(argv[0], "poddisable") == 0) 1782 req.features = WDSF_POD_DS; 1783 else if (strcmp(argv[0], "puisenable") == 0) 1784 req.features = WDSF_PUIS_EN; 1785 else if (strcmp(argv[0], "puisdisable") == 0) 1786 req.features = WDSF_PUIS_DS; 1787 else if (strcmp(argv[0], "puisspinup") == 0) 1788 req.features = WDSF_PUIS_SPINUP; 1789 else 1790 goto usage; 1791 1792 req.timeout = 1000; 1793 1794 ata_command(&req); 1795 1796 return; 1797 1798 usage: 1799 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1800 exit(1); 1801 } 1802 1803 /* 1804 * Set the idle timer on the disk. Set it for either idle mode or 1805 * standby mode, depending on how we were invoked. 1806 */ 1807 void 1808 device_setidle(int argc, char *argv[]) 1809 { 1810 unsigned long idle; 1811 struct atareq req; 1812 char *end; 1813 1814 if (argc != 2) 1815 goto usage; 1816 1817 idle = strtoul(argv[1], &end, 0); 1818 1819 if (*end != '\0' || idle > 19800) 1820 errx(1, "Invalid idle time: \"%s\" " 1821 "(valid values: 1 - 19800)", argv[1]); 1822 1823 if (idle != 0 && idle < 5) 1824 errx(1, "Idle timer must be at least 5 seconds"); 1825 1826 memset(&req, 0, sizeof(req)); 1827 1828 if (idle <= 240 * 5) 1829 req.sec_count = idle / 5; 1830 else 1831 req.sec_count = idle / (30 * 60) + 240; 1832 1833 if (strcmp(argv[0], "setstandby") == 0) 1834 req.command = WDCC_STANDBY; 1835 else if (strcmp(argv[0], "setidle") == 0) 1836 req.command = WDCC_IDLE; 1837 else 1838 goto usage; 1839 req.timeout = 1000; 1840 1841 ata_command(&req); 1842 1843 return; 1844 1845 usage: 1846 fprintf(stderr, "usage: %s device %s %s\n", __progname, argv[0], 1847 (strcmp(argv[0], "setidle") == 0) ? "idle-timer" : "standby-timer"); 1848 exit(1); 1849 } 1850 1851 /* 1852 * Query the device for the current power mode 1853 */ 1854 void 1855 device_checkpower(int argc, char *argv[]) 1856 { 1857 struct atareq req; 1858 1859 if (argc != 1) 1860 goto usage; 1861 1862 memset(&req, 0, sizeof(req)); 1863 1864 req.command = WDCC_CHECK_PWR; 1865 req.timeout = 1000; 1866 req.flags = ATACMD_READREG; 1867 1868 ata_command(&req); 1869 1870 printf("Current power status: "); 1871 1872 switch (req.sec_count) { 1873 case 0x00: 1874 printf("Standby mode\n"); 1875 break; 1876 case 0x80: 1877 printf("Idle mode\n"); 1878 break; 1879 case 0xff: 1880 printf("Active mode\n"); 1881 break; 1882 default: 1883 printf("Unknown power code (%02x)\n", req.sec_count); 1884 } 1885 1886 return; 1887 usage: 1888 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1889 exit(1); 1890 } 1891