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