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