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