1 /* $OpenBSD: atactl.c,v 1.41 2008/08/10 17:40:10 sobrado 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 { NULL, 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 { NULL, 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 { NULL, 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 { NULL, 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 { NULL, 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 { 7, "Seek Error Rate" }, 305 { 8, "Seek Time Performance" }, 306 { 9, "Power-on Hours Count" }, 307 { 10, "Spin Retry Count" }, 308 { 12, "Device Power Cycle Count" }, 309 { 192, "Power-off Retract Count" }, 310 { 193, "Load Cycle Count" }, 311 { 194, "Temperature" }, 312 { 196, "Reallocation Event Count" }, 313 { 197, "Current Pending Sector Count" }, 314 { 198, "Off-line Scan Uncorrectable Sector Count" }, 315 { 199, "Ultra DMA CRC Error Count" }, 316 { 0, NULL }, 317 }; 318 319 #define MAKEWORD(b1, b2) \ 320 (b2 << 8 | b1) 321 #define MAKEDWORD(b1, b2, b3, b4) \ 322 (b4 << 24 | b3 << 16 | b2 << 8 | b1) 323 324 int 325 main(int argc, char *argv[]) 326 { 327 struct command *cmdp; 328 char dvname_store[MAXPATHLEN]; 329 330 if (argc < 2) 331 usage(); 332 333 /* 334 * Open the device 335 */ 336 fd = opendisk(argv[1], O_RDWR, dvname_store, sizeof(dvname_store), 0); 337 if (fd == -1) { 338 if (errno == ENOENT) { 339 /* 340 * Device doesn't exist. Probably trying to open 341 * a device which doesn't use disk semantics for 342 * device name. Try again, specifying "cooked", 343 * which leaves off the "r" in front of the device's 344 * name. 345 */ 346 fd = opendisk(argv[1], O_RDWR, dvname_store, 347 sizeof(dvname_store), 1); 348 if (fd == -1) 349 err(1, "%s", argv[1]); 350 } else 351 err(1, "%s", argv[1]); 352 } 353 354 /* Skip program name and device name. */ 355 if (argc != 2) { 356 argv += 2; 357 argc -= 2; 358 } else { 359 argv[1] = "identify"; 360 argv += 1; 361 argc -= 1; 362 } 363 364 /* Look up and call the command. */ 365 for (cmdp = commands; cmdp->cmd_name != NULL; cmdp++) 366 if (strcmp(argv[0], cmdp->cmd_name) == 0) 367 break; 368 if (cmdp->cmd_name == NULL) 369 errx(1, "unknown command: %s", argv[0]); 370 371 (cmdp->cmd_func)(argc, argv); 372 373 return (0); 374 } 375 376 __dead void 377 usage(void) 378 { 379 380 fprintf(stderr, "usage: %s device [command [arg]]\n", __progname); 381 exit(1); 382 } 383 384 /* 385 * Wrapper that calls ATAIOCCOMMAND and checks for errors 386 */ 387 void 388 ata_command(struct atareq *req) 389 { 390 if (ioctl(fd, ATAIOCCOMMAND, req) == -1) 391 err(1, "ATAIOCCOMMAND failed"); 392 393 switch (req->retsts) { 394 395 case ATACMD_OK: 396 return; 397 case ATACMD_TIMEOUT: 398 errx(1, "ATA command timed out"); 399 case ATACMD_DF: 400 errx(1, "ATA device returned a Device Fault"); 401 case ATACMD_ERROR: 402 if (req->error & WDCE_ABRT) 403 errx(1, "ATA device returned Aborted Command"); 404 else 405 errx(1, "ATA device returned error register %0x", 406 req->error); 407 default: 408 errx(1, "ATAIOCCOMMAND returned unknown result code %d", 409 req->retsts); 410 } 411 } 412 413 /* 414 * Print out strings associated with particular bitmasks 415 */ 416 void 417 print_bitinfo(const char *f, u_int bits, struct bitinfo *binfo) 418 { 419 420 for (; binfo->bitmask != NULL; binfo++) 421 if (bits & binfo->bitmask) 422 printf(f, binfo->string); 423 } 424 425 /* 426 * strtoval(): 427 * returns value associated with given string, 428 * if no value found -1 is returned. 429 */ 430 int 431 strtoval(const char *str, struct valinfo *vinfo) 432 { 433 for (; vinfo->string != NULL; vinfo++) 434 if (strcmp(str, vinfo->string) == 0) 435 return (vinfo->value); 436 return (-1); 437 } 438 439 /* 440 * valtostr(): 441 * returns string associated with given value, 442 * if no string found NULL is returned. 443 */ 444 const char * 445 valtostr(int val, struct valinfo *vinfo) 446 { 447 for (; vinfo->string != NULL; vinfo++) 448 if (val == vinfo->value) 449 return (vinfo->string); 450 return (NULL); 451 } 452 453 /* 454 * DEVICE COMMANDS 455 */ 456 457 /* 458 * device dump: 459 * 460 * extract issued ATA requests from the log buffer 461 */ 462 void 463 device_dump(int argc, char *argv[]) 464 { 465 unsigned char buf[131072]; 466 atagettrace_t agt; 467 unsigned int total; 468 unsigned int p = 0; 469 int type; 470 const char *types[] = { NULL, "status", "error", "ATAPI", 471 "ATAPI done", "ATA cmd", "ATA", "select slave", 472 "select master", "register read", "ATA LBA48" }; 473 int num_types = sizeof(types) / sizeof(types[0]); 474 int info; 475 int entrysize; 476 int i; 477 int flags; 478 479 if (argc != 1) 480 goto usage; 481 482 memset(&agt, 0, sizeof(agt)); 483 agt.buf_size = sizeof(buf); 484 agt.buf = buf; 485 486 if (ioctl(fd, ATAIOGETTRACE, &agt) == -1) 487 err(1, "ATAIOGETTRACE failed"); 488 489 total = agt.bytes_copied; 490 491 /* Parse entries */ 492 while (p < total) { 493 type = buf[p++]; 494 if (p >= total) 495 return; 496 if (type <= 0 || type >= num_types) 497 return; 498 499 info = buf[p++]; 500 if (p >= total) 501 return; 502 entrysize = (info & 0x1f); 503 504 printf ("ch %d", (info >> 5) & 0x7); 505 printf(": %s", types[type]); 506 507 switch (type) { 508 case WDCEVENT_STATUS: 509 if (entrysize != 1) 510 return; 511 512 printf(": 0x%x", buf[p]); 513 if (buf[p] & WDCS_BSY) 514 printf(" BSY"); 515 if (buf[p] & WDCS_DRDY) 516 printf(" DRDY"); 517 if (buf[p] & WDCS_DWF) 518 printf(" DWF"); 519 if (buf[p] & WDCS_DSC) 520 printf(" DSC"); 521 if (buf[p] & WDCS_DRQ) 522 printf(" DRQ"); 523 if (buf[p] & WDCS_CORR) 524 printf(" CORR"); 525 if (buf[p] & WDCS_IDX) 526 printf(" IDX"); 527 if (buf[p] & WDCS_ERR) 528 printf(" ERR"); 529 530 p++; 531 entrysize = 0; 532 break; 533 case WDCEVENT_ERROR: 534 if (entrysize != 1) 535 return; 536 537 printf(": 0x%x", buf[p]); 538 if (buf[p] & WDCE_BBK) 539 printf(" BBK/CRC"); 540 if (buf[p] & WDCE_UNC) 541 printf(" UNC"); 542 if (buf[p] & WDCE_MC) 543 printf(" MC"); 544 if (buf[p] & WDCE_IDNF) 545 printf(" IDNF"); 546 if (buf[p] & WDCE_MCR) 547 printf(" MCR"); 548 if (buf[p] & WDCE_ABRT) 549 printf(" ABRT"); 550 if (buf[p] & WDCE_TK0NF) 551 printf(" TK0NF"); 552 if (buf[p] & WDCE_AMNF) 553 printf(" AMNF"); 554 555 p++; 556 entrysize = 0; 557 break; 558 case WDCEVENT_ATAPI_CMD: 559 if (entrysize < 2 || p + 2 > total) 560 return; 561 562 flags = (buf[p] << 8) + buf[p + 1]; 563 printf(": flags 0x%x", flags); 564 if (flags & 0x0100) 565 printf(" MEDIA"); 566 if (flags & 0x0080) 567 printf(" SENSE"); 568 if (flags & 0x0040) 569 printf(" DMA"); 570 if (flags & 0x0020) 571 printf(" POLL"); 572 if (flags & 0x0004) 573 printf(" TIMEOUT"); 574 if (flags & 0x0002) 575 printf(" ATAPI"); 576 577 p += 2; 578 entrysize -= 2; 579 break; 580 case WDCEVENT_ATAPI_DONE: 581 if (entrysize != 3 || p + 3 > total) 582 return; 583 584 flags = (buf[p] << 8) + buf[p + 1]; 585 printf(": flags 0x%x", flags); 586 if (flags & 0x0100) 587 printf(" MEDIA"); 588 if (flags & 0x0080) 589 printf(" SENSE"); 590 if (flags & 0x0040) 591 printf(" DMA"); 592 if (flags & 0x0020) 593 printf(" POLL"); 594 if (flags & 0x0004) 595 printf(" TIMEOUT"); 596 if (flags & 0x0002) 597 printf(" ATAPI"); 598 599 printf(", error 0x%x", buf[p + 2]); 600 switch (buf[p + 2]) { 601 case 1: 602 printf(" (sense)"); 603 break; 604 case 2: 605 printf(" (driver failure)"); 606 break; 607 case 3: 608 printf(" (timeout)"); 609 break; 610 case 4: 611 printf(" (busy)"); 612 break; 613 case 5: 614 printf(" (ATAPI sense)"); 615 break; 616 case 8: 617 printf(" (reset)"); 618 break; 619 } 620 621 p += 3; 622 entrysize = 0; 623 break; 624 case WDCEVENT_ATA_LONG: 625 if (entrysize != 7 || p + 7 > total) 626 return; 627 628 printf(": "); 629 switch (buf[p + 6]) { 630 case WDCC_READDMA: 631 printf("READ DMA"); 632 break; 633 case WDCC_WRITEDMA: 634 printf("WRITE DMA"); 635 break; 636 default: 637 printf("CMD 0x%x", buf[p + 6]); 638 } 639 printf(" head %d, precomp %d, cyl_hi %d, " 640 "cyl_lo %d, sec %d, cnt %d", 641 buf[p], buf[p + 1], buf[p + 2], buf[p + 3], 642 buf[p + 4], buf[p + 5]); 643 644 p += 7; 645 entrysize = 0; 646 break; 647 case WDCEVENT_REG: 648 if (entrysize != 3 || p + 3 > total) 649 return; 650 651 switch (buf[p]) { 652 case 1: 653 printf(": error"); 654 break; 655 case 2: 656 printf(": ireason"); 657 break; 658 case 3: 659 printf(": lba_lo"); 660 break; 661 case 4: 662 printf(": lba_mi"); 663 break; 664 case 5: 665 printf(": lba_hi"); 666 break; 667 case 6: 668 printf(": sdh"); 669 break; 670 case 7: 671 printf(": status"); 672 break; 673 case 8: 674 printf(": altstatus"); 675 break; 676 default: 677 printf(": unknown register %d", buf[p]); 678 } 679 printf(": 0x%x", (buf[p + 1] << 8) + buf[p + 2]); 680 681 p += 3; 682 entrysize = 0; 683 break; 684 case WDCEVENT_ATA_EXT: 685 if (entrysize != 9 || p + 9 > total) 686 return; 687 688 printf(": "); 689 switch (buf[p + 8]) { 690 case WDCC_READDMA_EXT: 691 printf("READ DMA EXT"); 692 break; 693 case WDCC_WRITEDMA_EXT: 694 printf("WRITE DMA EXT"); 695 break; 696 default: 697 printf("CMD 0x%x", buf[p + 8]); 698 } 699 printf(" lba_hi1 %d, lba_hi2 %d, " 700 "lba_mi1 %d, lba_mi2 %d, lba_lo1 %d, lba_lo2 %d, " 701 "count1 %d, count2 %d", 702 buf[p], buf[p + 1], buf[p + 2], buf[p + 3], 703 buf[p + 4], buf[p + 5], buf[p + 6], 704 buf[p + 7]); 705 706 p += 9; 707 entrysize = 0; 708 break; 709 } 710 711 if (entrysize > 0) 712 printf(":"); 713 for (i = 0; i < entrysize; i++) { 714 printf (" 0x%02x", buf[p]); 715 if (++p >= total) 716 break; 717 } 718 printf("\n"); 719 } 720 721 return; 722 723 usage: 724 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 725 exit(1); 726 } 727 728 /* 729 * device_identify: 730 * 731 * Display the identity of the device 732 */ 733 void 734 device_identify(int argc, char *argv[]) 735 { 736 struct ataparams *inqbuf; 737 struct atareq req; 738 char inbuf[DEV_BSIZE]; 739 u_int64_t capacity; 740 u_int8_t *s; 741 742 if (argc != 1) 743 goto usage; 744 745 memset(&inbuf, 0, sizeof(inbuf)); 746 memset(&req, 0, sizeof(req)); 747 748 inqbuf = (struct ataparams *) inbuf; 749 750 req.flags = ATACMD_READ; 751 req.command = WDCC_IDENTIFY; 752 req.databuf = (caddr_t) inbuf; 753 req.datalen = sizeof(inbuf); 754 req.timeout = 1000; 755 756 ata_command(&req); 757 758 if (BYTE_ORDER == BIG_ENDIAN) { 759 swap16_multi((u_int16_t *)inbuf, 10); 760 swap16_multi(((u_int16_t *)inbuf) + 20, 3); 761 swap16_multi(((u_int16_t *)inbuf) + 47, sizeof(inbuf) / 2 - 47); 762 } 763 764 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 765 ((inqbuf->atap_model[0] == 'N' && 766 inqbuf->atap_model[1] == 'E') || 767 (inqbuf->atap_model[0] == 'F' && 768 inqbuf->atap_model[1] == 'X')))) { 769 swap16_multi((u_int16_t *)(inqbuf->atap_model), 770 sizeof(inqbuf->atap_model) / 2); 771 swap16_multi((u_int16_t *)(inqbuf->atap_serial), 772 sizeof(inqbuf->atap_serial) / 2); 773 swap16_multi((u_int16_t *)(inqbuf->atap_revision), 774 sizeof(inqbuf->atap_revision) / 2); 775 } 776 777 /* 778 * Strip blanks off of the info strings. 779 */ 780 781 for (s = &inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1]; 782 s >= inqbuf->atap_model && *s == ' '; s--) 783 *s = '\0'; 784 785 for (s = &inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1]; 786 s >= inqbuf->atap_revision && *s == ' '; s--) 787 *s = '\0'; 788 789 for (s = &inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1]; 790 s >= inqbuf->atap_serial && *s == ' '; s--) 791 *s = '\0'; 792 793 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n", 794 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model, 795 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision, 796 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial); 797 798 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 799 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 800 "removable"); 801 802 if (inqbuf->atap_cmd2_en & ATAPI_CMD2_48AD) 803 capacity = ((u_int64_t)inqbuf->atap_max_lba[3] << 48) | 804 ((u_int64_t)inqbuf->atap_max_lba[2] << 32) | 805 ((u_int64_t)inqbuf->atap_max_lba[1] << 16) | 806 (u_int64_t)inqbuf->atap_max_lba[0]; 807 else 808 capacity = (inqbuf->atap_capacity[1] << 16) | 809 inqbuf->atap_capacity[0]; 810 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 811 "sectors: %llu\n", inqbuf->atap_cylinders, 812 inqbuf->atap_heads, inqbuf->atap_sectors, capacity); 813 814 if ((inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ) && 815 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)) 816 printf("Device supports command queue depth of %d\n", 817 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1); 818 819 printf("Device capabilities:\n"); 820 print_bitinfo("\t%s\n", inqbuf->atap_capabilities1, ata_caps); 821 822 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 823 printf("Device supports the following standards:\n"); 824 print_bitinfo("%s ", inqbuf->atap_ata_major, ata_vers); 825 printf("\n"); 826 } 827 828 if ((inqbuf->atap_cmd_set1 & WDC_CMD1_SEC) && 829 inqbuf->atap_mpasswd_rev != 0 && 830 inqbuf->atap_mpasswd_rev != 0xffff) 831 printf("Master password revision code 0x%04x\n", 832 inqbuf->atap_mpasswd_rev); 833 834 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 835 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 836 printf("Device supports the following command sets:\n"); 837 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set1, ata_cmd_set1); 838 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set2, ata_cmd_set2); 839 print_bitinfo("\t%s\n", inqbuf->atap_cmd_ext, ata_cmd_ext); 840 } 841 842 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 843 printf("Device has enabled the following command " 844 "sets/features:\n"); 845 print_bitinfo("\t%s\n", inqbuf->atap_cmd1_en, ata_cmd_set1); 846 print_bitinfo("\t%s\n", inqbuf->atap_cmd2_en, ata_cmd_set2); 847 } 848 849 return; 850 851 usage: 852 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 853 exit(1); 854 } 855 856 /* 857 * device idle: 858 * 859 * issue the IDLE IMMEDIATE command to the drive 860 */ 861 void 862 device_idle(int argc, char *argv[]) 863 { 864 struct atareq req; 865 866 if (argc != 1) 867 goto usage; 868 869 memset(&req, 0, sizeof(req)); 870 871 if (strcmp(argv[0], "idle") == 0) 872 req.command = WDCC_IDLE_IMMED; 873 else if (strcmp(argv[0], "standby") == 0) 874 req.command = WDCC_STANDBY_IMMED; 875 else 876 req.command = WDCC_SLEEP; 877 878 req.timeout = 1000; 879 880 ata_command(&req); 881 882 return; 883 usage: 884 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 885 exit(1); 886 } 887 888 /* 889 * SECURITY SET PASSWORD command 890 */ 891 void 892 device_sec_setpass(int argc, char *argv[]) 893 { 894 struct atareq req; 895 struct sec_password pwd; 896 char *pass, inbuf[DEV_BSIZE]; 897 struct ataparams *inqbuf = (struct ataparams *)inbuf; 898 899 if (argc < 2) 900 goto usage; 901 902 memset(&pwd, 0, sizeof(pwd)); 903 904 if (strcmp(argv[1], "user") == 0 && argc == 3) 905 pwd.ctrl |= SEC_PASSWORD_USER; 906 else if (strcmp(argv[1], "master") == 0 && argc == 2) 907 pwd.ctrl |= SEC_PASSWORD_MASTER; 908 else 909 goto usage; 910 if (argc == 3) { 911 if (strcmp(argv[2], "high") == 0) 912 pwd.ctrl |= SEC_LEVEL_HIGH; 913 else if (strcmp(argv[2], "maximum") == 0) 914 pwd.ctrl |= SEC_LEVEL_MAX; 915 else 916 goto usage; 917 } 918 919 /* 920 * Issue IDENTIFY command to obtain master password 921 * revision code and decrement its value. 922 * The valid revision codes are 0x0001 through 0xfffe. 923 * If the device returns 0x0000 or 0xffff as a revision 924 * code then the master password revision code is not 925 * supported so don't touch it. 926 */ 927 memset(&inbuf, 0, sizeof(inbuf)); 928 memset(&req, 0, sizeof(req)); 929 930 req.command = WDCC_IDENTIFY; 931 req.timeout = 1000; 932 req.flags = ATACMD_READ; 933 req.databuf = (caddr_t)inbuf; 934 req.datalen = sizeof(inbuf); 935 936 ata_command(&req); 937 938 pwd.revision = inqbuf->atap_mpasswd_rev; 939 if (pwd.revision != 0 && pwd.revision != 0xffff && --pwd.revision == 0) 940 pwd.revision = 0xfffe; 941 942 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 1); 943 memcpy(pwd.password, pass, strlen(pass)); 944 945 memset(&req, 0, sizeof(req)); 946 947 req.command = ATA_SEC_SET_PASSWORD; 948 req.timeout = 1000; 949 req.flags = ATACMD_WRITE; 950 req.databuf = (caddr_t)&pwd; 951 req.datalen = sizeof(pwd); 952 953 ata_command(&req); 954 955 return; 956 usage: 957 fprintf(stderr, "usage: %s device %s user high | maximum\n", 958 __progname, argv[0]); 959 fprintf(stderr, " %s device %s master\n", __progname, argv[0]); 960 exit(1); 961 } 962 963 /* 964 * SECURITY UNLOCK command 965 */ 966 void 967 device_sec_unlock(int argc, char *argv[]) 968 { 969 struct atareq req; 970 struct sec_password pwd; 971 char *pass; 972 973 if (argc != 2) 974 goto usage; 975 976 memset(&pwd, 0, sizeof(pwd)); 977 978 if (strcmp(argv[1], "user") == 0) 979 pwd.ctrl |= SEC_PASSWORD_USER; 980 else if (strcmp(argv[1], "master") == 0) 981 pwd.ctrl |= SEC_PASSWORD_MASTER; 982 else 983 goto usage; 984 985 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 986 memcpy(pwd.password, pass, strlen(pass)); 987 988 memset(&req, 0, sizeof(req)); 989 990 req.command = ATA_SEC_UNLOCK; 991 req.timeout = 1000; 992 req.flags = ATACMD_WRITE; 993 req.databuf = (caddr_t)&pwd; 994 req.datalen = sizeof(pwd); 995 996 ata_command(&req); 997 998 return; 999 usage: 1000 fprintf(stderr, "usage: %s device %s user | master\n", __progname, 1001 argv[0]); 1002 exit(1); 1003 } 1004 1005 /* 1006 * SECURITY ERASE UNIT command 1007 */ 1008 void 1009 device_sec_erase(int argc, char *argv[]) 1010 { 1011 struct atareq req; 1012 struct sec_password pwd; 1013 char *pass; 1014 1015 if (argc < 2) 1016 goto usage; 1017 1018 memset(&pwd, 0, sizeof(pwd)); 1019 1020 if (strcmp(argv[1], "user") == 0) 1021 pwd.ctrl |= SEC_PASSWORD_USER; 1022 else if (strcmp(argv[1], "master") == 0) 1023 pwd.ctrl |= SEC_PASSWORD_MASTER; 1024 else 1025 goto usage; 1026 if (argc == 2) 1027 pwd.ctrl |= SEC_ERASE_NORMAL; 1028 else if (argc == 3 && strcmp(argv[2], "enhanced") == 0) 1029 pwd.ctrl |= SEC_ERASE_ENHANCED; 1030 else 1031 goto usage; 1032 1033 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 1034 memcpy(pwd.password, pass, strlen(pass)); 1035 1036 /* Issue SECURITY ERASE PREPARE command before */ 1037 memset(&req, 0, sizeof(req)); 1038 1039 req.command = ATA_SEC_ERASE_PREPARE; 1040 req.timeout = 1000; 1041 1042 ata_command(&req); 1043 1044 memset(&req, 0, sizeof(req)); 1045 1046 req.command = ATA_SEC_ERASE_UNIT; 1047 req.timeout = 1000; 1048 req.flags = ATACMD_WRITE; 1049 req.databuf = (caddr_t)&pwd; 1050 req.datalen = sizeof(pwd); 1051 1052 ata_command(&req); 1053 1054 return; 1055 usage: 1056 fprintf(stderr, "usage: %s device %s user | master [enhanced]\n", 1057 __progname, argv[0]); 1058 exit(1); 1059 } 1060 1061 /* 1062 * SECURITY FREEZE LOCK command 1063 */ 1064 void 1065 device_sec_freeze(int argc, char *argv[]) 1066 { 1067 struct atareq req; 1068 1069 if (argc != 1) 1070 goto usage; 1071 1072 memset(&req, 0, sizeof(req)); 1073 1074 req.command = ATA_SEC_FREEZE_LOCK; 1075 req.timeout = 1000; 1076 1077 ata_command(&req); 1078 1079 return; 1080 usage: 1081 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1082 exit(1); 1083 } 1084 1085 /* 1086 * SECURITY DISABLE PASSWORD command 1087 */ 1088 void 1089 device_sec_disablepass(int argc, char *argv[]) 1090 { 1091 struct atareq req; 1092 struct sec_password pwd; 1093 char *pass; 1094 1095 if (argc != 2) 1096 goto usage; 1097 1098 memset(&pwd, 0, sizeof(pwd)); 1099 1100 if (strcmp(argv[1], "user") == 0) 1101 pwd.ctrl |= SEC_PASSWORD_USER; 1102 else if (strcmp(argv[1], "master") == 0) 1103 pwd.ctrl |= SEC_PASSWORD_MASTER; 1104 else 1105 goto usage; 1106 1107 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0); 1108 memcpy(pwd.password, pass, strlen(pass)); 1109 1110 memset(&req, 0, sizeof(req)); 1111 1112 req.command = ATA_SEC_DISABLE_PASSWORD; 1113 req.timeout = 1000; 1114 req.flags = ATACMD_WRITE; 1115 req.databuf = (caddr_t)&pwd; 1116 req.datalen = sizeof(pwd); 1117 1118 ata_command(&req); 1119 1120 return; 1121 usage: 1122 fprintf(stderr, "usage: %s device %s user | master\n", __progname, 1123 argv[0]); 1124 exit(1); 1125 } 1126 1127 char * 1128 sec_getpass(int ident, int confirm) 1129 { 1130 char *pass, buf[33]; 1131 1132 if ((pass = getpass(ident ? "Master password:" : 1133 "User password:")) == NULL) 1134 err(1, "getpass()"); 1135 if (strlen(pass) > 32) 1136 errx(1, "password too long"); 1137 if (confirm) { 1138 strlcpy(buf, pass, sizeof(buf)); 1139 if ((pass = getpass(ident ? "Retype master password:" : 1140 "Retype user password:")) == NULL) 1141 err(1, "getpass()"); 1142 if (strcmp(pass, buf) != 0) 1143 errx(1, "password mismatch"); 1144 } 1145 1146 return (pass); 1147 } 1148 1149 /* 1150 * SMART ENABLE OPERATIONS command 1151 */ 1152 void 1153 device_smart_enable(int argc, char *argv[]) 1154 { 1155 struct atareq req; 1156 1157 if (argc != 1) 1158 goto usage; 1159 1160 memset(&req, 0, sizeof(req)); 1161 1162 req.command = ATAPI_SMART; 1163 req.cylinder = 0xc24f; 1164 req.timeout = 1000; 1165 req.features = ATA_SMART_EN; 1166 1167 ata_command(&req); 1168 1169 return; 1170 usage: 1171 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1172 exit(1); 1173 } 1174 1175 /* 1176 * SMART DISABLE OPERATIONS command 1177 */ 1178 void 1179 device_smart_disable(int argc, char *argv[]) 1180 { 1181 struct atareq req; 1182 1183 if (argc != 1) 1184 goto usage; 1185 1186 memset(&req, 0, sizeof(req)); 1187 1188 req.command = ATAPI_SMART; 1189 req.cylinder = 0xc24f; 1190 req.timeout = 1000; 1191 req.features = ATA_SMART_DS; 1192 1193 ata_command(&req); 1194 1195 return; 1196 usage: 1197 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1198 exit(1); 1199 } 1200 1201 /* 1202 * SMART STATUS command 1203 */ 1204 void 1205 device_smart_status(int argc, char *argv[]) 1206 { 1207 struct atareq req; 1208 1209 if (argc != 1) 1210 goto usage; 1211 1212 memset(&req, 0, sizeof(req)); 1213 1214 req.command = ATAPI_SMART; 1215 req.cylinder = 0xc24f; 1216 req.timeout = 1000; 1217 req.features = ATA_SMART_STATUS; 1218 1219 ata_command(&req); 1220 1221 if (req.cylinder == 0xc24f) 1222 printf("No SMART threshold exceeded\n"); 1223 else if (req.cylinder == 0x2cf4) { 1224 errx(2, "SMART threshold exceeded!"); 1225 } else { 1226 errx(1, "Unknown response %02x!", req.cylinder); 1227 } 1228 1229 return; 1230 usage: 1231 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1232 exit(1); 1233 } 1234 1235 /* 1236 * SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE command 1237 */ 1238 void 1239 device_smart_autosave(int argc, char *argv[]) 1240 { 1241 struct atareq req; 1242 int val; 1243 1244 if (argc != 2) 1245 goto usage; 1246 1247 memset(&req, 0, sizeof(req)); 1248 1249 req.command = ATAPI_SMART; 1250 req.cylinder = 0xc24f; 1251 req.timeout = 1000; 1252 req.features = ATA_SMART_AUTOSAVE; 1253 if ((val = strtoval(argv[1], smart_autosave)) == -1) 1254 goto usage; 1255 req.sec_num = val; 1256 1257 ata_command(&req); 1258 1259 return; 1260 usage: 1261 fprintf(stderr, "usage: %s device %s enable | disable\n", __progname, 1262 argv[0]); 1263 exit(1); 1264 } 1265 1266 /* 1267 * SMART EXECUTE OFF-LINE IMMEDIATE command 1268 */ 1269 void 1270 device_smart_offline(int argc, char *argv[]) 1271 { 1272 struct atareq req; 1273 int val; 1274 1275 if (argc != 2) 1276 goto usage; 1277 1278 memset(&req, 0, sizeof(req)); 1279 1280 req.command = ATAPI_SMART; 1281 req.cylinder = 0xc24f; 1282 req.timeout = 1000; 1283 req.features = ATA_SMART_OFFLINE; 1284 if ((val = strtoval(argv[1], smart_offline)) == -1) 1285 goto usage; 1286 req.sec_num = val; 1287 1288 ata_command(&req); 1289 1290 return; 1291 usage: 1292 fprintf(stderr, "usage: %s device %s subcommand\n", __progname, 1293 argv[0]); 1294 exit(1); 1295 } 1296 1297 /* 1298 * SMART READ DATA command 1299 */ 1300 void 1301 device_smart_read(int argc, char *argv[]) 1302 { 1303 struct atareq req; 1304 struct smart_read data; 1305 1306 if (argc != 1) 1307 goto usage; 1308 1309 memset(&req, 0, sizeof(req)); 1310 memset(&data, 0, sizeof(data)); 1311 1312 req.command = ATAPI_SMART; 1313 req.cylinder = 0xc24f; 1314 req.timeout = 1000; 1315 req.features = ATA_SMART_READ; 1316 req.flags = ATACMD_READ; 1317 req.databuf = (caddr_t)&data; 1318 req.datalen = sizeof(data); 1319 1320 ata_command(&req); 1321 1322 if (smart_cksum((u_int8_t *)&data, sizeof(data)) != 0) 1323 errx(1, "Checksum mismatch"); 1324 1325 printf("Off-line data collection:\n"); 1326 printf(" status: %s\n", 1327 valtostr(data.offstat & 0x7f, smart_offstat)); 1328 printf(" activity completion time: %d seconds\n", 1329 letoh16(data.time)); 1330 printf(" capabilities:\n"); 1331 print_bitinfo("\t%s\n", data.offcap, smart_offcap); 1332 printf("Self-test execution:\n"); 1333 printf(" status: %s\n", valtostr(SMART_SELFSTAT_STAT(data.selfstat), 1334 smart_selfstat)); 1335 if (SMART_SELFSTAT_STAT(data.selfstat) == SMART_SELFSTAT_PROGRESS) 1336 printf("remains %d%% of total time\n", 1337 SMART_SELFSTAT_PCNT(data.selfstat)); 1338 printf(" recommended polling time:\n"); 1339 printf("\tshort routine: %d minutes\n", data.shtime); 1340 printf("\textended routine: %d minutes\n", data.extime); 1341 printf("SMART capabilities:\n"); 1342 print_bitinfo(" %s\n", letoh16(data.smartcap), smart_smartcap); 1343 printf("Error logging: "); 1344 if (data.errcap & SMART_ERRCAP_ERRLOG) 1345 printf("supported\n"); 1346 else 1347 printf("not supported\n"); 1348 1349 return; 1350 usage: 1351 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1352 exit(1); 1353 } 1354 1355 /* 1356 * SMART READ LOG command 1357 */ 1358 void 1359 device_smart_readlog(int argc, char *argv[]) 1360 { 1361 struct atareq req; 1362 int val; 1363 u_int8_t inbuf[DEV_BSIZE]; 1364 1365 if (argc != 2) 1366 goto usage; 1367 1368 memset(&req, 0, sizeof(req)); 1369 memset(&inbuf, 0, sizeof(inbuf)); 1370 1371 req.command = ATAPI_SMART; 1372 req.cylinder = 0xc24f; 1373 req.timeout = 1000; 1374 req.features = ATA_SMART_READLOG; 1375 req.flags = ATACMD_READ; 1376 req.sec_count = 1; 1377 req.databuf = (caddr_t)inbuf; 1378 req.datalen = sizeof(inbuf); 1379 if ((val = strtoval(argv[1], smart_readlog)) == -1) 1380 goto usage; 1381 req.sec_num = val; 1382 1383 ata_command(&req); 1384 1385 if (strcmp(argv[1], "directory") == 0) { 1386 struct smart_log_dir *data = (struct smart_log_dir *)inbuf; 1387 int i; 1388 1389 if (data->version != SMART_LOG_MSECT) { 1390 printf("Device doesn't support multi-sector logs\n"); 1391 return; 1392 } 1393 1394 for (i = 0; i < 255; i++) 1395 printf("Log address %d: %d sectors\n", i + 1, 1396 data->entry[i].sec_num); 1397 } else if (strcmp(argv[1], "summary") == 0) { 1398 struct smart_log_sum *data = (struct smart_log_sum *)inbuf; 1399 int i, n, nerr; 1400 1401 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1402 errx(1, "Checksum mismatch"); 1403 1404 if (data->index == 0) { 1405 printf("No log entries\n"); 1406 return; 1407 } 1408 1409 nerr = letoh16(data->err_cnt); 1410 printf("Error count: %d\n\n", nerr); 1411 /* 1412 * Five error log data structures form a circular 1413 * buffer. data->index points to the most recent 1414 * record and err_cnt contains total error number. 1415 * We pass from the most recent record to the 1416 * latest one. 1417 */ 1418 i = data->index - 1; 1419 n = 0; 1420 do { 1421 printf("Error %d:\n", n + 1); 1422 smart_print_errdata(&data->errdata[i--]); 1423 if (i == -1) 1424 i = 4; 1425 } while (++n < (nerr > 5 ? 5 : nerr)); 1426 } else if (strcmp(argv[1], "comp") == 0) { 1427 struct smart_log_comp *data = (struct smart_log_comp *)inbuf; 1428 u_int8_t *newbuf; 1429 int i, n, nerr, nsect; 1430 1431 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1432 errx(1, "Checksum mismatch"); 1433 1434 if (data->index == 0) { 1435 printf("No log entries\n"); 1436 return; 1437 } 1438 1439 i = data->index - 1; 1440 nerr = letoh16(data->err_cnt); 1441 printf("Error count: %d\n", nerr); 1442 /* 1443 * From the first sector we obtain total error number 1444 * and calculate necessary number of sectors to read. 1445 * All read error data structures form a circular 1446 * buffer and we pass from the most recent record to 1447 * the latest one. 1448 */ 1449 nsect = nerr / 5 + (nerr % 5 != 0 ? 1 : 0); 1450 if ((newbuf = (u_int8_t *)calloc(nsect, DEV_BSIZE)) == NULL) 1451 err(1, "calloc()"); 1452 memset(&req, 0, sizeof(req)); 1453 req.flags = ATACMD_READ; 1454 req.command = ATAPI_SMART; 1455 req.features = ATA_SMART_READLOG; 1456 req.sec_count = nsect; 1457 req.sec_num = SMART_READLOG_COMP; 1458 req.cylinder = 0xc24f; 1459 req.databuf = (caddr_t)newbuf; 1460 req.datalen = nsect * DEV_BSIZE; 1461 req.timeout = 1000; 1462 ata_command(&req); 1463 1464 n = 0; 1465 data = (struct smart_log_comp *) 1466 (newbuf + (nsect - 1) * DEV_BSIZE); 1467 do { 1468 printf("Error %d:\n", n + 1); 1469 smart_print_errdata(&data->errdata[i-- % 5]); 1470 if (i == -1) 1471 i = 254; 1472 if (i % 5 == 4) 1473 data = (struct smart_log_comp *) 1474 (newbuf + (i / 5) * DEV_BSIZE); 1475 } while (++n < nerr); 1476 } else if (strcmp(argv[1], "selftest") == 0) { 1477 struct smart_log_self *data = (struct smart_log_self *)inbuf; 1478 int i, n; 1479 1480 if (smart_cksum(inbuf, sizeof(inbuf)) != 0) 1481 errx(1, "Checksum mismatch"); 1482 1483 if (data->index == 0) { 1484 printf("No log entries\n"); 1485 return; 1486 } 1487 1488 /* circular buffer of 21 entries */ 1489 i = data->index - 1; 1490 n = 0; 1491 do { 1492 /* don't print empty entries */ 1493 if ((data->desc[i].time1 | data->desc[i].time2) == 0) 1494 break; 1495 printf("Test %d\n", n + 1); 1496 printf(" LBA Low: 0x%x\n", data->desc[i].reg_lbalo); 1497 printf(" status: %s\n", 1498 valtostr(SMART_SELFSTAT_STAT( 1499 data->desc[i].selfstat), 1500 smart_selfstat)); 1501 printf(" timestamp: %d\n", 1502 MAKEWORD(data->desc[i].time1, 1503 data->desc[i].time2)); 1504 printf(" failure checkpoint byte: 0x%x\n", 1505 data->desc[i].chkpnt); 1506 printf(" failing LBA: 0x%x\n", 1507 MAKEDWORD(data->desc[i].lbafail1, 1508 data->desc[i].lbafail2, 1509 data->desc[i].lbafail3, 1510 data->desc[i].lbafail4)); 1511 if (--i == -1) 1512 i = 20; 1513 } while (++n < 21); 1514 } 1515 1516 return; 1517 usage: 1518 fprintf(stderr, "usage: %s device %s log\n", __progname, argv[0]); 1519 exit(1); 1520 } 1521 1522 #define SMART_PRINTREG(str, reg) \ 1523 printf(str "0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n", \ 1524 data->cmd[0].reg, \ 1525 data->cmd[1].reg, \ 1526 data->cmd[2].reg, \ 1527 data->cmd[3].reg, \ 1528 data->cmd[4].reg) 1529 1530 void 1531 smart_print_errdata(struct smart_log_errdata *data) 1532 { 1533 printf(" error register: 0x%x\n", data->err.reg_err); 1534 printf(" sector count register: 0x%x\n", data->err.reg_seccnt); 1535 printf(" LBA Low register: 0x%x\n", data->err.reg_lbalo); 1536 printf(" LBA Mid register: 0x%x\n", data->err.reg_lbamid); 1537 printf(" LBA High register: 0x%x\n", data->err.reg_lbahi); 1538 printf(" device register: 0x%x\n", data->err.reg_dev); 1539 printf(" status register: 0x%x\n", data->err.reg_stat); 1540 printf(" state: %s\n", valtostr(data->err.state, smart_logstat)); 1541 printf(" timestamp: %d\n", MAKEWORD(data->err.time1, 1542 data->err.time2)); 1543 printf(" history:\n"); 1544 SMART_PRINTREG("\tcontrol register:\t", reg_ctl); 1545 SMART_PRINTREG("\tfeatures register:\t", reg_feat); 1546 SMART_PRINTREG("\tsector count register:\t", reg_seccnt); 1547 SMART_PRINTREG("\tLBA Low register:\t", reg_lbalo); 1548 SMART_PRINTREG("\tLBA Mid register:\t", reg_lbamid); 1549 SMART_PRINTREG("\tLBA High register:\t", reg_lbahi); 1550 SMART_PRINTREG("\tdevice register:\t", reg_dev); 1551 SMART_PRINTREG("\tcommand register:\t", reg_cmd); 1552 printf("\ttimestamp:\t\t" 1553 "%d\t%d\t%d\t%d\t%d\n", 1554 MAKEDWORD(data->cmd[0].time1, data->cmd[0].time2, 1555 data->cmd[0].time3, data->cmd[0].time4), 1556 MAKEDWORD(data->cmd[1].time1, data->cmd[1].time2, 1557 data->cmd[1].time3, data->cmd[1].time4), 1558 MAKEDWORD(data->cmd[2].time1, data->cmd[2].time2, 1559 data->cmd[2].time3, data->cmd[2].time4), 1560 MAKEDWORD(data->cmd[3].time1, data->cmd[3].time2, 1561 data->cmd[3].time3, data->cmd[3].time4), 1562 MAKEDWORD(data->cmd[4].time1, data->cmd[4].time2, 1563 data->cmd[4].time3, data->cmd[4].time4)); 1564 } 1565 1566 int 1567 smart_cksum(u_int8_t *data, size_t len) 1568 { 1569 u_int8_t sum = 0; 1570 size_t i; 1571 1572 for (i = 0; i < len; i++) 1573 sum += data[i]; 1574 1575 return (sum); 1576 } 1577 1578 /* 1579 * Read device attributes 1580 */ 1581 void 1582 device_attr(int argc, char *argv[]) 1583 { 1584 struct atareq req; 1585 struct smart_read attr_val; 1586 struct smart_threshold attr_thr; 1587 struct attribute *attr; 1588 struct threshold *thr; 1589 const char *attr_name; 1590 static const char hex[]="0123456789abcdef"; 1591 char raw[13], *format; 1592 int i, k, threshold_exceeded = 0; 1593 1594 if (argc != 1) 1595 goto usage; 1596 1597 memset(&req, 0, sizeof(req)); 1598 memset(&attr_val, 0, sizeof(attr_val)); /* XXX */ 1599 memset(&attr_thr, 0, sizeof(attr_thr)); /* XXX */ 1600 1601 req.command = ATAPI_SMART; 1602 req.cylinder = 0xc24f; /* LBA High = C2h, LBA Mid = 4Fh */ 1603 req.timeout = 1000; 1604 1605 req.features = ATA_SMART_READ; 1606 req.flags = ATACMD_READ; 1607 req.databuf = (caddr_t)&attr_val; 1608 req.datalen = sizeof(attr_val); 1609 ata_command(&req); 1610 1611 req.features = ATA_SMART_THRESHOLD; 1612 req.flags = ATACMD_READ; 1613 req.databuf = (caddr_t)&attr_thr; 1614 req.datalen = sizeof(attr_thr); 1615 ata_command(&req); 1616 1617 if (attr_val.revision != attr_thr.revision) { 1618 /* 1619 * Non standard vendor implementation. 1620 * Return, since we don't know how to use this. 1621 */ 1622 return; 1623 } 1624 1625 attr = attr_val.attribute; 1626 thr = attr_thr.threshold; 1627 1628 printf("Attributes table revision: %d\n", attr_val.revision); 1629 printf("ID\tAttribute name\t\t\tThreshold\tValue\tRaw\n"); 1630 for (i = 0; i < 30; i++) { 1631 if (thr[i].id != 0 && thr[i].id == attr[i].id) { 1632 attr_name = valtostr(thr[i].id, ibm_attr_names); 1633 if (attr_name == NULL) 1634 attr_name = "Unknown"; 1635 1636 for (k = 0; k < 6; k++) { 1637 u_int8_t b; 1638 b = attr[i].raw[6 - k]; 1639 raw[k + k] = hex[b >> 4]; 1640 raw[k + k + 1] = hex[b & 0x0f]; 1641 } 1642 raw[k + k] = '\0'; 1643 if (thr[i].value >= attr[i].value) { 1644 ++threshold_exceeded; 1645 format = "%3d *%-32.32s %3d\t\t%3d\t0x%s\n"; 1646 } else { 1647 format = "%3d\t%-32.32s %3d\t\t%3d\t0x%s\n"; 1648 } 1649 printf(format, thr[i].id, attr_name, 1650 thr[i].value, attr[i].value, raw); 1651 } 1652 } 1653 if (threshold_exceeded) 1654 fprintf(stderr, "One or more threshold values exceeded!\n"); 1655 1656 return; 1657 1658 usage: 1659 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1660 exit(1); 1661 } 1662 1663 /* 1664 * Set the automatic acoustic management on the disk. 1665 */ 1666 void 1667 device_acoustic(int argc, char *argv[]) 1668 { 1669 u_char acoustic; 1670 struct atareq req; 1671 const char *errstr; 1672 1673 if (argc != 2) 1674 goto usage; 1675 1676 acoustic = strtonum(argv[1], 0, 126, &errstr); 1677 if (errstr) 1678 errx(1, "Acoustic management value \"%s\" is %s " 1679 "(valid values: 0 - 126)", argv[1], errstr); 1680 1681 memset(&req, 0, sizeof(req)); 1682 1683 req.sec_count = acoustic + 0x80; 1684 1685 req.command = SET_FEATURES ; 1686 req.features = WDSF_AAM_EN ; 1687 req.timeout = 1000; 1688 1689 ata_command(&req); 1690 1691 return; 1692 1693 usage: 1694 fprintf(stderr, "usage: %s device %s acoustic-management-level\n", 1695 __progname, argv[0]); 1696 exit(1); 1697 } 1698 1699 /* 1700 * Set the advanced power managmement on the disk. Power management 1701 * levels are translated from user-range 0-253 to ATAPI levels 1-0xFD 1702 * to keep a uniform interface to the user. 1703 */ 1704 void 1705 device_apm(int argc, char *argv[]) 1706 { 1707 u_char power; 1708 struct atareq req; 1709 const char *errstr; 1710 1711 if (argc != 2) 1712 goto usage; 1713 1714 power = strtonum(argv[1], 0, 253, &errstr); 1715 if (errstr) 1716 errx(1, "Advanced power management value \"%s\" is %s " 1717 "(valid values: 0 - 253)", argv[1], errstr); 1718 1719 memset(&req, 0, sizeof(req)); 1720 1721 req.sec_count = power + 0x01; 1722 1723 req.command = SET_FEATURES ; 1724 req.features = WDSF_APM_EN ; 1725 req.timeout = 1000; 1726 1727 ata_command(&req); 1728 1729 return; 1730 1731 usage: 1732 fprintf(stderr, "usage: %s device %s power-management-level\n", 1733 __progname, argv[0]); 1734 exit(1); 1735 } 1736 1737 /* 1738 * En/disable features (the automatic acoustic managmement, Advanced Power 1739 * Management) on the disk. 1740 */ 1741 void 1742 device_feature(int argc, char *argv[]) 1743 { 1744 struct atareq req; 1745 1746 if (argc != 1) 1747 goto usage; 1748 1749 memset(&req, 0, sizeof(req)); 1750 1751 req.command = SET_FEATURES ; 1752 1753 if (strcmp(argv[0], "acousticdisable") == 0) 1754 req.features = WDSF_AAM_DS; 1755 else if (strcmp(argv[0], "readaheadenable") == 0) 1756 req.features = WDSF_READAHEAD_EN; 1757 else if (strcmp(argv[0], "readaheaddisable") == 0) 1758 req.features = WDSF_READAHEAD_DS; 1759 else if (strcmp(argv[0], "writecacheenable") == 0) 1760 req.features = WDSF_EN_WR_CACHE; 1761 else if (strcmp(argv[0], "writecachedisable") == 0) 1762 req.features = WDSF_WRITE_CACHE_DS; 1763 else if (strcmp(argv[0], "apmdisable") == 0) 1764 req.features = WDSF_APM_DS; 1765 else if (strcmp(argv[0], "podenable") == 0) 1766 req.features = WDSF_POD_EN; 1767 else if (strcmp(argv[0], "poddisable") == 0) 1768 req.features = WDSF_POD_DS; 1769 else if (strcmp(argv[0], "puisenable") == 0) 1770 req.features = WDSF_PUIS_EN; 1771 else if (strcmp(argv[0], "puisdisable") == 0) 1772 req.features = WDSF_PUIS_DS; 1773 else if (strcmp(argv[0], "puisspinup") == 0) 1774 req.features = WDSF_PUIS_SPINUP; 1775 else 1776 goto usage; 1777 1778 req.timeout = 1000; 1779 1780 ata_command(&req); 1781 1782 return; 1783 1784 usage: 1785 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1786 exit(1); 1787 } 1788 1789 /* 1790 * Set the idle timer on the disk. Set it for either idle mode or 1791 * standby mode, depending on how we were invoked. 1792 */ 1793 void 1794 device_setidle(int argc, char *argv[]) 1795 { 1796 unsigned long idle; 1797 struct atareq req; 1798 char *end; 1799 1800 if (argc != 2) 1801 goto usage; 1802 1803 idle = strtoul(argv[1], &end, 0); 1804 1805 if (*end != '\0' || idle > 19800) 1806 errx(1, "Invalid idle time: \"%s\" " 1807 "(valid values: 1 - 19800)", argv[1]); 1808 1809 if (idle != 0 && idle < 5) 1810 errx(1, "Idle timer must be at least 5 seconds"); 1811 1812 memset(&req, 0, sizeof(req)); 1813 1814 if (idle <= 240 * 5) 1815 req.sec_count = idle / 5; 1816 else 1817 req.sec_count = idle / (30 * 60) + 240; 1818 1819 if (strcmp(argv[0], "setstandby") == 0) 1820 req.command = WDCC_STANDBY; 1821 else if (strcmp(argv[0], "setidle") == 0) 1822 req.command = WDCC_IDLE; 1823 else 1824 goto usage; 1825 req.timeout = 1000; 1826 1827 ata_command(&req); 1828 1829 return; 1830 1831 usage: 1832 fprintf(stderr, "usage: %s device %s %s\n", __progname, argv[0], 1833 (strcmp(argv[0], "setidle") == 0) ? "idle-timer" : "standby-timer"); 1834 exit(1); 1835 } 1836 1837 /* 1838 * Query the device for the current power mode 1839 */ 1840 void 1841 device_checkpower(int argc, char *argv[]) 1842 { 1843 struct atareq req; 1844 1845 if (argc != 1) 1846 goto usage; 1847 1848 memset(&req, 0, sizeof(req)); 1849 1850 req.command = WDCC_CHECK_PWR; 1851 req.timeout = 1000; 1852 req.flags = ATACMD_READREG; 1853 1854 ata_command(&req); 1855 1856 printf("Current power status: "); 1857 1858 switch (req.sec_count) { 1859 case 0x00: 1860 printf("Standby mode\n"); 1861 break; 1862 case 0x80: 1863 printf("Idle mode\n"); 1864 break; 1865 case 0xff: 1866 printf("Active mode\n"); 1867 break; 1868 default: 1869 printf("Unknown power code (%02x)\n", req.sec_count); 1870 } 1871 1872 return; 1873 usage: 1874 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]); 1875 exit(1); 1876 } 1877