1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Nexenta Systems, Inc. 14 * Copyright 2019 Western Digital Corporation 15 * Copyright 2020 Oxide Computer Company 16 */ 17 18 /* 19 * functions for printing of NVMe data structures and their members 20 */ 21 22 #include <sys/byteorder.h> 23 #include <sys/types.h> 24 #include <inttypes.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <strings.h> 28 #include <stdarg.h> 29 #include <err.h> 30 #include <assert.h> 31 32 #include "nvmeadm.h" 33 34 static int nvme_strlen(const char *, int); 35 36 static void nvme_print_str(int, const char *, int, const char *, int); 37 static void nvme_print_double(int, const char *, double, int, const char *); 38 static void nvme_print_int64(int, const char *, uint64_t, const char *, 39 const char *); 40 static void nvme_print_uint64(int, const char *, uint64_t, const char *, 41 const char *); 42 static void nvme_print_uint128(int, const char *, nvme_uint128_t, const char *, 43 int, int); 44 static void nvme_print_bit(int, const char *, int, const char *, const char *); 45 46 #define ARRAYSIZE(x) (sizeof (x) / sizeof (*(x))) 47 48 static const char *generic_status_codes[] = { 49 "Successful Completion", 50 "Invalid Command Opcode", 51 "Invalid Field in Command", 52 "Command ID Conflict", 53 "Data Transfer Error", 54 "Commands Aborted due to Power Loss Notification", 55 "Internal Error", 56 "Command Abort Requested", 57 "Command Aborted due to SQ Deletion", 58 "Command Aborted due to Failed Fused Command", 59 "Command Aborted due to Missing Fused Command", 60 "Invalid Namespace or Format", 61 "Command Sequence Error", 62 /* NVMe 1.1 */ 63 "Invalid SGL Segment Descriptor", 64 "Invalid Number of SGL Descriptors", 65 "Data SGL Length Invalid", 66 "Metadata SGL Length Invalid", 67 "SGL Descriptor Type Invalid", 68 /* NVMe 1.2 */ 69 "Invalid Use of Controller Memory Buffer", 70 "PRP Offset Invalid", 71 "Atomic Write Unit Exceeded" 72 }; 73 74 static const char *specific_status_codes[] = { 75 "Completion Queue Invalid", 76 "Invalid Queue Identifier", 77 "Invalid Queue Size", 78 "Abort Command Limit Exceeded", 79 "Reserved", 80 "Asynchronous Event Request Limit Exceeded", 81 "Invalid Firmware Slot", 82 "Invalid Firmware Image", 83 "Invalid Interrupt Vector", 84 "Invalid Log Page", 85 "Invalid Format", 86 "Firmware Activation Requires Conventional Reset", 87 "Invalid Queue Deletion", 88 /* NVMe 1.1 */ 89 "Feature Identifier Not Saveable", 90 "Feature Not Changeable", 91 "Feature Not Namespace Specific", 92 "Firmware Activation Requires NVM Subsystem Reset", 93 /* NVMe 1.2 */ 94 "Firmware Activation Requires Reset", 95 "Firmware Activation Requires Maximum Time Violation", 96 "Firmware Activation Prohibited", 97 "Overlapping Range", 98 "Namespace Insufficient Capacity", 99 "Namespace Identifier Unavailable", 100 "Reserved", 101 "Namespace Already Attached", 102 "Namespace Is Private", 103 "Namespace Not Attached", 104 "Thin Provisioning Not Supported", 105 "Controller List Invalid" 106 }; 107 108 static const char *generic_nvm_status_codes[] = { 109 "LBA Out Of Range", 110 "Capacity Exceeded", 111 "Namespace Not Ready", 112 /* NVMe 1.1 */ 113 "Reservation Conflict", 114 /* NVMe 1.2 */ 115 "Format In Progress", 116 }; 117 118 static const char *specific_nvm_status_codes[] = { 119 "Conflicting Attributes", 120 "Invalid Protection Information", 121 "Attempted Write to Read Only Range" 122 }; 123 124 static const char *media_nvm_status_codes[] = { 125 "Write Fault", 126 "Unrecovered Read Error", 127 "End-to-End Guard Check Error", 128 "End-to-End Application Tag Check Error", 129 "End-to-End Reference Tag Check Error", 130 "Compare Failure", 131 "Access Denied", 132 /* NVMe 1.2 */ 133 "Deallocated or Unwritten Logical Block" 134 }; 135 136 static const char *status_code_types[] = { 137 "Generic Command Status", 138 "Command Specific Status", 139 "Media Errors", 140 "Reserved", 141 "Reserved", 142 "Reserved", 143 "Reserved", 144 "Vendor Specific" 145 }; 146 147 static const char *lbaf_relative_performance[] = { 148 "Best", "Better", "Good", "Degraded" 149 }; 150 151 static const char *lba_range_types[] = { 152 "Reserved", "Filesystem", "RAID", "Cache", "Page/Swap File" 153 }; 154 155 /* 156 * nvme_print 157 * 158 * This function prints a string indented by the specified number of spaces, 159 * optionally followed by the specified index if it is >= 0. If a format string 160 * is specified, a single colon and the required number of spaces for alignment 161 * are printed before the format string and any remaining arguments are passed 162 * vprintf. 163 * 164 * NVME_PRINT_ALIGN was chosen so that all values will be lined up nicely even 165 * for the longest name at its default indentation. 166 */ 167 168 #define NVME_PRINT_ALIGN 43 169 170 void 171 nvme_print(int indent, const char *name, int index, const char *fmt, ...) 172 { 173 int align = NVME_PRINT_ALIGN - (indent + strlen(name) + 1); 174 va_list ap; 175 176 if (index >= 0) 177 align -= snprintf(NULL, 0, " %d", index); 178 179 if (align < 0) 180 align = 0; 181 182 va_start(ap, fmt); 183 184 (void) printf("%*s%s", indent, "", name); 185 186 if (index >= 0) 187 (void) printf(" %d", index); 188 189 if (fmt != NULL) { 190 (void) printf(": %*s", align, ""); 191 (void) vprintf(fmt, ap); 192 } 193 194 (void) printf("\n"); 195 va_end(ap); 196 } 197 198 /* 199 * nvme_strlen -- return length of string without trailing whitespace 200 */ 201 static int 202 nvme_strlen(const char *str, int len) 203 { 204 if (len < 0) 205 return (0); 206 207 while (str[--len] == ' ') 208 ; 209 210 return (++len); 211 } 212 213 /* 214 * nvme_print_str -- print a string up to the specified length 215 */ 216 static void 217 nvme_print_str(int indent, const char *name, int index, const char *value, 218 int len) 219 { 220 if (len == 0) 221 len = strlen(value); 222 223 nvme_print(indent, name, index, "%.*s", nvme_strlen(value, len), value); 224 } 225 226 /* 227 * nvme_print_double -- print a double up to a specified number of places with 228 * optional unit 229 */ 230 static void 231 nvme_print_double(int indent, const char *name, double value, int places, 232 const char *unit) 233 { 234 if (unit == NULL) 235 unit = ""; 236 237 nvme_print(indent, name, -1, "%.*g%s", places, value, unit); 238 } 239 240 /* 241 * nvme_print_int64 -- print int64_t with optional unit in decimal or another 242 * format specified 243 */ 244 static void 245 nvme_print_int64(int indent, const char *name, uint64_t value, const char *fmt, 246 const char *unit) 247 { 248 char *tmp_fmt; 249 250 if (unit == NULL) 251 unit = ""; 252 253 if (fmt == NULL) 254 fmt = "%"PRId64; 255 256 if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0) 257 err(-1, "nvme_print_int64()"); 258 259 nvme_print(indent, name, -1, tmp_fmt, value, unit); 260 261 free(tmp_fmt); 262 } 263 264 /* 265 * nvme_print_temp -- The NVMe specification passes most temperature values as 266 * uint16_t values that are encoded in kelvin. This converts them in one place 267 * to Celsius. 268 */ 269 static void 270 nvme_print_temp(int indent, const char *name, uint16_t value) 271 { 272 int64_t temp = (int64_t)value; 273 temp -= 273; 274 nvme_print_int64(indent, name, temp, NULL, "C"); 275 } 276 277 /* 278 * nvme_print_uint64 -- print uint64_t with optional unit in decimal or another 279 * format specified 280 */ 281 static void 282 nvme_print_uint64(int indent, const char *name, uint64_t value, const char *fmt, 283 const char *unit) 284 { 285 char *tmp_fmt; 286 287 if (unit == NULL) 288 unit = ""; 289 290 if (fmt == NULL) 291 fmt = "%"PRIu64; 292 293 if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0) 294 err(-1, "nvme_print_uint64()"); 295 296 nvme_print(indent, name, -1, tmp_fmt, value, unit); 297 298 free(tmp_fmt); 299 } 300 301 /* 302 * nvme_print_uint128 -- print a 128bit uint with optional unit, after applying 303 * binary and/or decimal shifting 304 */ 305 static void 306 nvme_print_uint128(int indent, const char *name, nvme_uint128_t value, 307 const char *unit, int scale_bits, int scale_tens) 308 { 309 const char hex[] = "0123456789abcdef"; 310 uint8_t o[(128 + scale_bits) / 3]; 311 char p[sizeof (o) * 2]; 312 char *pp = &p[0]; 313 int i, x; 314 uint64_t rem = 0; 315 316 if (unit == NULL) 317 unit = ""; 318 319 /* 320 * Don't allow binary shifting by more than 64 bits to keep the 321 * arithmetic simple. Also limit decimal shifting based on the size 322 * of any possible remainder from binary shifting. 323 */ 324 assert(scale_bits <= 64); 325 assert(scale_tens <= (64 - scale_bits) / 3); 326 327 bzero(o, sizeof (o)); 328 bzero(p, sizeof (p)); 329 330 /* 331 * Convert the two 64-bit numbers into a series of BCD digits using 332 * a double-dabble algorithm. By using more or less iterations than 333 * 128 we can do a binary shift in either direction. 334 */ 335 for (x = 0; x != 128 - scale_bits; x++) { 336 for (i = 0; i != sizeof (o); i++) { 337 if ((o[i] & 0xf0) > 0x40) 338 o[i] += 0x30; 339 340 if ((o[i] & 0xf) > 4) 341 o[i] += 3; 342 } 343 344 for (i = 0; i != sizeof (o) - 1; i++) 345 o[i] = (o[i] << 1) + (o[i+1] >> 7); 346 347 o[i] = (o[i] << 1) + (value.hi >> 63); 348 349 value.hi = (value.hi << 1) + (value.lo >> 63); 350 value.lo = (value.lo << 1); 351 } 352 353 /* 354 * If we're supposed to do a decimal left shift (* 10^x), too, 355 * calculate the remainder of the previous binary shift operation. 356 */ 357 if (scale_tens > 0) { 358 rem = value.hi >> (64 - scale_bits); 359 360 for (i = 0; i != scale_tens; i++) 361 rem *= 10; 362 363 rem >>= scale_bits; 364 } 365 366 /* 367 * Construct the decimal number for printing. Skip leading zeros. 368 */ 369 for (i = 0; i < sizeof (o); i++) 370 if (o[i] != 0) 371 break; 372 373 if (i == sizeof (o)) { 374 /* 375 * The converted number is 0. Just print the calculated 376 * remainder and return. 377 */ 378 nvme_print(indent, name, -1, "%"PRId64"%s", rem, unit); 379 return; 380 } else { 381 if (o[i] > 0xf) 382 *pp++ = hex[o[i] >> 4]; 383 384 *pp++ = hex[o[i] & 0xf]; 385 386 for (i++; i < sizeof (o); i++) { 387 *pp++ = hex[o[i] >> 4]; 388 *pp++ = hex[o[i] & 0xf]; 389 } 390 } 391 392 /* 393 * For negative decimal scaling, use the printf precision specifier to 394 * truncate the results according to the requested decimal scaling. For 395 * positive decimal scaling we print the remainder padded with 0. 396 */ 397 nvme_print(indent, name, -1, "%.*s%0.*"PRId64"%s", 398 strlen(p) + scale_tens, p, 399 scale_tens > 0 ? scale_tens : 0, rem, 400 unit); 401 } 402 403 /* 404 * nvme_print_bit -- print a bit with optional names for both states 405 */ 406 static void 407 nvme_print_bit(int indent, const char *name, int value, const char *s_true, 408 const char *s_false) 409 { 410 if (s_true == NULL) 411 s_true = "supported"; 412 if (s_false == NULL) 413 s_false = "unsupported"; 414 415 nvme_print(indent, name, -1, "%s", value ? s_true : s_false); 416 } 417 418 /* 419 * nvme_print_ctrl_summary -- print a 1-line summary of the IDENTIFY CONTROLLER 420 * data structure 421 */ 422 void 423 nvme_print_ctrl_summary(nvme_identify_ctrl_t *idctl, nvme_version_t *version) 424 { 425 (void) printf("model: %.*s, serial: %.*s, FW rev: %.*s, NVMe v%d.%d\n", 426 nvme_strlen(idctl->id_model, sizeof (idctl->id_model)), 427 idctl->id_model, 428 nvme_strlen(idctl->id_serial, sizeof (idctl->id_serial)), 429 idctl->id_serial, 430 nvme_strlen(idctl->id_fwrev, sizeof (idctl->id_fwrev)), 431 idctl->id_fwrev, 432 version->v_major, version->v_minor); 433 } 434 435 /* 436 * nvme_print_nsid_summary -- print a 1-line summary of the IDENTIFY NAMESPACE 437 * data structure 438 */ 439 void 440 nvme_print_nsid_summary(nvme_identify_nsid_t *idns) 441 { 442 int bsize = 1 << idns->id_lbaf[idns->id_flbas.lba_format].lbaf_lbads; 443 444 (void) printf("Size = %"PRId64" MB, " 445 "Capacity = %"PRId64" MB, " 446 "Used = %"PRId64" MB\n", 447 idns->id_nsize * bsize / 1024 / 1024, 448 idns->id_ncap * bsize / 1024 / 1024, 449 idns->id_nuse * bsize / 1024 / 1024); 450 451 } 452 453 /* 454 * nvme_print_identify_ctrl 455 * 456 * This function pretty-prints the structure returned by the IDENTIFY CONTROLLER 457 * command. 458 */ 459 void 460 nvme_print_identify_ctrl(nvme_identify_ctrl_t *idctl, 461 nvme_capabilities_t *cap, nvme_version_t *version) 462 { 463 int i; 464 465 nvme_print(0, "Identify Controller", -1, NULL); 466 nvme_print(2, "Controller Capabilities and Features", -1, NULL); 467 nvme_print_str(4, "Model", -1, 468 idctl->id_model, sizeof (idctl->id_model)); 469 nvme_print_str(4, "Serial", -1, 470 idctl->id_serial, sizeof (idctl->id_serial)); 471 nvme_print_str(4, "Firmware Revision", -1, 472 idctl->id_fwrev, sizeof (idctl->id_fwrev)); 473 if (verbose) { 474 nvme_print_uint64(4, "PCI vendor ID", 475 idctl->id_vid, "0x%0.4"PRIx64, NULL); 476 nvme_print_uint64(4, "subsystem vendor ID", 477 idctl->id_ssvid, "0x%0.4"PRIx64, NULL); 478 nvme_print_uint64(4, "Recommended Arbitration Burst", 479 idctl->id_rab, NULL, NULL); 480 nvme_print(4, "Vendor IEEE OUI", -1, "%0.2X-%0.2X-%0.2X", 481 idctl->id_oui[0], idctl->id_oui[1], idctl->id_oui[2]); 482 } 483 nvme_print(4, "Multi-Interface Capabilities", -1, NULL); 484 nvme_print_bit(6, "Multiple PCI Express ports", 485 idctl->id_mic.m_multi_pci, NULL, NULL); 486 487 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 488 nvme_print_bit(6, "Multiple Controllers", 489 idctl->id_mic.m_multi_ctrl, NULL, NULL); 490 nvme_print_bit(6, "Is SR-IOV virtual function", 491 idctl->id_mic.m_sr_iov, "yes", "no"); 492 } 493 if (idctl->id_mdts > 0) 494 nvme_print_uint64(4, "Maximum Data Transfer Size", 495 (1 << idctl->id_mdts) * cap->mpsmin / 1024, NULL, "kB"); 496 else 497 nvme_print_str(4, "Maximum Data Transfer Size", -1, 498 "unlimited", 0); 499 500 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 501 nvme_print_uint64(4, "Unique Controller Identifier", 502 idctl->id_cntlid, "0x%0.4"PRIx64, NULL); 503 } 504 505 nvme_print(2, "Admin Command Set Attributes", -1, NULL); 506 nvme_print(4, "Optional Admin Command Support", -1, NULL); 507 nvme_print_bit(6, "Security Send & Receive", 508 idctl->id_oacs.oa_security, NULL, NULL); 509 nvme_print_bit(6, "Format NVM", 510 idctl->id_oacs.oa_format, NULL, NULL); 511 nvme_print_bit(6, "Firmware Activate & Download", 512 idctl->id_oacs.oa_firmware, NULL, NULL); 513 if (verbose) { 514 nvme_print_uint64(4, "Abort Command Limit", 515 (uint16_t)idctl->id_acl + 1, NULL, NULL); 516 nvme_print_uint64(4, "Asynchronous Event Request Limit", 517 (uint16_t)idctl->id_aerl + 1, NULL, NULL); 518 } 519 nvme_print(4, "Firmware Updates", -1, NULL); 520 nvme_print_bit(6, "Firmware Slot 1", 521 idctl->id_frmw.fw_readonly, "read-only", "writable"); 522 nvme_print_uint64(6, "No. of Firmware Slots", 523 idctl->id_frmw.fw_nslot, NULL, NULL); 524 nvme_print(2, "Log Page Attributes", -1, NULL); 525 nvme_print_bit(6, "per Namespace SMART/Health info", 526 idctl->id_lpa.lp_smart, NULL, NULL); 527 nvme_print_uint64(4, "Error Log Page Entries", 528 (uint16_t)idctl->id_elpe + 1, NULL, NULL); 529 nvme_print_uint64(4, "Number of Power States", 530 (uint16_t)idctl->id_npss + 1, NULL, NULL); 531 if (verbose) { 532 nvme_print_bit(4, "Admin Vendor-specific Command Format", 533 idctl->id_avscc.av_spec, "standard", "vendor-specific"); 534 } 535 536 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 537 nvme_print_bit(4, "Autonomous Power State Transitions", 538 idctl->id_apsta.ap_sup, NULL, NULL); 539 } 540 541 nvme_print(2, "NVM Command Set Attributes", -1, NULL); 542 if (verbose) { 543 nvme_print(4, "Submission Queue Entry Size", -1, 544 "min %d, max %d", 545 1 << idctl->id_sqes.qes_min, 1 << idctl->id_sqes.qes_max); 546 nvme_print(4, "Completion Queue Entry Size", -1, 547 "min %d, max %d", 548 1 << idctl->id_cqes.qes_min, 1 << idctl->id_cqes.qes_max); 549 } 550 nvme_print_uint64(4, "Number of Namespaces", 551 idctl->id_nn, NULL, NULL); 552 nvme_print(4, "Optional NVM Command Support", -1, NULL); 553 nvme_print_bit(6, "Compare", 554 idctl->id_oncs.on_compare, NULL, NULL); 555 nvme_print_bit(6, "Write Uncorrectable", 556 idctl->id_oncs.on_wr_unc, NULL, NULL); 557 nvme_print_bit(6, "Dataset Management", 558 idctl->id_oncs.on_dset_mgmt, NULL, NULL); 559 560 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 561 nvme_print_bit(6, "Write Zeros", 562 idctl->id_oncs.on_wr_zero, NULL, NULL); 563 nvme_print_bit(6, "Save/Select in Get/Set Features", 564 idctl->id_oncs.on_save, NULL, NULL); 565 nvme_print_bit(6, "Reservations", 566 idctl->id_oncs.on_reserve, NULL, NULL); 567 } 568 569 nvme_print(4, "Fused Operation Support", -1, NULL); 570 nvme_print_bit(6, "Compare and Write", 571 idctl->id_fuses.f_cmp_wr, NULL, NULL); 572 nvme_print(4, "Format NVM Attributes", -1, NULL); 573 nvme_print_bit(6, "per Namespace Format", 574 idctl->id_fna.fn_format == 0, NULL, NULL); 575 nvme_print_bit(6, "per Namespace Secure Erase", 576 idctl->id_fna.fn_sec_erase == 0, NULL, NULL); 577 nvme_print_bit(6, "Cryptographic Erase", 578 idctl->id_fna.fn_crypt_erase, NULL, NULL); 579 nvme_print_bit(4, "Volatile Write Cache", 580 idctl->id_vwc.vwc_present, "present", "not present"); 581 nvme_print_uint64(4, "Atomic Write Unit Normal", 582 (uint32_t)idctl->id_awun + 1, NULL, 583 idctl->id_awun == 0 ? " block" : " blocks"); 584 nvme_print_uint64(4, "Atomic Write Unit Power Fail", 585 (uint32_t)idctl->id_awupf + 1, NULL, 586 idctl->id_awupf == 0 ? " block" : " blocks"); 587 588 if (verbose != 0) 589 nvme_print_bit(4, "NVM Vendor-specific Command Format", 590 idctl->id_nvscc.nv_spec, "standard", "vendor-specific"); 591 592 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 593 nvme_print_uint64(4, "Atomic Compare & Write Size", 594 (uint32_t)idctl->id_acwu + 1, NULL, 595 idctl->id_acwu == 0 ? " block" : " blocks"); 596 nvme_print(4, "SGL Support", -1, NULL); 597 nvme_print_bit(6, "SGLs in NVM commands", 598 idctl->id_sgls.sgl_sup, NULL, NULL); 599 nvme_print_bit(6, "SGL Bit Bucket Descriptor", 600 idctl->id_sgls.sgl_bucket, NULL, NULL); 601 } 602 603 for (i = 0; i != idctl->id_npss + 1; i++) { 604 double scale = 0.01; 605 double power = 0; 606 int places = 2; 607 char *unit = "W"; 608 609 if (NVME_VERSION_ATLEAST(version, 1, 1) && 610 idctl->id_psd[i].psd_mps == 1) { 611 scale = 0.0001; 612 places = 4; 613 } 614 615 power = (double)idctl->id_psd[i].psd_mp * scale; 616 if (power < 1.0) { 617 power *= 1000.0; 618 unit = "mW"; 619 } 620 621 nvme_print(4, "Power State Descriptor", i, NULL); 622 nvme_print_double(6, "Maximum Power", power, places, unit); 623 nvme_print_bit(6, "Non-Operational State", 624 idctl->id_psd[i].psd_nops, "yes", "no"); 625 nvme_print_uint64(6, "Entry Latency", 626 idctl->id_psd[i].psd_enlat, NULL, "us"); 627 nvme_print_uint64(6, "Exit Latency", 628 idctl->id_psd[i].psd_exlat, NULL, "us"); 629 nvme_print_uint64(6, "Relative Read Throughput (0 = best)", 630 idctl->id_psd[i].psd_rrt, NULL, NULL); 631 nvme_print_uint64(6, "Relative Read Latency (0 = best)", 632 idctl->id_psd[i].psd_rrl, NULL, NULL); 633 nvme_print_uint64(6, "Relative Write Throughput (0 = best)", 634 idctl->id_psd[i].psd_rwt, NULL, NULL); 635 nvme_print_uint64(6, "Relative Write Latency (0 = best)", 636 idctl->id_psd[i].psd_rwl, NULL, NULL); 637 } 638 } 639 640 /* 641 * nvme_print_identify_nsid 642 * 643 * This function pretty-prints the structure returned by the IDENTIFY NAMESPACE 644 * command. 645 */ 646 void 647 nvme_print_identify_nsid(nvme_identify_nsid_t *idns, nvme_version_t *version) 648 { 649 int bsize = 1 << idns->id_lbaf[idns->id_flbas.lba_format].lbaf_lbads; 650 int i; 651 652 nvme_print(0, "Identify Namespace", -1, NULL); 653 nvme_print(2, "Namespace Capabilities and Features", -1, NULL); 654 nvme_print_uint64(4, "Namespace Size", 655 idns->id_nsize * bsize / 1024 / 1024, NULL, "MB"); 656 nvme_print_uint64(4, "Namespace Capacity", 657 idns->id_ncap * bsize / 1024 / 1024, NULL, "MB"); 658 nvme_print_uint64(4, "Namespace Utilization", 659 idns->id_nuse * bsize / 1024 / 1024, NULL, "MB"); 660 nvme_print(4, "Namespace Features", -1, NULL); 661 nvme_print_bit(6, "Thin Provisioning", 662 idns->id_nsfeat.f_thin, NULL, NULL); 663 nvme_print_uint64(4, "Number of LBA Formats", 664 (uint16_t)idns->id_nlbaf + 1, NULL, NULL); 665 nvme_print(4, "Formatted LBA Size", -1, NULL); 666 nvme_print_uint64(6, "LBA Format", 667 (uint16_t)idns->id_flbas.lba_format, NULL, NULL); 668 nvme_print_bit(6, "Extended Data LBA", 669 idns->id_flbas.lba_extlba, "yes", "no"); 670 nvme_print(4, "Metadata Capabilities", -1, NULL); 671 nvme_print_bit(6, "Extended Data LBA", 672 idns->id_mc.mc_extlba, NULL, NULL); 673 nvme_print_bit(6, "Separate Metadata", 674 idns->id_mc.mc_separate, NULL, NULL); 675 nvme_print(4, "End-to-End Data Protection Capabilities", -1, NULL); 676 nvme_print_bit(6, "Protection Information Type 1", 677 idns->id_dpc.dp_type1, NULL, NULL); 678 nvme_print_bit(6, "Protection Information Type 2", 679 idns->id_dpc.dp_type2, NULL, NULL); 680 nvme_print_bit(6, "Protection Information Type 3", 681 idns->id_dpc.dp_type3, NULL, NULL); 682 nvme_print_bit(6, "Protection Information first", 683 idns->id_dpc.dp_first, NULL, NULL); 684 nvme_print_bit(6, "Protection Information last", 685 idns->id_dpc.dp_last, NULL, NULL); 686 nvme_print(4, "End-to-End Data Protection Settings", -1, NULL); 687 if (idns->id_dps.dp_pinfo == 0) 688 nvme_print_str(6, "Protection Information", -1, 689 "disabled", 0); 690 else 691 nvme_print_uint64(6, "Protection Information Type", 692 idns->id_dps.dp_pinfo, NULL, NULL); 693 nvme_print_bit(6, "Protection Information in Metadata", 694 idns->id_dps.dp_first, "first 8 bytes", "last 8 bytes"); 695 696 if (NVME_VERSION_ATLEAST(version, 1, 1)) { 697 nvme_print(4, "Namespace Multi-Path I/O and Namespace Sharing " 698 "Capabilities", -1, NULL); 699 nvme_print_bit(6, "Namespace is shared", 700 idns->id_nmic.nm_shared, "yes", "no"); 701 nvme_print(2, "Reservation Capabilities", -1, NULL); 702 nvme_print_bit(6, "Persist Through Power Loss", 703 idns->id_rescap.rc_persist, NULL, NULL); 704 nvme_print_bit(6, "Write Exclusive", 705 idns->id_rescap.rc_wr_excl, NULL, NULL); 706 nvme_print_bit(6, "Exclusive Access", 707 idns->id_rescap.rc_excl, NULL, NULL); 708 nvme_print_bit(6, "Write Exclusive - Registrants Only", 709 idns->id_rescap.rc_wr_excl_r, NULL, NULL); 710 nvme_print_bit(6, "Exclusive Access - Registrants Only", 711 idns->id_rescap.rc_excl_r, NULL, NULL); 712 nvme_print_bit(6, "Write Exclusive - All Registrants", 713 idns->id_rescap.rc_wr_excl_a, NULL, NULL); 714 nvme_print_bit(6, "Exclusive Access - All Registrants", 715 idns->id_rescap.rc_excl_a, NULL, NULL); 716 717 nvme_print(4, "IEEE Extended Unique Identifier", -1, 718 "%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X", 719 idns->id_eui64[0], idns->id_eui64[1], 720 idns->id_eui64[2], idns->id_eui64[3], 721 idns->id_eui64[4], idns->id_eui64[5], 722 idns->id_eui64[6], idns->id_eui64[7]); 723 } 724 725 for (i = 0; i <= idns->id_nlbaf; i++) { 726 if (verbose == 0 && idns->id_lbaf[i].lbaf_ms != 0) 727 continue; 728 729 nvme_print(4, "LBA Format", i, NULL); 730 nvme_print_uint64(6, "Metadata Size", 731 idns->id_lbaf[i].lbaf_ms, NULL, " bytes"); 732 nvme_print_uint64(6, "LBA Data Size", 733 1 << idns->id_lbaf[i].lbaf_lbads, NULL, " bytes"); 734 nvme_print_str(6, "Relative Performance", -1, 735 lbaf_relative_performance[idns->id_lbaf[i].lbaf_rp], 0); 736 } 737 } 738 739 /* 740 * nvme_print_error_log 741 * 742 * This function pretty-prints all non-zero error log entries, or all entries 743 * if verbose is set. 744 */ 745 void 746 nvme_print_error_log(int nlog, nvme_error_log_entry_t *elog) 747 { 748 int i; 749 750 nvme_print(0, "Error Log", -1, NULL); 751 for (i = 0; i != nlog; i++) 752 if (elog[i].el_count == 0) 753 break; 754 nvme_print_uint64(2, "Number of Error Log Entries", i, NULL, NULL); 755 756 for (i = 0; i != nlog; i++) { 757 int sc = elog[i].el_sf.sf_sc; 758 const char *sc_str = ""; 759 760 if (elog[i].el_count == 0 && verbose == 0) 761 break; 762 763 switch (elog[i].el_sf.sf_sct) { 764 case 0: /* Generic Command Status */ 765 if (sc < ARRAYSIZE(generic_status_codes)) 766 sc_str = generic_status_codes[sc]; 767 else if (sc >= 0x80 && 768 sc - 0x80 < ARRAYSIZE(generic_nvm_status_codes)) 769 sc_str = generic_nvm_status_codes[sc - 0x80]; 770 break; 771 case 1: /* Specific Command Status */ 772 if (sc < ARRAYSIZE(specific_status_codes)) 773 sc_str = specific_status_codes[sc]; 774 else if (sc >= 0x80 && 775 sc - 0x80 < ARRAYSIZE(specific_nvm_status_codes)) 776 sc_str = specific_nvm_status_codes[sc - 0x80]; 777 break; 778 case 2: /* Media Errors */ 779 if (sc >= 0x80 && 780 sc - 0x80 < ARRAYSIZE(media_nvm_status_codes)) 781 sc_str = media_nvm_status_codes[sc - 0x80]; 782 break; 783 case 7: /* Vendor Specific */ 784 sc_str = "Unknown Vendor Specific"; 785 break; 786 default: 787 sc_str = "Reserved"; 788 break; 789 } 790 791 nvme_print(2, "Entry", i, NULL); 792 nvme_print_uint64(4, "Error Count", 793 elog[i].el_count, NULL, NULL); 794 nvme_print_uint64(4, "Submission Queue ID", 795 elog[i].el_sqid, NULL, NULL); 796 nvme_print_uint64(4, "Command ID", 797 elog[i].el_cid, NULL, NULL); 798 nvme_print(4, "Status Field", -1, NULL); 799 nvme_print_uint64(6, "Phase Tag", 800 elog[i].el_sf.sf_p, NULL, NULL); 801 nvme_print(6, "Status Code", -1, "0x%0.2x (%s)", 802 sc, sc_str); 803 nvme_print(6, "Status Code Type", -1, "0x%x (%s)", 804 elog[i].el_sf.sf_sct, 805 status_code_types[elog[i].el_sf.sf_sct]); 806 nvme_print_bit(6, "More", 807 elog[i].el_sf.sf_m, "yes", "no"); 808 nvme_print_bit(6, "Do Not Retry", 809 elog[i].el_sf.sf_m, "yes", "no"); 810 nvme_print_uint64(4, "Parameter Error Location byte", 811 elog[i].el_byte, "0x%0.2"PRIx64, NULL); 812 nvme_print_uint64(4, "Parameter Error Location bit", 813 elog[i].el_bit, NULL, NULL); 814 nvme_print_uint64(4, "Logical Block Address", 815 elog[i].el_lba, NULL, NULL); 816 nvme_print(4, "Namespace ID", -1, "%d", 817 elog[i].el_nsid == 0xffffffff ? 818 0 : elog[i].el_nsid); 819 nvme_print_uint64(4, 820 "Vendor Specifc Information Available", 821 elog[i].el_vendor, NULL, NULL); 822 } 823 } 824 825 /* 826 * nvme_print_health_log 827 * 828 * This function pretty-prints a summary of the SMART/Health log, or all 829 * of the log if verbose is set. 830 */ 831 void 832 nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl, 833 nvme_version_t *vers) 834 { 835 nvme_print(0, "SMART/Health Information", -1, NULL); 836 nvme_print(2, "Critical Warnings", -1, NULL); 837 nvme_print_bit(4, "Available Space", 838 hlog->hl_crit_warn.cw_avail, "low", "OK"); 839 nvme_print_bit(4, "Temperature", 840 hlog->hl_crit_warn.cw_temp, "too high", "OK"); 841 nvme_print_bit(4, "Device Reliability", 842 hlog->hl_crit_warn.cw_reliab, "degraded", "OK"); 843 nvme_print_bit(4, "Media", 844 hlog->hl_crit_warn.cw_readonly, "read-only", "OK"); 845 if (idctl->id_vwc.vwc_present != 0) 846 nvme_print_bit(4, "Volatile Memory Backup", 847 hlog->hl_crit_warn.cw_volatile, "failed", "OK"); 848 849 nvme_print_temp(2, "Temperature", hlog->hl_temp); 850 nvme_print_uint64(2, "Available Spare Capacity", 851 hlog->hl_avail_spare, NULL, "%"); 852 853 if (verbose != 0) 854 nvme_print_uint64(2, "Available Spare Threshold", 855 hlog->hl_avail_spare_thr, NULL, "%"); 856 857 nvme_print_uint64(2, "Device Life Used", 858 hlog->hl_used, NULL, "%"); 859 860 if (verbose == 0) 861 return; 862 863 /* 864 * The following two fields are in 1000 512 byte units. Convert that to 865 * GB by doing binary shifts (9 left and 30 right) and multiply by 10^3. 866 */ 867 nvme_print_uint128(2, "Data Read", 868 hlog->hl_data_read, "GB", 30 - 9, 3); 869 nvme_print_uint128(2, "Data Written", 870 hlog->hl_data_write, "GB", 30 - 9, 3); 871 872 nvme_print_uint128(2, "Read Commands", 873 hlog->hl_host_read, NULL, 0, 0); 874 nvme_print_uint128(2, "Write Commands", 875 hlog->hl_host_write, NULL, 0, 0); 876 nvme_print_uint128(2, "Controller Busy", 877 hlog->hl_ctrl_busy, "min", 0, 0); 878 nvme_print_uint128(2, "Power Cycles", 879 hlog->hl_power_cycles, NULL, 0, 0); 880 nvme_print_uint128(2, "Power On", 881 hlog->hl_power_on_hours, "h", 0, 0); 882 nvme_print_uint128(2, "Unsafe Shutdowns", 883 hlog->hl_unsafe_shutdn, NULL, 0, 0); 884 nvme_print_uint128(2, "Uncorrectable Media Errors", 885 hlog->hl_media_errors, NULL, 0, 0); 886 nvme_print_uint128(2, "Errors Logged", 887 hlog->hl_errors_logged, NULL, 0, 0); 888 889 if (!NVME_VERSION_ATLEAST(vers, 1, 2)) { 890 return; 891 } 892 893 if (idctl->ap_wctemp != 0) { 894 nvme_print_uint64(2, "Warning Composite Temperature Time", 895 hlog->hl_warn_temp_time, NULL, "min"); 896 } 897 898 if (idctl->ap_cctemp != 0) { 899 nvme_print_uint64(2, "Critical Composite Temperature Time", 900 hlog->hl_crit_temp_time, NULL, "min"); 901 } 902 903 if (hlog->hl_temp_sensor_1 != 0) { 904 nvme_print_temp(2, "Temperature Sensor 1", 905 hlog->hl_temp_sensor_1); 906 } 907 908 if (hlog->hl_temp_sensor_2 != 0) { 909 nvme_print_temp(2, "Temperature Sensor 2", 910 hlog->hl_temp_sensor_2); 911 } 912 913 if (hlog->hl_temp_sensor_3 != 0) { 914 nvme_print_temp(2, "Temperature Sensor 3", 915 hlog->hl_temp_sensor_3); 916 } 917 918 if (hlog->hl_temp_sensor_4 != 0) { 919 nvme_print_temp(2, "Temperature Sensor 4", 920 hlog->hl_temp_sensor_4); 921 } 922 923 if (hlog->hl_temp_sensor_5 != 0) { 924 nvme_print_temp(2, "Temperature Sensor 5", 925 hlog->hl_temp_sensor_5); 926 } 927 928 if (hlog->hl_temp_sensor_6 != 0) { 929 nvme_print_temp(2, "Temperature Sensor 6", 930 hlog->hl_temp_sensor_6); 931 } 932 933 if (hlog->hl_temp_sensor_7 != 0) { 934 nvme_print_temp(2, "Temperature Sensor 7", 935 hlog->hl_temp_sensor_7); 936 } 937 938 if (hlog->hl_temp_sensor_8 != 0) { 939 nvme_print_temp(2, "Temperature Sensor 8", 940 hlog->hl_temp_sensor_8); 941 } 942 943 if (!NVME_VERSION_ATLEAST(vers, 1, 3)) { 944 return; 945 } 946 947 nvme_print_uint64(2, "Thermal Management Temp 1 Transition Count", 948 hlog->hl_tmtemp_1_tc, NULL, NULL); 949 950 nvme_print_uint64(2, "Thermal Management Temp 2 Transition Count", 951 hlog->hl_tmtemp_2_tc, NULL, NULL); 952 953 nvme_print_uint64(2, "Time for Thermal Management Temp 1", 954 hlog->hl_tmtemp_1_time, NULL, "sec"); 955 956 nvme_print_uint64(2, "Time for Thermal Management Temp 2", 957 hlog->hl_tmtemp_2_time, NULL, "sec"); 958 } 959 960 /* 961 * nvme_print_fwslot_log 962 * 963 * This function pretty-prints the firmware slot information. 964 */ 965 void 966 nvme_print_fwslot_log(nvme_fwslot_log_t *fwlog) 967 { 968 int i; 969 970 nvme_print(0, "Firmware Slot Information", -1, NULL); 971 nvme_print_uint64(2, "Active Firmware Slot", fwlog->fw_afi, NULL, NULL); 972 if (fwlog->fw_next != 0) 973 nvme_print_uint64(2, "Next Firmware Slot", fwlog->fw_next, 974 NULL, NULL); 975 976 for (i = 0; i != ARRAYSIZE(fwlog->fw_frs); i++) { 977 nvme_print_str(2, "Firmware Revision for Slot", i + 1, 978 fwlog->fw_frs[i][0] == '\0' ? "<Unused>" : 979 fwlog->fw_frs[i], sizeof (fwlog->fw_frs[i])); 980 } 981 } 982 983 /* 984 * nvme_print_feat_* 985 * 986 * These functions pretty-print the data structures returned by GET FEATURES. 987 */ 988 void 989 nvme_print_feat_arbitration(uint64_t res, void *b, size_t s, 990 nvme_identify_ctrl_t *id) 991 { 992 _NOTE(ARGUNUSED(b)); 993 _NOTE(ARGUNUSED(s)); 994 _NOTE(ARGUNUSED(id)); 995 nvme_arbitration_t arb; 996 997 arb.r = (uint32_t)res; 998 if (arb.b.arb_ab != 7) 999 nvme_print_uint64(4, "Arbitration Burst", 1000 1 << arb.b.arb_ab, NULL, NULL); 1001 else 1002 nvme_print_str(4, "Arbitration Burst", 0, 1003 "no limit", 0); 1004 nvme_print_uint64(4, "Low Priority Weight", 1005 (uint16_t)arb.b.arb_lpw + 1, NULL, NULL); 1006 nvme_print_uint64(4, "Medium Priority Weight", 1007 (uint16_t)arb.b.arb_mpw + 1, NULL, NULL); 1008 nvme_print_uint64(4, "High Priority Weight", 1009 (uint16_t)arb.b.arb_hpw + 1, NULL, NULL); 1010 } 1011 1012 void 1013 nvme_print_feat_power_mgmt(uint64_t res, void *b, size_t s, 1014 nvme_identify_ctrl_t *id) 1015 { 1016 _NOTE(ARGUNUSED(b)); 1017 _NOTE(ARGUNUSED(s)); 1018 _NOTE(ARGUNUSED(id)); 1019 nvme_power_mgmt_t pm; 1020 1021 pm.r = (uint32_t)res; 1022 nvme_print_uint64(4, "Power State", (uint8_t)pm.b.pm_ps, 1023 NULL, NULL); 1024 } 1025 1026 void 1027 nvme_print_feat_lba_range(uint64_t res, void *buf, size_t bufsize, 1028 nvme_identify_ctrl_t *id) 1029 { 1030 _NOTE(ARGUNUSED(id)); 1031 1032 nvme_lba_range_type_t lrt; 1033 nvme_lba_range_t *lr; 1034 size_t n_lr; 1035 int i; 1036 1037 if (buf == NULL) 1038 return; 1039 1040 lrt.r = res; 1041 lr = buf; 1042 1043 n_lr = bufsize / sizeof (nvme_lba_range_t); 1044 if (n_lr > lrt.b.lr_num + 1) 1045 n_lr = lrt.b.lr_num + 1; 1046 1047 nvme_print_uint64(4, "Number of LBA Ranges", 1048 (uint8_t)lrt.b.lr_num + 1, NULL, NULL); 1049 1050 for (i = 0; i != n_lr; i++) { 1051 if (verbose == 0 && lr[i].lr_nlb == 0) 1052 continue; 1053 1054 nvme_print(4, "LBA Range", i, NULL); 1055 if (lr[i].lr_type < ARRAYSIZE(lba_range_types)) 1056 nvme_print_str(6, "Type", -1, 1057 lba_range_types[lr[i].lr_type], 0); 1058 else 1059 nvme_print_uint64(6, "Type", 1060 lr[i].lr_type, NULL, NULL); 1061 nvme_print(6, "Attributes", -1, NULL); 1062 nvme_print_bit(8, "Writable", 1063 lr[i].lr_attr.lr_write, "yes", "no"); 1064 nvme_print_bit(8, "Hidden", 1065 lr[i].lr_attr.lr_hidden, "yes", "no"); 1066 nvme_print_uint64(6, "Starting LBA", 1067 lr[i].lr_slba, NULL, NULL); 1068 nvme_print_uint64(6, "Number of Logical Blocks", 1069 lr[i].lr_nlb, NULL, NULL); 1070 nvme_print(6, "Unique Identifier", -1, 1071 "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x" 1072 "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", 1073 lr[i].lr_guid[0], lr[i].lr_guid[1], 1074 lr[i].lr_guid[2], lr[i].lr_guid[3], 1075 lr[i].lr_guid[4], lr[i].lr_guid[5], 1076 lr[i].lr_guid[6], lr[i].lr_guid[7], 1077 lr[i].lr_guid[8], lr[i].lr_guid[9], 1078 lr[i].lr_guid[10], lr[i].lr_guid[11], 1079 lr[i].lr_guid[12], lr[i].lr_guid[13], 1080 lr[i].lr_guid[14], lr[i].lr_guid[15]); 1081 } 1082 } 1083 1084 void 1085 nvme_print_feat_temperature(uint64_t res, void *b, size_t s, 1086 nvme_identify_ctrl_t *id) 1087 { 1088 _NOTE(ARGUNUSED(s)); 1089 _NOTE(ARGUNUSED(id)); 1090 nvme_temp_threshold_t tt; 1091 char *label = b; 1092 1093 tt.r = (uint32_t)res; 1094 nvme_print_temp(4, label, tt.b.tt_tmpth); 1095 } 1096 1097 void 1098 nvme_print_feat_error(uint64_t res, void *b, size_t s, 1099 nvme_identify_ctrl_t *id) 1100 { 1101 _NOTE(ARGUNUSED(b)); 1102 _NOTE(ARGUNUSED(s)); 1103 _NOTE(ARGUNUSED(id)); 1104 nvme_error_recovery_t er; 1105 1106 er.r = (uint32_t)res; 1107 if (er.b.er_tler > 0) 1108 nvme_print_uint64(4, "Time Limited Error Recovery", 1109 (uint32_t)er.b.er_tler * 100, NULL, "ms"); 1110 else 1111 nvme_print_str(4, "Time Limited Error Recovery", -1, 1112 "no time limit", 0); 1113 } 1114 1115 void 1116 nvme_print_feat_write_cache(uint64_t res, void *b, size_t s, 1117 nvme_identify_ctrl_t *id) 1118 { 1119 _NOTE(ARGUNUSED(b)); 1120 _NOTE(ARGUNUSED(s)); 1121 _NOTE(ARGUNUSED(id)); 1122 nvme_write_cache_t wc; 1123 1124 wc.r = (uint32_t)res; 1125 nvme_print_bit(4, "Volatile Write Cache", 1126 wc.b.wc_wce, "enabled", "disabled"); 1127 } 1128 1129 void 1130 nvme_print_feat_nqueues(uint64_t res, void *b, size_t s, 1131 nvme_identify_ctrl_t *id) 1132 { 1133 _NOTE(ARGUNUSED(b)); 1134 _NOTE(ARGUNUSED(s)); 1135 _NOTE(ARGUNUSED(id)); 1136 nvme_nqueues_t nq; 1137 1138 nq.r = (uint32_t)res; 1139 nvme_print_uint64(4, "Number of Submission Queues", 1140 nq.b.nq_nsq + 1, NULL, NULL); 1141 nvme_print_uint64(4, "Number of Completion Queues", 1142 nq.b.nq_ncq + 1, NULL, NULL); 1143 } 1144 1145 void 1146 nvme_print_feat_intr_coal(uint64_t res, void *b, size_t s, 1147 nvme_identify_ctrl_t *id) 1148 { 1149 _NOTE(ARGUNUSED(b)); 1150 _NOTE(ARGUNUSED(s)); 1151 _NOTE(ARGUNUSED(id)); 1152 nvme_intr_coal_t ic; 1153 1154 ic.r = (uint32_t)res; 1155 nvme_print_uint64(4, "Aggregation Threshold", 1156 ic.b.ic_thr + 1, NULL, NULL); 1157 nvme_print_uint64(4, "Aggregation Time", 1158 (uint16_t)ic.b.ic_time * 100, NULL, "us"); 1159 } 1160 void 1161 nvme_print_feat_intr_vect(uint64_t res, void *b, size_t s, 1162 nvme_identify_ctrl_t *id) 1163 { 1164 _NOTE(ARGUNUSED(b)); 1165 _NOTE(ARGUNUSED(s)); 1166 _NOTE(ARGUNUSED(id)); 1167 nvme_intr_vect_t iv; 1168 char *tmp; 1169 1170 iv.r = (uint32_t)res; 1171 if (asprintf(&tmp, "Vector %d Coalescing Disable", iv.b.iv_iv) < 0) 1172 err(-1, "nvme_print_feat_common()"); 1173 1174 nvme_print_bit(4, tmp, iv.b.iv_cd, "yes", "no"); 1175 } 1176 1177 void 1178 nvme_print_feat_write_atom(uint64_t res, void *b, size_t s, 1179 nvme_identify_ctrl_t *id) 1180 { 1181 _NOTE(ARGUNUSED(b)); 1182 _NOTE(ARGUNUSED(s)); 1183 _NOTE(ARGUNUSED(id)); 1184 nvme_write_atomicity_t wa; 1185 1186 wa.r = (uint32_t)res; 1187 nvme_print_bit(4, "Disable Normal", wa.b.wa_dn, "yes", "no"); 1188 } 1189 1190 void 1191 nvme_print_feat_async_event(uint64_t res, void *b, size_t s, 1192 nvme_identify_ctrl_t *idctl) 1193 { 1194 _NOTE(ARGUNUSED(b)); 1195 _NOTE(ARGUNUSED(s)); 1196 nvme_async_event_conf_t aec; 1197 1198 aec.r = (uint32_t)res; 1199 nvme_print_bit(4, "Available Space below threshold", 1200 aec.b.aec_avail, "enabled", "disabled"); 1201 nvme_print_bit(4, "Temperature above threshold", 1202 aec.b.aec_temp, "enabled", "disabled"); 1203 nvme_print_bit(4, "Device Reliability compromised", 1204 aec.b.aec_reliab, "enabled", "disabled"); 1205 nvme_print_bit(4, "Media read-only", 1206 aec.b.aec_readonly, "enabled", "disabled"); 1207 if (idctl->id_vwc.vwc_present != 0) 1208 nvme_print_bit(4, "Volatile Memory Backup failed", 1209 aec.b.aec_volatile, "enabled", "disabled"); 1210 } 1211 1212 void 1213 nvme_print_feat_auto_pst(uint64_t res, void *buf, size_t bufsize, 1214 nvme_identify_ctrl_t *id) 1215 { 1216 _NOTE(ARGUNUSED(id)); 1217 1218 nvme_auto_power_state_trans_t apst; 1219 nvme_auto_power_state_t *aps; 1220 int i; 1221 int cnt = bufsize / sizeof (nvme_auto_power_state_t); 1222 1223 if (buf == NULL) 1224 return; 1225 1226 apst.r = res; 1227 aps = buf; 1228 1229 nvme_print_bit(4, "Autonomous Power State Transition", 1230 apst.b.apst_apste, "enabled", "disabled"); 1231 for (i = 0; i != cnt; i++) { 1232 if (aps[i].apst_itps == 0 && aps[i].apst_itpt == 0) 1233 break; 1234 1235 nvme_print(4, "Power State", i, NULL); 1236 nvme_print_uint64(6, "Idle Transition Power State", 1237 (uint16_t)aps[i].apst_itps, NULL, NULL); 1238 nvme_print_uint64(6, "Idle Time Prior to Transition", 1239 aps[i].apst_itpt, NULL, "ms"); 1240 } 1241 } 1242 1243 void 1244 nvme_print_feat_progress(uint64_t res, void *b, size_t s, 1245 nvme_identify_ctrl_t *id) 1246 { 1247 _NOTE(ARGUNUSED(b)); 1248 _NOTE(ARGUNUSED(s)); 1249 _NOTE(ARGUNUSED(id)); 1250 nvme_software_progress_marker_t spm; 1251 1252 spm.r = (uint32_t)res; 1253 nvme_print_uint64(4, "Pre-Boot Software Load Count", 1254 spm.b.spm_pbslc, NULL, NULL); 1255 } 1256 1257 static const char * 1258 nvme_str_generic_error(int sc) 1259 { 1260 switch (sc) { 1261 case NVME_CQE_SC_GEN_SUCCESS: 1262 return ("Success"); 1263 default: 1264 return ("See message log (usually /var/adm/messages) " 1265 "for details"); 1266 } 1267 } 1268 1269 static const char * 1270 nvme_str_specific_error(int sc) 1271 { 1272 switch (sc) { 1273 case NVME_CQE_SC_SPC_INV_FW_SLOT: 1274 return ("Invalid firmware slot"); 1275 case NVME_CQE_SC_SPC_INV_FW_IMG: 1276 return ("Invalid firmware image"); 1277 case NVME_CQE_SC_SPC_FW_RESET: 1278 return ("Conventional reset required - use " 1279 "'reboot -p' or similar"); 1280 case NVME_CQE_SC_SPC_FW_NSSR: 1281 return ("NVM subsystem reset required - power cycle " 1282 "your system"); 1283 case NVME_CQE_SC_SPC_FW_NEXT_RESET: 1284 return ("Image will be activated at next reset"); 1285 case NVME_CQE_SC_SPC_FW_MTFA: 1286 return ("Activation requires maxmimum time violation"); 1287 case NVME_CQE_SC_SPC_FW_PROHIBITED: 1288 return ("Activation prohibited"); 1289 default: 1290 return ("See message log (usually /var/adm/messages) " 1291 "for details"); 1292 } 1293 } 1294 1295 const char * 1296 nvme_str_error(int sct, int sc) 1297 { 1298 switch (sct) { 1299 case NVME_CQE_SCT_GENERIC: 1300 return (nvme_str_generic_error(sc)); 1301 1302 case NVME_CQE_SCT_SPECIFIC: 1303 return (nvme_str_specific_error(sc)); 1304 1305 default: 1306 return ("See message log (usually /var/adm/messages) " 1307 "for details"); 1308 } 1309 } 1310