xref: /illumos-gate/usr/src/cmd/nvmeadm/nvmeadm_print.c (revision 8d5300d3859436fa82e7199f50011911090c65dc)
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 2021 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 *, boolean_t, uint_t, const char *,
45     const char *);
46 
47 #define	ARRAYSIZE(x)		(sizeof (x) / sizeof (*(x)))
48 
49 static const char *generic_status_codes[] = {
50 	"Successful Completion",
51 	"Invalid Command Opcode",
52 	"Invalid Field in Command",
53 	"Command ID Conflict",
54 	"Data Transfer Error",
55 	"Commands Aborted due to Power Loss Notification",
56 	"Internal Error",
57 	"Command Abort Requested",
58 	"Command Aborted due to SQ Deletion",
59 	"Command Aborted due to Failed Fused Command",
60 	"Command Aborted due to Missing Fused Command",
61 	"Invalid Namespace or Format",
62 	"Command Sequence Error",
63 	/* NVMe 1.1 */
64 	"Invalid SGL Segment Descriptor",
65 	"Invalid Number of SGL Descriptors",
66 	"Data SGL Length Invalid",
67 	"Metadata SGL Length Invalid",
68 	"SGL Descriptor Type Invalid",
69 	/* NVMe 1.2 */
70 	"Invalid Use of Controller Memory Buffer",
71 	"PRP Offset Invalid",
72 	"Atomic Write Unit Exceeded"
73 };
74 
75 static const char *specific_status_codes[] = {
76 	"Completion Queue Invalid",
77 	"Invalid Queue Identifier",
78 	"Invalid Queue Size",
79 	"Abort Command Limit Exceeded",
80 	"Reserved",
81 	"Asynchronous Event Request Limit Exceeded",
82 	"Invalid Firmware Slot",
83 	"Invalid Firmware Image",
84 	"Invalid Interrupt Vector",
85 	"Invalid Log Page",
86 	"Invalid Format",
87 	"Firmware Activation Requires Conventional Reset",
88 	"Invalid Queue Deletion",
89 	/* NVMe 1.1 */
90 	"Feature Identifier Not Saveable",
91 	"Feature Not Changeable",
92 	"Feature Not Namespace Specific",
93 	"Firmware Activation Requires NVM Subsystem Reset",
94 	/* NVMe 1.2 */
95 	"Firmware Activation Requires Reset",
96 	"Firmware Activation Requires Maximum Time Violation",
97 	"Firmware Activation Prohibited",
98 	"Overlapping Range",
99 	"Namespace Insufficient Capacity",
100 	"Namespace Identifier Unavailable",
101 	"Reserved",
102 	"Namespace Already Attached",
103 	"Namespace Is Private",
104 	"Namespace Not Attached",
105 	"Thin Provisioning Not Supported",
106 	"Controller List Invalid"
107 };
108 
109 static const char *generic_nvm_status_codes[] = {
110 	"LBA Out Of Range",
111 	"Capacity Exceeded",
112 	"Namespace Not Ready",
113 	/* NVMe 1.1 */
114 	"Reservation Conflict",
115 	/* NVMe 1.2 */
116 	"Format In Progress",
117 };
118 
119 static const char *specific_nvm_status_codes[] = {
120 	"Conflicting Attributes",
121 	"Invalid Protection Information",
122 	"Attempted Write to Read Only Range"
123 };
124 
125 static const char *media_nvm_status_codes[] = {
126 	"Write Fault",
127 	"Unrecovered Read Error",
128 	"End-to-End Guard Check Error",
129 	"End-to-End Application Tag Check Error",
130 	"End-to-End Reference Tag Check Error",
131 	"Compare Failure",
132 	"Access Denied",
133 	/* NVMe 1.2 */
134 	"Deallocated or Unwritten Logical Block"
135 };
136 
137 static const char *status_code_types[] = {
138 	"Generic Command Status",
139 	"Command Specific Status",
140 	"Media Errors",
141 	"Reserved",
142 	"Reserved",
143 	"Reserved",
144 	"Reserved",
145 	"Vendor Specific"
146 };
147 
148 static const char *lbaf_relative_performance[] = {
149 	"Best", "Better", "Good", "Degraded"
150 };
151 
152 static const char *lba_range_types[] = {
153 	"Reserved", "Filesystem", "RAID", "Cache", "Page/Swap File"
154 };
155 
156 /*
157  * nvme_print
158  *
159  * This function prints a string indented by the specified number of spaces,
160  * optionally followed by the specified index if it is >= 0. If a format string
161  * is specified, a single colon and the required number of spaces for alignment
162  * are printed before the format string and any remaining arguments are passed
163  * vprintf.
164  *
165  * NVME_PRINT_ALIGN was chosen so that all values will be lined up nicely even
166  * for the longest name at its default indentation.
167  */
168 
169 #define	NVME_PRINT_ALIGN	43
170 
171 void
172 nvme_print(int indent, const char *name, int index, const char *fmt, ...)
173 {
174 	int align = NVME_PRINT_ALIGN - (indent + strlen(name) + 1);
175 	va_list ap;
176 
177 	if (index >= 0)
178 		align -= snprintf(NULL, 0, " %d", index);
179 
180 	if (align < 0)
181 		align = 0;
182 
183 	va_start(ap, fmt);
184 
185 	(void) printf("%*s%s", indent, "", name);
186 
187 	if (index >= 0)
188 		(void) printf(" %d", index);
189 
190 	if (fmt != NULL) {
191 		(void) printf(": %*s", align, "");
192 		(void) vprintf(fmt, ap);
193 	}
194 
195 	(void) printf("\n");
196 	va_end(ap);
197 }
198 
199 /*
200  * nvme_strlen -- return length of string without trailing whitespace
201  */
202 static int
203 nvme_strlen(const char *str, int len)
204 {
205 	if (len < 0)
206 		return (0);
207 
208 	while (str[--len] == ' ')
209 		;
210 
211 	return (++len);
212 }
213 
214 /*
215  * nvme_print_str -- print a string up to the specified length
216  */
217 static void
218 nvme_print_str(int indent, const char *name, int index, const char *value,
219     int len)
220 {
221 	if (len == 0)
222 		len = strlen(value);
223 
224 	nvme_print(indent, name, index, "%.*s", nvme_strlen(value, len), value);
225 }
226 
227 /*
228  * nvme_print_double -- print a double up to a specified number of places with
229  * optional unit
230  */
231 static void
232 nvme_print_double(int indent, const char *name, double value, int places,
233     const char *unit)
234 {
235 	if (unit == NULL)
236 		unit = "";
237 
238 	nvme_print(indent, name, -1, "%.*g%s", places, value, unit);
239 }
240 
241 /*
242  * nvme_print_int64 -- print int64_t with optional unit in decimal or another
243  * format specified
244  */
245 static void
246 nvme_print_int64(int indent, const char *name, uint64_t value, const char *fmt,
247     const char *unit)
248 {
249 	char *tmp_fmt;
250 
251 	if (unit == NULL)
252 		unit = "";
253 
254 	if (fmt == NULL)
255 		fmt = "%"PRId64;
256 
257 	if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0)
258 		err(-1, "nvme_print_int64()");
259 
260 	nvme_print(indent, name, -1, tmp_fmt, value, unit);
261 
262 	free(tmp_fmt);
263 }
264 
265 /*
266  * nvme_print_temp -- The NVMe specification passes most temperature values as
267  * uint16_t values that are encoded in kelvin. This converts them in one place
268  * to Celsius.
269  */
270 static void
271 nvme_print_temp(int indent, const char *name, uint16_t value)
272 {
273 	int64_t temp = (int64_t)value;
274 	temp -= 273;
275 	nvme_print_int64(indent, name, temp, NULL, "C");
276 }
277 
278 /*
279  * nvme_print_uint64 -- print uint64_t with optional unit in decimal or another
280  * format specified
281  */
282 static void
283 nvme_print_uint64(int indent, const char *name, uint64_t value, const char *fmt,
284     const char *unit)
285 {
286 	char *tmp_fmt;
287 
288 	if (unit == NULL)
289 		unit = "";
290 
291 	if (fmt == NULL)
292 		fmt = "%"PRIu64;
293 
294 	if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0)
295 		err(-1, "nvme_print_uint64()");
296 
297 	nvme_print(indent, name, -1, tmp_fmt, value, unit);
298 
299 	free(tmp_fmt);
300 }
301 
302 /*
303  * nvme_print_uint128 -- print a 128bit uint with optional unit, after applying
304  * binary and/or decimal shifting
305  */
306 static void
307 nvme_print_uint128(int indent, const char *name, nvme_uint128_t value,
308     const char *unit, int scale_bits, int scale_tens)
309 {
310 	const char hex[] = "0123456789abcdef";
311 	uint8_t o[(128 + scale_bits) / 3];
312 	char p[sizeof (o) * 2];
313 	char *pp = &p[0];
314 	int i, x;
315 	uint64_t rem = 0;
316 
317 	if (unit == NULL)
318 		unit = "";
319 
320 	/*
321 	 * Don't allow binary shifting by more than 64 bits to keep the
322 	 * arithmetic simple. Also limit decimal shifting based on the size
323 	 * of any possible remainder from binary shifting.
324 	 */
325 	assert(scale_bits <= 64);
326 	assert(scale_tens <= (64 - scale_bits) / 3);
327 
328 	bzero(o, sizeof (o));
329 	bzero(p, sizeof (p));
330 
331 	/*
332 	 * Convert the two 64-bit numbers into a series of BCD digits using
333 	 * a double-dabble algorithm. By using more or less iterations than
334 	 * 128 we can do a binary shift in either direction.
335 	 */
336 	for (x = 0; x != 128 - scale_bits; x++) {
337 		for (i = 0; i != sizeof (o); i++) {
338 			if ((o[i] & 0xf0) > 0x40)
339 				o[i] += 0x30;
340 
341 			if ((o[i] & 0xf) > 4)
342 				o[i] += 3;
343 		}
344 
345 		for (i = 0; i != sizeof (o) - 1; i++)
346 			o[i] = (o[i] << 1) + (o[i+1] >> 7);
347 
348 		o[i] = (o[i] << 1) + (value.hi >> 63);
349 
350 		value.hi = (value.hi << 1) + (value.lo >> 63);
351 		value.lo = (value.lo << 1);
352 	}
353 
354 	/*
355 	 * If we're supposed to do a decimal left shift (* 10^x), too,
356 	 * calculate the remainder of the previous binary shift operation.
357 	 */
358 	if (scale_tens > 0) {
359 		rem = value.hi >> (64 - scale_bits);
360 
361 		for (i = 0; i != scale_tens; i++)
362 			rem *= 10;
363 
364 		rem >>= scale_bits;
365 	}
366 
367 	/*
368 	 * Construct the decimal number for printing. Skip leading zeros.
369 	 */
370 	for (i = 0; i < sizeof (o); i++)
371 		if (o[i] != 0)
372 			break;
373 
374 	if (i == sizeof (o)) {
375 		/*
376 		 * The converted number is 0. Just print the calculated
377 		 * remainder and return.
378 		 */
379 		nvme_print(indent, name, -1, "%"PRId64"%s", rem, unit);
380 		return;
381 	} else {
382 		if (o[i] > 0xf)
383 			*pp++ = hex[o[i] >> 4];
384 
385 		*pp++ = hex[o[i] & 0xf];
386 
387 		for (i++; i < sizeof (o); i++) {
388 			*pp++ = hex[o[i] >> 4];
389 			*pp++ = hex[o[i] & 0xf];
390 		}
391 	}
392 
393 	/*
394 	 * For negative decimal scaling, use the printf precision specifier to
395 	 * truncate the results according to the requested decimal scaling. For
396 	 * positive decimal scaling we print the remainder padded with 0.
397 	 */
398 	nvme_print(indent, name, -1, "%.*s%0.*"PRId64"%s",
399 	    strlen(p) + scale_tens, p,
400 	    scale_tens > 0 ? scale_tens : 0, rem,
401 	    unit);
402 }
403 
404 /*
405  * nvme_print_bit -- print a bit with optional names for both states
406  */
407 static void
408 nvme_print_bit(int indent, const char *name, boolean_t valid_vers, uint_t value,
409     const char *s_true, const char *s_false)
410 {
411 	if (s_true == NULL)
412 		s_true = "supported";
413 	if (s_false == NULL)
414 		s_false = "unsupported";
415 
416 	if (!valid_vers)
417 		value = 0;
418 
419 	nvme_print(indent, name, -1, "%s", value ? s_true : s_false);
420 }
421 
422 /*
423  * nvme_print_version -- print a uint32_t encoded nvme version
424  */
425 static void
426 nvme_print_version(int indent, const char *name, uint32_t value)
427 {
428 	nvme_reg_vs_t vers;
429 
430 	vers.r = value;
431 	nvme_print(indent, name, -1, "%u.%u", vers.b.vs_mjr, vers.b.vs_mnr);
432 }
433 
434 /*
435  * nvme_print_ctrl_summary -- print a 1-line summary of the IDENTIFY CONTROLLER
436  * data structure
437  */
438 void
439 nvme_print_ctrl_summary(nvme_identify_ctrl_t *idctl, nvme_version_t *version)
440 {
441 	(void) printf("model: %.*s, serial: %.*s, FW rev: %.*s, NVMe v%d.%d\n",
442 	    nvme_strlen(idctl->id_model, sizeof (idctl->id_model)),
443 	    idctl->id_model,
444 	    nvme_strlen(idctl->id_serial, sizeof (idctl->id_serial)),
445 	    idctl->id_serial,
446 	    nvme_strlen(idctl->id_fwrev, sizeof (idctl->id_fwrev)),
447 	    idctl->id_fwrev,
448 	    version->v_major, version->v_minor);
449 }
450 
451 /*
452  * nvme_print_nsid_summary -- print a 1-line summary of the IDENTIFY NAMESPACE
453  * data structure
454  */
455 void
456 nvme_print_nsid_summary(nvme_identify_nsid_t *idns)
457 {
458 	int bsize = 1 << idns->id_lbaf[idns->id_flbas.lba_format].lbaf_lbads;
459 
460 	(void) printf("Size = %"PRId64" MB, "
461 	    "Capacity = %"PRId64" MB, "
462 	    "Used = %"PRId64" MB\n",
463 	    idns->id_nsize * bsize / 1024 / 1024,
464 	    idns->id_ncap * bsize / 1024 / 1024,
465 	    idns->id_nuse * bsize / 1024 / 1024);
466 
467 }
468 
469 /*
470  * nvme_print_identify_ctrl
471  *
472  * This function pretty-prints the structure returned by the IDENTIFY CONTROLLER
473  * command.
474  */
475 void
476 nvme_print_identify_ctrl(nvme_identify_ctrl_t *idctl,
477     nvme_capabilities_t *cap, nvme_version_t *version)
478 {
479 	int i;
480 
481 	nvme_print(0, "Identify Controller", -1, NULL);
482 	nvme_print(2, "Controller Capabilities and Features", -1, NULL);
483 	nvme_print_str(4, "Model", -1,
484 	    idctl->id_model, sizeof (idctl->id_model));
485 	nvme_print_str(4, "Serial", -1,
486 	    idctl->id_serial, sizeof (idctl->id_serial));
487 	nvme_print_str(4, "Firmware Revision", -1,
488 	    idctl->id_fwrev, sizeof (idctl->id_fwrev));
489 	if (verbose) {
490 		nvme_print_uint64(4, "PCI vendor ID",
491 		    idctl->id_vid, "0x%0.4"PRIx64, NULL);
492 		nvme_print_uint64(4, "subsystem vendor ID",
493 		    idctl->id_ssvid, "0x%0.4"PRIx64, NULL);
494 		nvme_print_uint64(4, "Recommended Arbitration Burst",
495 		    idctl->id_rab, NULL, NULL);
496 		nvme_print(4, "Vendor IEEE OUI", -1, "%0.2X-%0.2X-%0.2X",
497 		    idctl->id_oui[0], idctl->id_oui[1], idctl->id_oui[2]);
498 	}
499 	nvme_print(4, "Multi-Interface Capabilities", -1, NULL);
500 	nvme_print_bit(6, "Multiple PCI Express ports",
501 	    nvme_version_check(version, 1, 0),
502 	    idctl->id_mic.m_multi_pci, NULL, NULL);
503 	nvme_print_bit(6, "Multiple Controller Support",
504 	    nvme_version_check(version, 1, 0),
505 	    idctl->id_mic.m_multi_ctrl, NULL, NULL);
506 	nvme_print_bit(6, "Controller is an SR-IOV Virtual Function",
507 	    nvme_version_check(version, 1, 0),
508 	    idctl->id_mic.m_sr_iov, NULL, NULL);
509 	nvme_print_bit(6, "Asymmetric Namespace Access Reporting",
510 	    nvme_version_check(version, 1, 4),
511 	    idctl->id_mic.m_anar_sup, NULL, NULL);
512 
513 	if (idctl->id_mdts > 0)
514 		nvme_print_uint64(4, "Maximum Data Transfer Size",
515 		    (1 << idctl->id_mdts) * cap->mpsmin / 1024, NULL, "kB");
516 	else
517 		nvme_print_str(4, "Maximum Data Transfer Size", -1,
518 		    "unlimited", 0);
519 
520 	if (nvme_version_check(version, 1, 1)) {
521 		nvme_print_uint64(4, "Unique Controller Identifier",
522 		    idctl->id_cntlid, "0x%0.4"PRIx64, NULL);
523 	}
524 
525 	if (nvme_version_check(version, 1, 2)) {
526 		nvme_print_version(4, "NVMe Version",
527 		    idctl->id_ver);
528 
529 		if (idctl->id_rtd3r != 0) {
530 			nvme_print_uint64(4, "RTD3 Resume Latency",
531 			    idctl->id_rtd3r, NULL, "us");
532 		}
533 
534 		if (idctl->id_rtd3e != 0) {
535 			nvme_print_uint64(4, "RTD3 Entry Latency",
536 			    idctl->id_rtd3e, NULL, "us");
537 		}
538 	}
539 
540 	if (verbose) {
541 		nvme_print(4, "Optional Asynchronous Events Supported", -1,
542 		    NULL);
543 		nvme_print_bit(6, "Namespace Attribute Notices",
544 		    nvme_version_check(version, 1, 2),
545 		    idctl->id_oaes.oaes_nsan, NULL, NULL);
546 		nvme_print_bit(6, "Firmware Activation Notices",
547 		    nvme_version_check(version, 1, 2),
548 		    idctl->id_oaes.oaes_fwact, NULL, NULL);
549 		nvme_print_bit(6, "Asynchronous Namespace Access Change "
550 		    "Notices",
551 		    nvme_version_check(version, 1, 4),
552 		    idctl->id_oaes.oaes_ansacn, NULL, NULL);
553 		nvme_print_bit(6, "Predictable Latency Event Aggregation",
554 		    nvme_version_check(version, 1, 4),
555 		    idctl->id_oaes.oaes_plat, NULL, NULL);
556 		nvme_print_bit(6, "LBA Status Information Notices",
557 		    nvme_version_check(version, 1, 4),
558 		    idctl->id_oaes.oaes_lbasi, NULL, NULL);
559 		nvme_print_bit(6, "Endurance Group Event Aggregate Log Page "
560 		    "Change Notices",
561 		    nvme_version_check(version, 1, 4),
562 		    idctl->id_oaes.oaes_egeal, NULL, NULL);
563 
564 		nvme_print(4, "Controller Attributes", -1,
565 		    NULL);
566 		nvme_print_bit(6, "128-bit Host Identifier",
567 		    nvme_version_check(version, 1, 2),
568 		    idctl->id_ctratt.ctrat_hid, NULL, NULL);
569 		nvme_print_bit(6, "Non-Operational Power State Permissive Mode",
570 		    nvme_version_check(version, 1, 3),
571 		    idctl->id_ctratt.ctrat_nops, NULL, NULL);
572 		nvme_print_bit(6, "NVM Sets",
573 		    nvme_version_check(version, 1, 4),
574 		    idctl->id_ctratt.ctrat_nvmset, NULL, NULL);
575 		nvme_print_bit(6, "Read Recovery Levels",
576 		    nvme_version_check(version, 1, 4),
577 		    idctl->id_ctratt.ctrat_rrl, NULL, NULL);
578 		nvme_print_bit(6, "Endurance Groups",
579 		    nvme_version_check(version, 1, 4),
580 		    idctl->id_ctratt.ctrat_engrp, NULL, NULL);
581 		nvme_print_bit(6, "Predictable Latency Mode",
582 		    nvme_version_check(version, 1, 4),
583 		    idctl->id_ctratt.ctrat_plm, NULL, NULL);
584 		nvme_print_bit(6, "Traffic Based Keep Alive",
585 		    nvme_version_check(version, 1, 4),
586 		    idctl->id_ctratt.ctrat_tbkas, NULL, NULL);
587 		nvme_print_bit(6, "Namespace Granularity",
588 		    nvme_version_check(version, 1, 4),
589 		    idctl->id_ctratt.ctrat_nsg, NULL, NULL);
590 		nvme_print_bit(6, "SQ Associations",
591 		    nvme_version_check(version, 1, 4),
592 		    idctl->id_ctratt.ctrat_sqass, NULL, NULL);
593 		nvme_print_bit(6, "UUID List",
594 		    nvme_version_check(version, 1, 4),
595 		    idctl->id_ctratt.ctrat_uuid, NULL, NULL);
596 
597 		nvme_print(4, "Read Recovery Levels", -1,
598 		    NULL);
599 		nvme_print_bit(6, "Read Recovery Level 0",
600 		    nvme_version_check(version, 1, 4),
601 		    idctl->id_rrls & (1 << 0), NULL, NULL);
602 		nvme_print_bit(6, "Read Recovery Level 1",
603 		    nvme_version_check(version, 1, 4),
604 		    idctl->id_rrls & (1 << 1), NULL, NULL);
605 		nvme_print_bit(6, "Read Recovery Level 2",
606 		    nvme_version_check(version, 1, 4),
607 		    idctl->id_rrls & (1 << 2), NULL, NULL);
608 		nvme_print_bit(6, "Read Recovery Level 3",
609 		    nvme_version_check(version, 1, 4),
610 		    idctl->id_rrls & (1 << 3), NULL, NULL);
611 		nvme_print_bit(6, "Read Recovery Level 4 - Default",
612 		    nvme_version_check(version, 1, 4),
613 		    idctl->id_rrls & (1 << 4), NULL, NULL);
614 		nvme_print_bit(6, "Read Recovery Level 5",
615 		    nvme_version_check(version, 1, 4),
616 		    idctl->id_rrls & (1 << 5), NULL, NULL);
617 		nvme_print_bit(6, "Read Recovery Level 6",
618 		    nvme_version_check(version, 1, 4),
619 		    idctl->id_rrls & (1 << 6), NULL, NULL);
620 		nvme_print_bit(6, "Read Recovery Level 7",
621 		    nvme_version_check(version, 1, 4),
622 		    idctl->id_rrls & (1 << 7), NULL, NULL);
623 		nvme_print_bit(6, "Read Recovery Level 8",
624 		    nvme_version_check(version, 1, 4),
625 		    idctl->id_rrls & (1 << 8), NULL, NULL);
626 		nvme_print_bit(6, "Read Recovery Level 9",
627 		    nvme_version_check(version, 1, 4),
628 		    idctl->id_rrls & (1 << 9), NULL, NULL);
629 		nvme_print_bit(6, "Read Recovery Level 10",
630 		    nvme_version_check(version, 1, 4),
631 		    idctl->id_rrls & (1 << 10), NULL, NULL);
632 		nvme_print_bit(6, "Read Recovery Level 11",
633 		    nvme_version_check(version, 1, 4),
634 		    idctl->id_rrls & (1 << 11), NULL, NULL);
635 		nvme_print_bit(6, "Read Recovery Level 12",
636 		    nvme_version_check(version, 1, 4),
637 		    idctl->id_rrls & (1 << 12), NULL, NULL);
638 		nvme_print_bit(6, "Read Recovery Level 13",
639 		    nvme_version_check(version, 1, 4),
640 		    idctl->id_rrls & (1 << 13), NULL, NULL);
641 		nvme_print_bit(6, "Read Recovery Level 14",
642 		    nvme_version_check(version, 1, 4),
643 		    idctl->id_rrls & (1 << 14), NULL, NULL);
644 		nvme_print_bit(6, "Read Recovery Level 15 - Fast Fail",
645 		    nvme_version_check(version, 1, 4),
646 		    idctl->id_rrls & (1 << 15), NULL, NULL);
647 	}
648 
649 	if (nvme_version_check(version, 1, 4)) {
650 		switch (idctl->id_cntrltype) {
651 		case NVME_CNTRLTYPE_RSVD:
652 			nvme_print_str(4, "Controller Type", -1,
653 			    "not reported", 0);
654 			break;
655 		case NVME_CNTRLTYPE_IO:
656 			nvme_print_str(4, "Controller Type", -1, "I/O", 0);
657 			break;
658 		case NVME_CNTRLTYPE_DISC:
659 			nvme_print_str(4, "Controller Type", -1, "discovery",
660 			    0);
661 			break;
662 		case NVME_CNTRLTYPE_ADMIN:
663 			nvme_print_str(4, "Controller Type", -1,
664 			    "administrative", 0);
665 			break;
666 		default:
667 			nvme_print(4, "Controller Type", -1,
668 			    "unknown reserved value: %u", idctl->id_cntrltype);
669 			break;
670 		}
671 	} else {
672 		nvme_print_str(4, "Controller Type", -1, "not reported", 0);
673 	}
674 
675 	if (nvme_version_check(version, 1, 3)) {
676 		uint8_t zguid[16] = { 0 };
677 
678 		if (memcmp(zguid, idctl->id_frguid, sizeof (zguid)) != 0) {
679 			nvme_print(4, "FRU GUID", -1, "%02x%02x%02x%02x%02x%02x"
680 			    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
681 			    idctl->id_frguid[0], idctl->id_frguid[1],
682 			    idctl->id_frguid[2], idctl->id_frguid[3],
683 			    idctl->id_frguid[4], idctl->id_frguid[5],
684 			    idctl->id_frguid[6], idctl->id_frguid[7],
685 			    idctl->id_frguid[8], idctl->id_frguid[9],
686 			    idctl->id_frguid[10], idctl->id_frguid[11],
687 			    idctl->id_frguid[12], idctl->id_frguid[13],
688 			    idctl->id_frguid[14], idctl->id_frguid[15]);
689 		} else {
690 			nvme_print_str(4, "FRU GUID", -1, "unsupported", 0);
691 		}
692 	} else {
693 		nvme_print_str(4, "FRU GUID", -1, "unsupported", 0);
694 	}
695 
696 	if (nvme_version_check(version, 1, 4)) {
697 		nvme_print_uint64(4, "Command Retry Delay Time 1",
698 		    idctl->id_crdt1 * 100, NULL, "ms");
699 		nvme_print_uint64(4, "Command Retry Delay Time 2",
700 		    idctl->id_crdt2 * 100, NULL, "ms");
701 		nvme_print_uint64(4, "Command Retry Delay Time 3",
702 		    idctl->id_crdt3 * 100, NULL, "ms");
703 	} else {
704 		nvme_print_str(4, "Command Retry Delay Time 1", -1,
705 		    "unsupported", 0);
706 		nvme_print_str(4, "Command Retry Delay Time 2", -1,
707 		    "unsupported", 0);
708 		nvme_print_str(4, "Command Retry Delay Time 3", -1,
709 		    "unsupported", 0);
710 	}
711 
712 	/*
713 	 * The NVMe-MI spec claimed a portion of the identify controller data;
714 	 * however, there's no way to actually figure out if this data is valid
715 	 * or not. We basically have to rely on the NVMe spec's initialized to
716 	 * zero behavior for this region. Unfortunately, there's no way to get
717 	 * the NVMe-MI version to know when fields were added here so we
718 	 * basically treat the minimum version required as that of when the
719 	 * NVMe-MI region was reserved in the NVMe spec, which is 1.2. Note,
720 	 * these bytes go in reverse order because they're allocating them in
721 	 * reverse order.
722 	 */
723 	if (verbose) {
724 		nvme_print(2, "NVMe Management Interface", -1, NULL);
725 		nvme_print(4, "Management Endpoint Capabilities", -1, NULL);
726 		nvme_print_bit(6, "SMBus/I2C Port Management Endpoint",
727 		    nvme_version_check(version, 1, 2),
728 		    idctl->id_mec.mec_smbusme, NULL, NULL);
729 		nvme_print_bit(6, "PCIe Port Management Endpoint",
730 		    nvme_version_check(version, 1, 2),
731 		    idctl->id_mec.mec_pcieme, NULL, NULL);
732 
733 		if (idctl->id_vpdwc.vwci_valid != 0) {
734 			nvme_print_uint64(4, "VPD Write Cycles Remaining",
735 			    idctl->id_vpdwc.vwci_crem, NULL, NULL);
736 		} else {
737 			nvme_print_str(4, "VPD Write Cycles Remaining", -1,
738 			    "invalid or unsupported", 0);
739 		}
740 
741 		if (idctl->id_nvmsr.nvmsr_nvmesd == 0 &&
742 		    idctl->id_nvmsr.nvmsr_nvmee == 0 &&
743 		    idctl->id_nvmsr.nvmsr_rsvd == 0) {
744 			nvme_print_str(4, "NVM Subsystem Report", -1,
745 			    "unsupported", 0);
746 		} else {
747 			nvme_print(4, "NVM Subsystem Report", -1, NULL);
748 			nvme_print_bit(6, "NVMe Storage Device",
749 			    nvme_version_check(version, 1, 2),
750 			    idctl->id_nvmsr.nvmsr_nvmesd, NULL, NULL);
751 			nvme_print_bit(6, "NVMe Enclosure",
752 			    nvme_version_check(version, 1, 2),
753 			    idctl->id_nvmsr.nvmsr_nvmee, NULL, NULL);
754 		}
755 	}
756 
757 	nvme_print(2, "Admin Command Set Attributes", -1, NULL);
758 	nvme_print(4, "Optional Admin Command Support", -1, NULL);
759 	nvme_print_bit(6, "Security Send & Receive",
760 	    nvme_version_check(version, 1, 0),
761 	    idctl->id_oacs.oa_security, NULL, NULL);
762 	nvme_print_bit(6, "Format NVM",
763 	    nvme_version_check(version, 1, 0),
764 	    idctl->id_oacs.oa_format, NULL, NULL);
765 	nvme_print_bit(6, "Firmware Activate & Download",
766 	    nvme_version_check(version, 1, 0),
767 	    idctl->id_oacs.oa_firmware, NULL, NULL);
768 	nvme_print_bit(6, "Namespace Management",
769 	    nvme_version_check(version, 1, 2),
770 	    idctl->id_oacs.oa_nsmgmt, NULL, NULL);
771 	nvme_print_bit(6, "Device Self-test",
772 	    nvme_version_check(version, 1, 3),
773 	    idctl->id_oacs.oa_selftest, NULL, NULL);
774 	nvme_print_bit(6, "Directives",
775 	    nvme_version_check(version, 1, 3),
776 	    idctl->id_oacs.oa_direct, NULL, NULL);
777 	nvme_print_bit(6, "NVME-MI Send and Receive",
778 	    nvme_version_check(version, 1, 3),
779 	    idctl->id_oacs.oa_nvmemi, NULL, NULL);
780 	nvme_print_bit(6, "Virtualization Management",
781 	    nvme_version_check(version, 1, 3),
782 	    idctl->id_oacs.oa_virtmgmt, NULL, NULL);
783 	nvme_print_bit(6, "Doorbell Buffer Config",
784 	    nvme_version_check(version, 1, 3),
785 	    idctl->id_oacs.oa_doorbell, NULL, NULL);
786 	nvme_print_bit(6, "Get LBA Status",
787 	    nvme_version_check(version, 1, 4),
788 	    idctl->id_oacs.oa_lbastat, NULL, NULL);
789 	if (verbose) {
790 		nvme_print_uint64(4, "Abort Command Limit",
791 		    (uint16_t)idctl->id_acl + 1, NULL, NULL);
792 		nvme_print_uint64(4, "Asynchronous Event Request Limit",
793 		    (uint16_t)idctl->id_aerl + 1, NULL, NULL);
794 	}
795 	nvme_print(4, "Firmware Updates", -1, NULL);
796 	nvme_print_bit(6, "Firmware Slot 1",
797 	    nvme_version_check(version, 1, 0),
798 	    idctl->id_frmw.fw_readonly, "read-only", "writable");
799 	nvme_print_uint64(6, "No. of Firmware Slots",
800 	    idctl->id_frmw.fw_nslot, NULL, NULL);
801 	nvme_print_bit(6, "Activate Without Reset",
802 	    nvme_version_check(version, 1, 2),
803 	    idctl->id_frmw.fw_norst, NULL, NULL);
804 
805 	nvme_print(2, "Log Page Attributes", -1, NULL);
806 	nvme_print_bit(6, "Per Namespace SMART/Health info",
807 	    nvme_version_check(version, 1, 0),
808 	    idctl->id_lpa.lp_smart, NULL, NULL);
809 	nvme_print_bit(6, "Commands Supported and Effects",
810 	    nvme_version_check(version, 1, 2),
811 	    idctl->id_lpa.lp_cmdeff, NULL, NULL);
812 	nvme_print_bit(6, "Get Log Page Extended Data",
813 	    nvme_version_check(version, 1, 2),
814 	    idctl->id_lpa.lp_extsup, NULL, NULL);
815 	nvme_print_bit(6, "Telemetry Log Pages",
816 	    nvme_version_check(version, 1, 3),
817 	    idctl->id_lpa.lp_telemetry, NULL, NULL);
818 	nvme_print_bit(6, "Persistent Event Log",
819 	    nvme_version_check(version, 1, 4),
820 	    idctl->id_lpa.lp_persist, NULL, NULL);
821 
822 	nvme_print_uint64(4, "Error Log Page Entries",
823 	    (uint16_t)idctl->id_elpe + 1, NULL, NULL);
824 	nvme_print_uint64(4, "Number of Power States",
825 	    (uint16_t)idctl->id_npss + 1, NULL, NULL);
826 	if (verbose) {
827 		nvme_print_bit(4, "Admin Vendor-specific Command Format",
828 		    nvme_version_check(version, 1, 0),
829 		    idctl->id_avscc.av_spec, "standard", "vendor-specific");
830 	}
831 
832 	nvme_print_bit(4, "Autonomous Power State Transitions",
833 	    nvme_version_check(version, 1, 1),
834 	    idctl->id_apsta.ap_sup, NULL, NULL);
835 
836 	if (nvme_version_check(version, 1, 2)) {
837 		nvme_print_temp(4, "Warning Composite Temperature Threshold",
838 		    idctl->ap_wctemp);
839 		nvme_print_temp(4, "Critical Composite Temperature Threshold",
840 		    idctl->ap_cctemp);
841 	} else {
842 		nvme_print_str(4, "Warning Composite Temperature Threshold",
843 		    -1, "unspecified", 0);
844 		nvme_print_str(4, "Critical Composite Temperature Threshold",
845 		    -1, "unspecified", 0);
846 	}
847 
848 	if (verbose) {
849 		if (idctl->ap_mtfa != 0) {
850 			nvme_print_uint64(4, "Maximum Firmware Activation Time",
851 			    idctl->ap_mtfa * 100, NULL, "ms");
852 		} else {
853 			nvme_print_str(4, "Maximum Firmware Activation Time",
854 			    -1, "unknown", 0);
855 		}
856 
857 		if (idctl->ap_hmpre != 0) {
858 			nvme_print_uint64(4, "Host Memory Buffer Preferred "
859 			    "Size", idctl->ap_hmpre * 4, NULL, "KiB");
860 		} else {
861 			nvme_print_str(4, "Host Memory Buffer Preferred "
862 			    "Size", -1, "unsupported", 0);
863 		}
864 
865 		if (idctl->ap_hmmin != 0) {
866 			nvme_print_uint64(4, "Host Memory Buffer Minimum Size",
867 			    idctl->ap_hmmin * 4, NULL, "KiB");
868 		} else {
869 			nvme_print_str(4, "Host Memory Buffer Minimum Size",
870 			    -1, "unsupported", 0);
871 		}
872 
873 		if (idctl->id_oacs.oa_nsmgmt != 0) {
874 			nvme_print_uint128(4, "Total NVM Capacity",
875 			    idctl->ap_tnvmcap, "B", 0, 0);
876 			nvme_print_uint128(4, "Unallocated NVM Capacity",
877 			    idctl->ap_unvmcap, "B", 0, 0);
878 		} else {
879 			nvme_print_str(4, "Total NVM Capacity", -1,
880 			    "unsupported", 0);
881 			nvme_print_str(4, "Unallocated NVM Capacity", -1,
882 			    "unsupported", 0);
883 		}
884 
885 		if (idctl->ap_rpmbs.rpmbs_units != 0) {
886 			nvme_print(4, "Replay Protected Memory Block", -1,
887 			    NULL);
888 			nvme_print_uint64(6, "Number of RPMB Units",
889 			    idctl->ap_rpmbs.rpmbs_units, NULL, NULL);
890 			switch (idctl->ap_rpmbs.rpmbs_auth) {
891 			case NVME_RPMBS_AUTH_HMAC_SHA256:
892 				nvme_print_str(6, "Authentication Method", -1,
893 				    "HMAC SHA-256", 0);
894 				break;
895 			default:
896 				nvme_print(6, "Authentication Method", -1,
897 				    "unknown reserved value: %u",
898 				    idctl->ap_rpmbs.rpmbs_auth);
899 				break;
900 			}
901 			nvme_print_uint64(6, "Total Size",
902 			    (idctl->ap_rpmbs.rpmbs_tot + 1) * 128, NULL, "KiB");
903 			nvme_print_uint64(6, "Access Size",
904 			    (idctl->ap_rpmbs.rpmbs_acc + 1) * 512, NULL, "KiB");
905 		} else {
906 			nvme_print_str(4, "Replay Protected Memory Block", -1,
907 			    "unsupported", 0);
908 		}
909 
910 		if (idctl->id_oacs.oa_selftest != 0) {
911 			nvme_print_uint64(4, "Extended Device Self-test Time",
912 			    idctl->ap_edstt, NULL, "min");
913 			nvme_print(4, "Device Self-test Options", -1, NULL);
914 			nvme_print_bit(6, "Self-test operation granularity",
915 			    nvme_version_check(version, 1, 3),
916 			    idctl->ap_dsto.dsto_sub, "subsystem", "controller");
917 		} else {
918 			nvme_print_str(4, "Extended Device Self-test Time", -1,
919 			    "unsupported", 0);
920 			nvme_print_str(4, "Device Self-test Options", -1,
921 			    "unsupported", 0);
922 		}
923 	}
924 
925 	switch (idctl->ap_fwug) {
926 	case 0x00:
927 		nvme_print_str(4, "Firmware Update Granularity", -1, "unknown",
928 		    0);
929 		break;
930 	case 0xff:
931 		nvme_print_str(4, "Firmware Update Granularity", -1,
932 		    "unrestricted", 0);
933 		break;
934 	default:
935 		nvme_print_uint64(4, "Firmware Update Granularity",
936 		    idctl->ap_fwug * 4, NULL, "KiB");
937 		break;
938 	}
939 
940 	if (verbose) {
941 		if (idctl->ap_kas != 0) {
942 			nvme_print_uint64(4, "Keep Alive Support",
943 			    idctl->ap_kas * 100, NULL, "ms");
944 		} else {
945 			nvme_print_str(4, "Keep Alive Support", -1,
946 			    "unsupported", 0);
947 		}
948 
949 		nvme_print(4, "Host Controlled Thermal Management Attributes",
950 		    -1, NULL);
951 		nvme_print_bit(6, "Host Controlled Thermal Management",
952 		    nvme_version_check(version, 1, 3),
953 		    idctl->ap_hctma.hctma_hctm, NULL, NULL);
954 		if (idctl->ap_mntmt != 0 && nvme_version_check(version, 1, 3)) {
955 			nvme_print_temp(6, "Minimum Thermal Management "
956 			    "Temperature", idctl->ap_mntmt);
957 		} else {
958 			nvme_print_str(6, "Minimum Thermal Management "
959 			    "Temperature", -1, "unsupported", -1);
960 		}
961 
962 		if (idctl->ap_mxtmt != 0 && nvme_version_check(version, 1, 3)) {
963 			nvme_print_temp(6, "Maximum Thermal Management "
964 			    "Temperature", idctl->ap_mxtmt);
965 		} else {
966 			nvme_print_str(6, "Maximum Thermal Management "
967 			    "Temperature", -1, "unsupported", -1);
968 		}
969 
970 		nvme_print(4, "Sanitize Capabilities", -1, NULL);
971 		nvme_print_bit(6, "Crypto Erase Support",
972 		    nvme_version_check(version, 1, 3),
973 		    idctl->ap_sanitize.san_ces, NULL, NULL);
974 		nvme_print_bit(6, "Block Erase Support",
975 		    nvme_version_check(version, 1, 3),
976 		    idctl->ap_sanitize.san_bes, NULL, NULL);
977 		nvme_print_bit(6, "Overwrite Support",
978 		    nvme_version_check(version, 1, 3),
979 		    idctl->ap_sanitize.san_ows, NULL, NULL);
980 		nvme_print_bit(6, "No-Deallocate Inhibited",
981 		    nvme_version_check(version, 1, 4),
982 		    idctl->ap_sanitize.san_ndi, NULL, NULL);
983 		if (nvme_version_check(version, 1, 4)) {
984 			uint_t val = idctl->ap_sanitize.san_nodmmas;
985 			switch (val) {
986 			case NVME_NODMMAS_UNDEF:
987 				nvme_print_str(6, "No-Deallocate Modifies "
988 				    "Media after Sanitize", -1,
989 				    "undefined", 0);
990 				break;
991 			case NVME_NODMMAS_NOMOD:
992 				nvme_print_str(6, "No-Deallocate Modifies "
993 				    "Media after Sanitize", -1,
994 				    "no modification", 0);
995 				break;
996 			case NVME_NODMMAS_DOMOD:
997 				nvme_print_str(6, "No-Deallocate Modifies "
998 				    "Media after Sanitize", -1,
999 				    "modification required", 0);
1000 				break;
1001 			default:
1002 				nvme_print(6, "No-Deallocate Modifies "
1003 				    "Media after Sanitize", -1,
1004 				    "unknown reserved value: %u", val);
1005 				break;
1006 			}
1007 		} else {
1008 			nvme_print_str(6, "No-Deallocate Modifies Media after "
1009 			    "Sanitize", -1, "undefined", 0);
1010 		}
1011 
1012 		if (idctl->ap_hmminds != 0) {
1013 			nvme_print_uint64(4, "Host Memory Buffer Minimum "
1014 			    "Descriptor Entry Size", idctl->ap_hmminds * 4,
1015 			    NULL, "KiB");
1016 		} else {
1017 			nvme_print_str(4, "Host Memory Buffer Minimum "
1018 			    "Descriptor Entry Size", -1, "unsupported", 0);
1019 		}
1020 
1021 		if (idctl->ap_hmmaxd != 0) {
1022 			nvme_print_uint64(4, "Host Memory Buffer Maximum "
1023 			    "Descriptor Entries", idctl->ap_hmmaxd,
1024 			    NULL, NULL);
1025 		} else {
1026 			nvme_print_str(4, "Host Memory Buffer Maximum "
1027 			    "Descriptor Entries", -1, "unsupported", 0);
1028 		}
1029 
1030 		if (idctl->id_ctratt.ctrat_engrp != 0) {
1031 			nvme_print_uint64(4, "Max Endurance Group Identifier",
1032 			    idctl->ap_engidmax, NULL, NULL);
1033 		} else {
1034 			nvme_print_str(4, "Max Endurance Group Identifier",
1035 			    -1, "unsupported", 0);
1036 		}
1037 
1038 		if (idctl->id_mic.m_anar_sup != 0) {
1039 			nvme_print_uint64(4, "ANA Transition Time",
1040 			    idctl->ap_anatt, NULL, "secs");
1041 		} else {
1042 			nvme_print_str(4, "ANA Transition Time", -1,
1043 			    "unsupported", 0);
1044 		}
1045 
1046 		nvme_print(4, "Asymmetric Namespace Access Capabilities",
1047 		    -1, NULL);
1048 		nvme_print_bit(6, "ANA Optimized state",
1049 		    nvme_version_check(version, 1, 4),
1050 		    idctl->ap_anacap.anacap_opt, NULL, NULL);
1051 		nvme_print_bit(6, "ANA Non-Optimized state",
1052 		    nvme_version_check(version, 1, 4),
1053 		    idctl->ap_anacap.anacap_unopt, NULL, NULL);
1054 		nvme_print_bit(6, "ANA Inaccessible state",
1055 		    nvme_version_check(version, 1, 4),
1056 		    idctl->ap_anacap.anacap_inacc, NULL, NULL);
1057 		nvme_print_bit(6, "ANA Persistent Loss state",
1058 		    nvme_version_check(version, 1, 4),
1059 		    idctl->ap_anacap.anacap_ploss, NULL, NULL);
1060 		nvme_print_bit(6, "ANA Persistent Change state",
1061 		    nvme_version_check(version, 1, 4),
1062 		    idctl->ap_anacap.anacap_chg, NULL, NULL);
1063 		nvme_print_bit(6, "ANAGRPID doesn't change with attached NS",
1064 		    nvme_version_check(version, 1, 4),
1065 		    idctl->ap_anacap.anacap_grpns, "yes", "no");
1066 		nvme_print_bit(6, "Non-zero ANAGRPID in Namespace Management",
1067 		    nvme_version_check(version, 1, 4),
1068 		    idctl->ap_anacap.anacap_grpid, NULL, NULL);
1069 
1070 		if (idctl->id_mic.m_anar_sup != 0) {
1071 			nvme_print_uint64(4, "Max ANA Group Identifier",
1072 			    idctl->ap_anagrpmax, NULL, NULL);
1073 			nvme_print_uint64(4, "Number of ANA Group Identifiers",
1074 			    idctl->ap_nanagrpid, NULL, NULL);
1075 		} else {
1076 			nvme_print_str(4, "Max ANA Group Identifier",
1077 			    -1, "unsupported", 0);
1078 			nvme_print_str(4, "Number of ANA Group Identifiers",
1079 			    -1, "unsupported", 0);
1080 		}
1081 
1082 		if (idctl->id_lpa.lp_persist != 0) {
1083 			nvme_print_uint64(4, "Persistent Event Log Size",
1084 			    idctl->ap_pels * 64, NULL, "KiB");
1085 		} else {
1086 			nvme_print_str(4, "Persistent Event Log Size",
1087 			    -1, "unsupported", 0);
1088 		}
1089 	}
1090 
1091 
1092 	nvme_print(2, "NVM Command Set Attributes", -1, NULL);
1093 	if (verbose) {
1094 		nvme_print(4, "Submission Queue Entry Size", -1,
1095 		    "min %d, max %d",
1096 		    1 << idctl->id_sqes.qes_min, 1 << idctl->id_sqes.qes_max);
1097 		nvme_print(4, "Completion Queue Entry Size", -1,
1098 		    "min %d, max %d",
1099 		    1 << idctl->id_cqes.qes_min, 1 << idctl->id_cqes.qes_max);
1100 
1101 		if (nvme_version_check(version, 1, 2)) {
1102 			nvme_print_uint64(4, "Maximum Outstanding Commands",
1103 			    idctl->id_maxcmd, NULL, NULL);
1104 		} else {
1105 			nvme_print_str(4, "Maximum Outstanding Commands",
1106 			    -1, "unknown", 0);
1107 		}
1108 	}
1109 	nvme_print_uint64(4, "Number of Namespaces",
1110 	    idctl->id_nn, NULL, NULL);
1111 	nvme_print(4, "Optional NVM Command Support", -1, NULL);
1112 	nvme_print_bit(6, "Compare",
1113 	    nvme_version_check(version, 1, 0),
1114 	    idctl->id_oncs.on_compare, NULL, NULL);
1115 	nvme_print_bit(6, "Write Uncorrectable",
1116 	    nvme_version_check(version, 1, 0),
1117 	    idctl->id_oncs.on_wr_unc, NULL, NULL);
1118 	nvme_print_bit(6, "Dataset Management",
1119 	    nvme_version_check(version, 1, 0),
1120 	    idctl->id_oncs.on_dset_mgmt, NULL, NULL);
1121 	nvme_print_bit(6, "Write Zeros",
1122 	    nvme_version_check(version, 1, 1),
1123 	    idctl->id_oncs.on_wr_zero, NULL, NULL);
1124 	nvme_print_bit(6, "Save/Select in Get/Set Features",
1125 	    nvme_version_check(version, 1, 1),
1126 	    idctl->id_oncs.on_save, NULL, NULL);
1127 	nvme_print_bit(6, "Reservations",
1128 	    nvme_version_check(version, 1, 1),
1129 	    idctl->id_oncs.on_reserve, NULL, NULL);
1130 	nvme_print_bit(6, "Timestamp Feature",
1131 	    nvme_version_check(version, 1, 3),
1132 	    idctl->id_oncs.on_ts, NULL, NULL);
1133 	nvme_print_bit(6, "Verify",
1134 	    nvme_version_check(version, 1, 4),
1135 	    idctl->id_oncs.on_verify, NULL, NULL);
1136 
1137 	nvme_print(4, "Fused Operation Support", -1, NULL);
1138 	nvme_print_bit(6, "Compare and Write",
1139 	    nvme_version_check(version, 1, 0),
1140 	    idctl->id_fuses.f_cmp_wr, NULL, NULL);
1141 	nvme_print(4, "Format NVM Attributes", -1, NULL);
1142 	nvme_print_bit(6, "Per Namespace Format",
1143 	    nvme_version_check(version, 1, 0),
1144 	    idctl->id_fna.fn_format == 0, NULL, NULL);
1145 	nvme_print_bit(6, "Per Namespace Secure Erase",
1146 	    nvme_version_check(version, 1, 0),
1147 	    idctl->id_fna.fn_sec_erase == 0, NULL, NULL);
1148 	nvme_print_bit(6, "Cryptographic Erase",
1149 	    nvme_version_check(version, 1, 0),
1150 	    idctl->id_fna.fn_crypt_erase, NULL, NULL);
1151 	nvme_print(4, "Volatile Write Cache", -1, NULL);
1152 	nvme_print_bit(6, "Present",
1153 	    nvme_version_check(version, 1, 0),
1154 	    idctl->id_vwc.vwc_present, "yes", "no");
1155 	if (verbose) {
1156 		switch (idctl->id_vwc.vwc_nsflush) {
1157 		case NVME_VWCNS_UNKNOWN:
1158 			nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
1159 			    -1, "unknown", 0);
1160 			break;
1161 		case NVME_VWCNS_UNSUP:
1162 			nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
1163 			    -1, "unsupported", 0);
1164 			break;
1165 		case NVME_VWCNS_SUP:
1166 			nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
1167 			    -1, "supported", 0);
1168 			break;
1169 		default:
1170 			nvme_print(6, "Flush with NSID 0xFFFFFFFF",
1171 			    -1, "unknown reserved value: %u",
1172 			    idctl->id_vwc.vwc_nsflush);
1173 			break;
1174 		}
1175 	}
1176 	nvme_print_uint64(4, "Atomic Write Unit Normal",
1177 	    (uint32_t)idctl->id_awun + 1, NULL,
1178 	    idctl->id_awun == 0 ? " block" : " blocks");
1179 	nvme_print_uint64(4, "Atomic Write Unit Power Fail",
1180 	    (uint32_t)idctl->id_awupf + 1, NULL,
1181 	    idctl->id_awupf == 0 ? " block" : " blocks");
1182 
1183 	if (verbose != 0) {
1184 		nvme_print_bit(4, "NVM Vendor-specific Command Format",
1185 		    nvme_version_check(version, 1, 0),
1186 		    idctl->id_nvscc.nv_spec, "standard", "vendor-specific");
1187 
1188 		nvme_print(4, "Namespace Write Protection Capabilities",
1189 		    -1, NULL);
1190 		nvme_print_bit(6, "Core Support",
1191 		    nvme_version_check(version, 1, 4),
1192 		    idctl->id_nwpc.nwpc_base, NULL, NULL);
1193 		nvme_print_bit(6, "Write Protect Until Power Cycle",
1194 		    nvme_version_check(version, 1, 4),
1195 		    idctl->id_nwpc.nwpc_wpupc, NULL, NULL);
1196 		nvme_print_bit(6, "Permanent Write Protect",
1197 		    nvme_version_check(version, 1, 4),
1198 		    idctl->id_nwpc.nwpc_permwp, NULL, NULL);
1199 	}
1200 
1201 	if (idctl->id_fuses.f_cmp_wr && nvme_version_check(version, 1, 1)) {
1202 		nvme_print_uint64(4, "Atomic Compare & Write Size",
1203 		    (uint32_t)idctl->id_acwu + 1, NULL,
1204 		    idctl->id_acwu == 0 ? " block" : " blocks");
1205 	} else {
1206 		nvme_print_str(4, "Atomic Compare & Write Size", -1,
1207 		    "unsupported", 0);
1208 	}
1209 
1210 	nvme_print(4, "SGL Support", -1, NULL);
1211 	switch (idctl->id_sgls.sgl_sup) {
1212 	case NVME_SGL_UNSUP:
1213 		nvme_print_str(6, "Command Set", -1, "unsupported", 0);
1214 		break;
1215 	case NVME_SGL_SUP_UNALIGN:
1216 		nvme_print_str(6, "Command Set", -1, "supported, "
1217 		    "no restrictions", 0);
1218 		break;
1219 	case NVME_SGL_SUP_ALIGN:
1220 		nvme_print_str(6, "Command Set", -1, "supported, "
1221 		    "alignment restrictions", 0);
1222 		break;
1223 	default:
1224 		nvme_print(6, "Command Set", -1, "unknown reserved value: %u",
1225 		    idctl->id_sgls.sgl_sup);
1226 		break;
1227 	}
1228 	nvme_print_bit(6, "Keyed SGL Block Descriptor",
1229 	    nvme_version_check(version, 1, 2),
1230 	    idctl->id_sgls.sgl_keyed, NULL, NULL);
1231 	nvme_print_bit(6, "SGL Bit Bucket Descriptor",
1232 	    nvme_version_check(version, 1, 1),
1233 	    idctl->id_sgls.sgl_bucket, NULL, NULL);
1234 	nvme_print_bit(6, "Byte Aligned Contiguous Metadata",
1235 	    nvme_version_check(version, 1, 2),
1236 	    idctl->id_sgls.sgl_balign, NULL, NULL);
1237 	nvme_print_bit(6, "SGL Longer than Data Transferred",
1238 	    nvme_version_check(version, 1, 2),
1239 	    idctl->id_sgls.sgl_sglgtd, NULL, NULL);
1240 	nvme_print_bit(6, "MPTR with SGL",
1241 	    nvme_version_check(version, 1, 2),
1242 	    idctl->id_sgls.sgl_mptr, NULL, NULL);
1243 	nvme_print_bit(6, "SGL Address as Offset",
1244 	    nvme_version_check(version, 1, 2),
1245 	    idctl->id_sgls.sgl_offset, NULL, NULL);
1246 	nvme_print_bit(6, "Transport SGL Data Block",
1247 	    nvme_version_check(version, 1, 4),
1248 	    idctl->id_sgls.sgl_tport, NULL, NULL);
1249 	if (verbose) {
1250 		if (idctl->id_mnam != 0) {
1251 			nvme_print_uint64(4, "Maximum Number of Allowed "
1252 			    "Namespaces", idctl->id_mnam, NULL, NULL);
1253 		} else {
1254 			nvme_print(4, "Maximum Number of Allowed "
1255 			    "Namespaces", -1, "at most %u", idctl->id_nn);
1256 		}
1257 	}
1258 
1259 	if (nvme_version_check(version, 1, 2) && idctl->id_subnqn[0] != '\0') {
1260 		nvme_print_str(4, "NVMe Subsystem Qualified Name", -1,
1261 		    (char *)idctl->id_subnqn, sizeof (idctl->id_subnqn));
1262 	} else {
1263 		nvme_print_str(4, "NVMe Subsystem Qualified Name", -1,
1264 		    "unknown", 0);
1265 	}
1266 
1267 	for (i = 0; i != idctl->id_npss + 1; i++) {
1268 		double scale = 0.01;
1269 		double power = 0;
1270 		int places = 2;
1271 		char *unit = "W";
1272 
1273 		if (nvme_version_check(version, 1, 1) &&
1274 		    idctl->id_psd[i].psd_mps == 1) {
1275 			scale = 0.0001;
1276 			places = 4;
1277 		}
1278 
1279 		power = (double)idctl->id_psd[i].psd_mp * scale;
1280 		if (power < 1.0) {
1281 			power *= 1000.0;
1282 			unit = "mW";
1283 		}
1284 
1285 		nvme_print(4, "Power State Descriptor", i, NULL);
1286 		nvme_print_double(6, "Maximum Power", power, places, unit);
1287 		nvme_print_bit(6, "Non-Operational State",
1288 		    nvme_version_check(version, 1, 1),
1289 		    idctl->id_psd[i].psd_nops, "yes", "no");
1290 		nvme_print_uint64(6, "Entry Latency",
1291 		    idctl->id_psd[i].psd_enlat, NULL, "us");
1292 		nvme_print_uint64(6, "Exit Latency",
1293 		    idctl->id_psd[i].psd_exlat, NULL, "us");
1294 		nvme_print_uint64(6, "Relative Read Throughput (0 = best)",
1295 		    idctl->id_psd[i].psd_rrt, NULL, NULL);
1296 		nvme_print_uint64(6, "Relative Read Latency (0 = best)",
1297 		    idctl->id_psd[i].psd_rrl, NULL, NULL);
1298 		nvme_print_uint64(6, "Relative Write Throughput (0 = best)",
1299 		    idctl->id_psd[i].psd_rwt, NULL, NULL);
1300 		nvme_print_uint64(6, "Relative Write Latency (0 = best)",
1301 		    idctl->id_psd[i].psd_rwl, NULL, NULL);
1302 	}
1303 }
1304 
1305 /*
1306  * nvme_print_identify_nsid
1307  *
1308  * This function pretty-prints the structure returned by the IDENTIFY NAMESPACE
1309  * command.
1310  */
1311 void
1312 nvme_print_identify_nsid(nvme_identify_nsid_t *idns, nvme_version_t *version)
1313 {
1314 	int bsize = 1 << idns->id_lbaf[idns->id_flbas.lba_format].lbaf_lbads;
1315 	int i;
1316 
1317 	nvme_print(0, "Identify Namespace", -1, NULL);
1318 	nvme_print(2, "Namespace Capabilities and Features", -1, NULL);
1319 	nvme_print_uint64(4, "Namespace Size",
1320 	    idns->id_nsize * bsize / 1024 / 1024, NULL, "MB");
1321 	nvme_print_uint64(4, "Namespace Capacity",
1322 	    idns->id_ncap * bsize / 1024 / 1024, NULL, "MB");
1323 	nvme_print_uint64(4, "Namespace Utilization",
1324 	    idns->id_nuse * bsize / 1024 / 1024, NULL, "MB");
1325 	nvme_print(4, "Namespace Features", -1, NULL);
1326 	nvme_print_bit(6, "Thin Provisioning",
1327 	    nvme_version_check(version, 1, 0),
1328 	    idns->id_nsfeat.f_thin, NULL, NULL);
1329 	nvme_print_bit(6, "Namespace-specific Atomic Units",
1330 	    nvme_version_check(version, 1, 2),
1331 	    idns->id_nsfeat.f_nsabp, NULL, NULL);
1332 	nvme_print_bit(6, "Deallocate errors",
1333 	    nvme_version_check(version, 1, 2),
1334 	    idns->id_nsfeat.f_dae, NULL, NULL);
1335 	nvme_print_bit(6, "Namespace GUID Reuse",
1336 	    nvme_version_check(version, 1, 2),
1337 	    idns->id_nsfeat.f_uidreuse, "impossible", "possible");
1338 	nvme_print_bit(6, "Namespace-specific I/O Optimized Sizes",
1339 	    nvme_version_check(version, 1, 4),
1340 	    idns->id_nsfeat.f_optperf, NULL, NULL);
1341 
1342 	nvme_print_uint64(4, "Number of LBA Formats",
1343 	    (uint16_t)idns->id_nlbaf + 1, NULL, NULL);
1344 	nvme_print(4, "Formatted LBA Size", -1, NULL);
1345 	nvme_print_uint64(6, "LBA Format",
1346 	    (uint16_t)idns->id_flbas.lba_format, NULL, NULL);
1347 	nvme_print_bit(6, "Extended Data LBA",
1348 	    nvme_version_check(version, 1, 0),
1349 	    idns->id_flbas.lba_extlba, "yes", "no");
1350 
1351 	nvme_print(4, "Metadata Capabilities", -1, NULL);
1352 	nvme_print_bit(6, "Extended Data LBA",
1353 	    nvme_version_check(version, 1, 0),
1354 	    idns->id_mc.mc_extlba, NULL, NULL);
1355 	nvme_print_bit(6, "Separate Metadata",
1356 	    nvme_version_check(version, 1, 0),
1357 	    idns->id_mc.mc_separate, NULL, NULL);
1358 
1359 	nvme_print(4, "End-to-End Data Protection Capabilities", -1, NULL);
1360 	nvme_print_bit(6, "Protection Information Type 1",
1361 	    nvme_version_check(version, 1, 0),
1362 	    idns->id_dpc.dp_type1, NULL, NULL);
1363 	nvme_print_bit(6, "Protection Information Type 2",
1364 	    nvme_version_check(version, 1, 0),
1365 	    idns->id_dpc.dp_type2, NULL, NULL);
1366 	nvme_print_bit(6, "Protection Information Type 3",
1367 	    nvme_version_check(version, 1, 0),
1368 	    idns->id_dpc.dp_type3, NULL, NULL);
1369 	nvme_print_bit(6, "Protection Information first",
1370 	    nvme_version_check(version, 1, 0),
1371 	    idns->id_dpc.dp_first, NULL, NULL);
1372 	nvme_print_bit(6, "Protection Information last",
1373 	    nvme_version_check(version, 1, 0),
1374 	    idns->id_dpc.dp_last, NULL, NULL);
1375 	nvme_print(4, "End-to-End Data Protection Settings", -1, NULL);
1376 	if (idns->id_dps.dp_pinfo == 0) {
1377 		nvme_print_str(6, "Protection Information", -1,
1378 		    "disabled", 0);
1379 	} else {
1380 		nvme_print_uint64(6, "Protection Information Type",
1381 		    idns->id_dps.dp_pinfo, NULL, NULL);
1382 	}
1383 	nvme_print_bit(6, "Protection Information in Metadata",
1384 	    nvme_version_check(version, 1, 0),
1385 	    idns->id_dps.dp_first, "first 8 bytes", "last 8 bytes");
1386 
1387 	nvme_print(4, "Namespace Multi-Path I/O and Namespace Sharing "
1388 	    "Capabilities", -1, NULL);
1389 
1390 	nvme_print_bit(6, "Namespace is shared",
1391 	    nvme_version_check(version, 1, 1),
1392 	    idns->id_nmic.nm_shared, "yes", "no");
1393 	nvme_print(2, "Reservation Capabilities", -1, NULL);
1394 	nvme_print_bit(6, "Persist Through Power Loss",
1395 	    nvme_version_check(version, 1, 1),
1396 	    idns->id_rescap.rc_persist, NULL, NULL);
1397 	nvme_print_bit(6, "Write Exclusive",
1398 	    nvme_version_check(version, 1, 1),
1399 	    idns->id_rescap.rc_wr_excl, NULL, NULL);
1400 	nvme_print_bit(6, "Exclusive Access",
1401 	    nvme_version_check(version, 1, 1),
1402 	    idns->id_rescap.rc_excl, NULL, NULL);
1403 	nvme_print_bit(6, "Write Exclusive - Registrants Only",
1404 	    nvme_version_check(version, 1, 1),
1405 	    idns->id_rescap.rc_wr_excl_r, NULL, NULL);
1406 	nvme_print_bit(6, "Exclusive Access - Registrants Only",
1407 	    nvme_version_check(version, 1, 1),
1408 	    idns->id_rescap.rc_excl_r, NULL, NULL);
1409 	nvme_print_bit(6, "Write Exclusive - All Registrants",
1410 	    nvme_version_check(version, 1, 1),
1411 	    idns->id_rescap.rc_wr_excl_a, NULL, NULL);
1412 	nvme_print_bit(6, "Exclusive Access - All Registrants",
1413 	    nvme_version_check(version, 1, 1),
1414 	    idns->id_rescap.rc_excl_a, NULL, NULL);
1415 	nvme_print_bit(6, "Ignore Existing Key Behavior",
1416 	    nvme_version_check(version, 1, 3),
1417 	    idns->id_rescap.rc_ign_ekey, "NVMe 1.3 behavior", "pre-NVMe 1.3");
1418 
1419 	if (idns->id_fpi.fpi_sup != 0) {
1420 		nvme_print_uint64(4, "NVM Format Remaining",
1421 		    idns->id_fpi.fpi_remp, NULL, "%");
1422 	} else {
1423 		nvme_print_str(4, "NVM Format Remaining", -1, "unsupported", 0);
1424 	}
1425 
1426 	if (verbose) {
1427 		if (idns->id_nawun != 0) {
1428 			nvme_print_uint64(4, "Namespace Atomic Write Unit "
1429 			    "Normal", idns->id_nawun + 1, NULL, " blocks");
1430 		} else {
1431 			nvme_print_str(4, "Namespace Atomic Write Unit "
1432 			    "Normal", -1, "unspecified", 0);
1433 		}
1434 
1435 		if (idns->id_nawupf != 0) {
1436 			nvme_print_uint64(4, "Namespace Atomic Write Unit "
1437 			    "Power Fail", idns->id_nawupf + 1, NULL, " blocks");
1438 		} else {
1439 			nvme_print_str(4, "Namespace Atomic Write Unit "
1440 			    "Power Fail", -1, "unspecified", 0);
1441 		}
1442 
1443 		if (idns->id_nacwu != 0) {
1444 			nvme_print_uint64(4, "Namespace Atomic Compare & Write "
1445 			    "Unit", idns->id_nacwu + 1, NULL, " blocks");
1446 		} else {
1447 			nvme_print_str(4, "Namespace Atomic Compare & Write "
1448 			    "Unit", -1, "unspecified", 0);
1449 		}
1450 
1451 		if (idns->id_nabsn != 0) {
1452 			nvme_print_uint64(4, "Namespace Atomic Boundary Size "
1453 			    "Normal", idns->id_nabsn + 1, NULL, " blocks");
1454 		} else {
1455 			nvme_print_str(4, "Namespace Atomic Boundary Size "
1456 			    "Normal", -1, "unspecified", 0);
1457 		}
1458 
1459 		if (idns->id_nbao != 0) {
1460 			nvme_print(4, "Namespace Atomic Boundary Offset", -1,
1461 			    "LBA %u", idns->id_nbao);
1462 		} else {
1463 			nvme_print_str(4, "Namespace Atomic Boundary Offset",
1464 			    -1, "unspecified", 0);
1465 		}
1466 
1467 		if (idns->id_nabspf != 0) {
1468 			nvme_print_uint64(4, "Namespace Atomic Boundary Size "
1469 			    "Power Fail", idns->id_nabspf + 1, NULL,
1470 			    idns->id_nabspf == 0 ? " block" : " blocks");
1471 		} else {
1472 			nvme_print_str(4, "Namespace Atomic Boundary Size "
1473 			    "Power Fail", -1, "unspecified", 0);
1474 		}
1475 
1476 		if (idns->id_noiob != 0) {
1477 			nvme_print_uint64(4, "Namespace Optional I/O Boundary",
1478 			    idns->id_noiob, NULL,
1479 			    idns->id_noiob == 1 ? " block" : " blocks");
1480 		} else {
1481 			nvme_print_str(4, "Namespace Optimal I/O Boundary",
1482 			    -1, "unspecified", 0);
1483 		}
1484 	}
1485 
1486 	if (idns->id_nvmcap.lo != 0 || idns->id_nvmcap.hi != 0) {
1487 		nvme_print_uint128(4, "NVM Capacity", idns->id_nvmcap,
1488 		    "B", 0, 0);
1489 	} else {
1490 		nvme_print_str(4, "NVM Capacity", -1, "unknown", 0);
1491 	}
1492 
1493 	if (verbose) {
1494 		if (idns->id_npwg != 0) {
1495 			nvme_print_uint64(4, "Namespace Preferred Write "
1496 			    "Granularity", idns->id_npwg + 1, NULL, " blocks");
1497 		} else {
1498 			nvme_print_str(4, "Namespace Preferred Write "
1499 			    "Granularity", -1, "unspecified", 0);
1500 		}
1501 
1502 		if (idns->id_npwa != 0) {
1503 			nvme_print_uint64(4, "Namespace Preferred Write "
1504 			    "Alignment", idns->id_npwa + 1, NULL, " blocks");
1505 		} else {
1506 			nvme_print_str(4, "Namespace Preferred Write "
1507 			    "Alignment", -1, "unspecified", 0);
1508 		}
1509 
1510 		if (idns->id_npdg != 0) {
1511 			nvme_print_uint64(4, "Namespace Preferred Deallocate "
1512 			    "Granularity", idns->id_npdg + 1, NULL, " blocks");
1513 		} else {
1514 			nvme_print_str(4, "Namespace Preferred Deallocate "
1515 			    "Granularity", -1, "unspecified", 0);
1516 		}
1517 
1518 		if (idns->id_npda != 0) {
1519 			nvme_print_uint64(4, "Namespace Preferred Deallocate "
1520 			    "Alignment", idns->id_npda + 1, NULL, " blocks");
1521 		} else {
1522 			nvme_print_str(4, "Namespace Preferred Deallocate "
1523 			    "Alignment", -1, "unspecified", 0);
1524 		}
1525 
1526 		if (idns->id_nows != 0) {
1527 			nvme_print_uint64(4, "Namespace Optimal Write Size",
1528 			    idns->id_nows + 1, NULL, " blocks");
1529 		} else {
1530 			nvme_print_str(4, "Namespace Optimal Write Size",
1531 			    -1, "unspecified", 0);
1532 		}
1533 
1534 		if (idns->id_anagrpid != 0) {
1535 			nvme_print_uint64(4, "Namespace ANA Group Identifier",
1536 			    idns->id_anagrpid, NULL, NULL);
1537 		} else {
1538 			nvme_print_str(4, "Namespace ANA Group Identifier",
1539 			    -1, "unsupported", 0);
1540 		}
1541 	}
1542 
1543 	nvme_print(4, "Namespace Attributes", -1, NULL);
1544 	nvme_print_bit(6, "Write Protected",
1545 	    nvme_version_check(version, 1, 4),
1546 	    idns->id_nsattr.nsa_wprot, "yes", "no");
1547 
1548 	if (verbose) {
1549 		if (idns->id_nvmsetid != 0) {
1550 			nvme_print_uint64(4, "Namespace Set Identifier",
1551 			    idns->id_nvmsetid, NULL, NULL);
1552 		} else {
1553 			nvme_print_str(4, "Namespace Set Identifier",
1554 			    -1, "unsupported", 0);
1555 		}
1556 
1557 		if (idns->id_endgid != 0) {
1558 			nvme_print_uint64(4, "Namespace Endurance Group "
1559 			    "Identifier", idns->id_endgid, NULL, NULL);
1560 		} else {
1561 			nvme_print_str(4, "Namespace Endurance Group "
1562 			    "Identifier", -1, "unsupported", 0);
1563 		}
1564 	}
1565 
1566 	if (nvme_version_check(version, 1, 2)) {
1567 		uint8_t guid[16] = { 0 };
1568 		if (memcmp(guid, idns->id_nguid, sizeof (guid) != 0)) {
1569 			nvme_print(4, "Namespace GUID", -1, "%02x%02x%02x"
1570 			    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
1571 			    "%02x%02x", idns->id_nguid[0], idns->id_nguid[1],
1572 			    idns->id_nguid[2], idns->id_nguid[3],
1573 			    idns->id_nguid[4], idns->id_nguid[5],
1574 			    idns->id_nguid[6], idns->id_nguid[7],
1575 			    idns->id_nguid[8], idns->id_nguid[9],
1576 			    idns->id_nguid[10], idns->id_nguid[11],
1577 			    idns->id_nguid[12], idns->id_nguid[13],
1578 			    idns->id_nguid[14], idns->id_nguid[15]);
1579 		} else {
1580 			nvme_print_str(4, "Namespace GUID",
1581 			    -1, "unsupported", 0);
1582 		}
1583 	} else {
1584 		nvme_print_str(4, "Namespace GUID", -1, "unsupported", 0);
1585 	}
1586 
1587 
1588 	if (nvme_version_check(version, 1, 1)) {
1589 		uint8_t oui[8] = { 0 };
1590 		if (memcmp(oui, idns->id_eui64, sizeof (oui)) != 0) {
1591 			nvme_print(4, "IEEE Extended Unique Identifier", -1,
1592 			    "%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X",
1593 			    idns->id_eui64[0], idns->id_eui64[1],
1594 			    idns->id_eui64[2], idns->id_eui64[3],
1595 			    idns->id_eui64[4], idns->id_eui64[5],
1596 			    idns->id_eui64[6], idns->id_eui64[7]);
1597 		} else {
1598 			nvme_print_str(4, "IEEE Extended Unique Identifier",
1599 			    -1, "unsupported", 0);
1600 		}
1601 	} else {
1602 		nvme_print_str(4, "IEEE Extended Unique Identifier", -1,
1603 		    "unsupported", 0);
1604 	}
1605 
1606 	for (i = 0; i <= idns->id_nlbaf; i++) {
1607 		if (verbose == 0 && idns->id_lbaf[i].lbaf_ms != 0)
1608 			continue;
1609 
1610 		nvme_print(4, "LBA Format", i, NULL);
1611 		nvme_print_uint64(6, "Metadata Size",
1612 		    idns->id_lbaf[i].lbaf_ms, NULL, " bytes");
1613 		nvme_print_uint64(6, "LBA Data Size",
1614 		    1 << idns->id_lbaf[i].lbaf_lbads, NULL, " bytes");
1615 		nvme_print_str(6, "Relative Performance", -1,
1616 		    lbaf_relative_performance[idns->id_lbaf[i].lbaf_rp], 0);
1617 	}
1618 }
1619 
1620 /*
1621  * nvme_print_error_log
1622  *
1623  * This function pretty-prints all non-zero error log entries, or all entries
1624  * if verbose is set.
1625  */
1626 void
1627 nvme_print_error_log(int nlog, nvme_error_log_entry_t *elog,
1628     nvme_version_t *version)
1629 {
1630 	int i;
1631 
1632 	nvme_print(0, "Error Log", -1, NULL);
1633 	for (i = 0; i != nlog; i++)
1634 		if (elog[i].el_count == 0)
1635 			break;
1636 	nvme_print_uint64(2, "Number of Error Log Entries", i, NULL, NULL);
1637 
1638 	for (i = 0; i != nlog; i++) {
1639 		int sc = elog[i].el_sf.sf_sc;
1640 		const char *sc_str = "";
1641 
1642 		if (elog[i].el_count == 0 && verbose == 0)
1643 			break;
1644 
1645 		switch (elog[i].el_sf.sf_sct) {
1646 		case 0: /* Generic Command Status */
1647 			if (sc < ARRAYSIZE(generic_status_codes))
1648 				sc_str = generic_status_codes[sc];
1649 			else if (sc >= 0x80 &&
1650 			    sc - 0x80 < ARRAYSIZE(generic_nvm_status_codes))
1651 				sc_str = generic_nvm_status_codes[sc - 0x80];
1652 			break;
1653 		case 1: /* Specific Command Status */
1654 			if (sc < ARRAYSIZE(specific_status_codes))
1655 				sc_str = specific_status_codes[sc];
1656 			else if (sc >= 0x80 &&
1657 			    sc - 0x80 < ARRAYSIZE(specific_nvm_status_codes))
1658 				sc_str = specific_nvm_status_codes[sc - 0x80];
1659 			break;
1660 		case 2: /* Media Errors */
1661 			if (sc >= 0x80 &&
1662 			    sc - 0x80 < ARRAYSIZE(media_nvm_status_codes))
1663 				sc_str = media_nvm_status_codes[sc - 0x80];
1664 			break;
1665 		case 7: /* Vendor Specific */
1666 			sc_str = "Unknown Vendor Specific";
1667 			break;
1668 		default:
1669 			sc_str = "Reserved";
1670 			break;
1671 		}
1672 
1673 		nvme_print(2, "Entry", i, NULL);
1674 		nvme_print_uint64(4, "Error Count",
1675 		    elog[i].el_count, NULL, NULL);
1676 		nvme_print_uint64(4, "Submission Queue ID",
1677 		    elog[i].el_sqid, NULL, NULL);
1678 		nvme_print_uint64(4, "Command ID",
1679 		    elog[i].el_cid, NULL, NULL);
1680 		nvme_print(4, "Status Field", -1, NULL);
1681 		nvme_print_uint64(6, "Phase Tag",
1682 		    elog[i].el_sf.sf_p, NULL, NULL);
1683 		nvme_print(6, "Status Code", -1, "0x%0.2x (%s)",
1684 		    sc, sc_str);
1685 		nvme_print(6, "Status Code Type", -1, "0x%x (%s)",
1686 		    elog[i].el_sf.sf_sct,
1687 		    status_code_types[elog[i].el_sf.sf_sct]);
1688 		nvme_print_bit(6, "More",
1689 		    nvme_version_check(version, 1, 0),
1690 		    elog[i].el_sf.sf_m, "yes", "no");
1691 		nvme_print_bit(6, "Do Not Retry",
1692 		    nvme_version_check(version, 1, 0),
1693 		    elog[i].el_sf.sf_m, "yes", "no");
1694 		nvme_print_uint64(4, "Parameter Error Location byte",
1695 		    elog[i].el_byte, "0x%0.2"PRIx64, NULL);
1696 		nvme_print_uint64(4, "Parameter Error Location bit",
1697 		    elog[i].el_bit, NULL, NULL);
1698 		nvme_print_uint64(4, "Logical Block Address",
1699 		    elog[i].el_lba, NULL, NULL);
1700 		nvme_print(4, "Namespace ID", -1, "%d",
1701 		    elog[i].el_nsid == 0xffffffff ?
1702 		    0 : elog[i].el_nsid);
1703 		nvme_print_uint64(4,
1704 		    "Vendor Specific Information Available",
1705 		    elog[i].el_vendor, NULL, NULL);
1706 	}
1707 }
1708 
1709 /*
1710  * nvme_print_health_log
1711  *
1712  * This function pretty-prints a summary of the SMART/Health log, or all
1713  * of the log if verbose is set.
1714  */
1715 void
1716 nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl,
1717     nvme_version_t *version)
1718 {
1719 	nvme_print(0, "SMART/Health Information", -1, NULL);
1720 	nvme_print(2, "Critical Warnings", -1, NULL);
1721 	nvme_print_bit(4, "Available Space",
1722 	    nvme_version_check(version, 1, 0),
1723 	    hlog->hl_crit_warn.cw_avail, "low", "OK");
1724 	nvme_print_bit(4, "Temperature",
1725 	    nvme_version_check(version, 1, 0),
1726 	    hlog->hl_crit_warn.cw_temp, "too high", "OK");
1727 	nvme_print_bit(4, "Device Reliability",
1728 	    nvme_version_check(version, 1, 0),
1729 	    hlog->hl_crit_warn.cw_reliab, "degraded", "OK");
1730 	nvme_print_bit(4, "Media",
1731 	    nvme_version_check(version, 1, 0),
1732 	    hlog->hl_crit_warn.cw_readonly, "read-only", "OK");
1733 	if (idctl->id_vwc.vwc_present != 0)
1734 		nvme_print_bit(4, "Volatile Memory Backup",
1735 		    nvme_version_check(version, 1, 0),
1736 		    hlog->hl_crit_warn.cw_volatile, "failed", "OK");
1737 
1738 	nvme_print_temp(2, "Temperature", hlog->hl_temp);
1739 	nvme_print_uint64(2, "Available Spare Capacity",
1740 	    hlog->hl_avail_spare, NULL, "%");
1741 
1742 	if (verbose != 0)
1743 		nvme_print_uint64(2, "Available Spare Threshold",
1744 		    hlog->hl_avail_spare_thr, NULL, "%");
1745 
1746 	nvme_print_uint64(2, "Device Life Used",
1747 	    hlog->hl_used, NULL, "%");
1748 
1749 	if (verbose == 0)
1750 		return;
1751 
1752 	/*
1753 	 * The following two fields are in 1000 512 byte units. Convert that to
1754 	 * GB by doing binary shifts (9 left and 30 right) and multiply by 10^3.
1755 	 */
1756 	nvme_print_uint128(2, "Data Read",
1757 	    hlog->hl_data_read, "GB", 30 - 9, 3);
1758 	nvme_print_uint128(2, "Data Written",
1759 	    hlog->hl_data_write, "GB", 30 - 9, 3);
1760 
1761 	nvme_print_uint128(2, "Read Commands",
1762 	    hlog->hl_host_read, NULL, 0, 0);
1763 	nvme_print_uint128(2, "Write Commands",
1764 	    hlog->hl_host_write, NULL, 0, 0);
1765 	nvme_print_uint128(2, "Controller Busy",
1766 	    hlog->hl_ctrl_busy, "min", 0, 0);
1767 	nvme_print_uint128(2, "Power Cycles",
1768 	    hlog->hl_power_cycles, NULL, 0, 0);
1769 	nvme_print_uint128(2, "Power On",
1770 	    hlog->hl_power_on_hours, "h", 0, 0);
1771 	nvme_print_uint128(2, "Unsafe Shutdowns",
1772 	    hlog->hl_unsafe_shutdn, NULL, 0, 0);
1773 	nvme_print_uint128(2, "Uncorrectable Media Errors",
1774 	    hlog->hl_media_errors, NULL, 0, 0);
1775 	nvme_print_uint128(2, "Errors Logged",
1776 	    hlog->hl_errors_logged, NULL, 0, 0);
1777 
1778 	if (!nvme_version_check(version, 1, 2)) {
1779 		return;
1780 	}
1781 
1782 	if (idctl->ap_wctemp != 0) {
1783 		nvme_print_uint64(2, "Warning Composite Temperature Time",
1784 		    hlog->hl_warn_temp_time, NULL, "min");
1785 	}
1786 
1787 	if (idctl->ap_cctemp != 0) {
1788 		nvme_print_uint64(2, "Critical Composite Temperature Time",
1789 		    hlog->hl_crit_temp_time, NULL, "min");
1790 	}
1791 
1792 	if (hlog->hl_temp_sensor_1 != 0) {
1793 		nvme_print_temp(2, "Temperature Sensor 1",
1794 		    hlog->hl_temp_sensor_1);
1795 	}
1796 
1797 	if (hlog->hl_temp_sensor_2 != 0) {
1798 		nvme_print_temp(2, "Temperature Sensor 2",
1799 		    hlog->hl_temp_sensor_2);
1800 	}
1801 
1802 	if (hlog->hl_temp_sensor_3 != 0) {
1803 		nvme_print_temp(2, "Temperature Sensor 3",
1804 		    hlog->hl_temp_sensor_3);
1805 	}
1806 
1807 	if (hlog->hl_temp_sensor_4 != 0) {
1808 		nvme_print_temp(2, "Temperature Sensor 4",
1809 		    hlog->hl_temp_sensor_4);
1810 	}
1811 
1812 	if (hlog->hl_temp_sensor_5 != 0) {
1813 		nvme_print_temp(2, "Temperature Sensor 5",
1814 		    hlog->hl_temp_sensor_5);
1815 	}
1816 
1817 	if (hlog->hl_temp_sensor_6 != 0) {
1818 		nvme_print_temp(2, "Temperature Sensor 6",
1819 		    hlog->hl_temp_sensor_6);
1820 	}
1821 
1822 	if (hlog->hl_temp_sensor_7 != 0) {
1823 		nvme_print_temp(2, "Temperature Sensor 7",
1824 		    hlog->hl_temp_sensor_7);
1825 	}
1826 
1827 	if (hlog->hl_temp_sensor_8 != 0) {
1828 		nvme_print_temp(2, "Temperature Sensor 8",
1829 		    hlog->hl_temp_sensor_8);
1830 	}
1831 
1832 	if (!nvme_version_check(version, 1, 3)) {
1833 		return;
1834 	}
1835 
1836 	nvme_print_uint64(2, "Thermal Management Temp 1 Transition Count",
1837 	    hlog->hl_tmtemp_1_tc, NULL, NULL);
1838 
1839 	nvme_print_uint64(2, "Thermal Management Temp 2 Transition Count",
1840 	    hlog->hl_tmtemp_2_tc, NULL, NULL);
1841 
1842 	nvme_print_uint64(2, "Time for Thermal Management Temp 1",
1843 	    hlog->hl_tmtemp_1_time, NULL, "sec");
1844 
1845 	nvme_print_uint64(2, "Time for Thermal Management Temp 2",
1846 	    hlog->hl_tmtemp_2_time, NULL, "sec");
1847 }
1848 
1849 /*
1850  * nvme_print_fwslot_log
1851  *
1852  * This function pretty-prints the firmware slot information.
1853  */
1854 void
1855 nvme_print_fwslot_log(nvme_fwslot_log_t *fwlog)
1856 {
1857 	int i;
1858 
1859 	nvme_print(0, "Firmware Slot Information", -1, NULL);
1860 	nvme_print_uint64(2, "Active Firmware Slot", fwlog->fw_afi, NULL, NULL);
1861 	if (fwlog->fw_next != 0)
1862 		nvme_print_uint64(2, "Next Firmware Slot", fwlog->fw_next,
1863 		    NULL, NULL);
1864 
1865 	for (i = 0; i != ARRAYSIZE(fwlog->fw_frs); i++) {
1866 		nvme_print_str(2, "Firmware Revision for Slot", i + 1,
1867 		    fwlog->fw_frs[i][0] == '\0' ? "<Unused>" :
1868 		    fwlog->fw_frs[i], sizeof (fwlog->fw_frs[i]));
1869 	}
1870 }
1871 
1872 /*
1873  * nvme_print_feat_*
1874  *
1875  * These functions pretty-print the data structures returned by GET FEATURES.
1876  */
1877 void
1878 nvme_print_feat_arbitration(uint64_t res, void *b, size_t s,
1879     nvme_identify_ctrl_t *id, nvme_version_t *version)
1880 {
1881 	_NOTE(ARGUNUSED(b));
1882 	_NOTE(ARGUNUSED(s));
1883 	_NOTE(ARGUNUSED(id));
1884 	nvme_arbitration_t arb;
1885 
1886 	arb.r = (uint32_t)res;
1887 	if (arb.b.arb_ab != 7)
1888 		nvme_print_uint64(4, "Arbitration Burst",
1889 		    1 << arb.b.arb_ab, NULL, NULL);
1890 	else
1891 		nvme_print_str(4, "Arbitration Burst", 0,
1892 		    "no limit", 0);
1893 	nvme_print_uint64(4, "Low Priority Weight",
1894 	    (uint16_t)arb.b.arb_lpw + 1, NULL, NULL);
1895 	nvme_print_uint64(4, "Medium Priority Weight",
1896 	    (uint16_t)arb.b.arb_mpw + 1, NULL, NULL);
1897 	nvme_print_uint64(4, "High Priority Weight",
1898 	    (uint16_t)arb.b.arb_hpw + 1, NULL, NULL);
1899 }
1900 
1901 void
1902 nvme_print_feat_power_mgmt(uint64_t res, void *b, size_t s,
1903     nvme_identify_ctrl_t *id, nvme_version_t *version)
1904 {
1905 	_NOTE(ARGUNUSED(b));
1906 	_NOTE(ARGUNUSED(s));
1907 	_NOTE(ARGUNUSED(id));
1908 	nvme_power_mgmt_t pm;
1909 
1910 	pm.r = (uint32_t)res;
1911 	nvme_print_uint64(4, "Power State", (uint8_t)pm.b.pm_ps,
1912 	    NULL, NULL);
1913 }
1914 
1915 void
1916 nvme_print_feat_lba_range(uint64_t res, void *buf, size_t bufsize,
1917     nvme_identify_ctrl_t *id, nvme_version_t *version)
1918 {
1919 	_NOTE(ARGUNUSED(id));
1920 
1921 	nvme_lba_range_type_t lrt;
1922 	nvme_lba_range_t *lr;
1923 	size_t n_lr;
1924 	int i;
1925 
1926 	if (buf == NULL)
1927 		return;
1928 
1929 	lrt.r = res;
1930 	lr = buf;
1931 
1932 	n_lr = bufsize / sizeof (nvme_lba_range_t);
1933 	if (n_lr > lrt.b.lr_num + 1)
1934 		n_lr = lrt.b.lr_num + 1;
1935 
1936 	nvme_print_uint64(4, "Number of LBA Ranges",
1937 	    (uint8_t)lrt.b.lr_num + 1, NULL, NULL);
1938 
1939 	for (i = 0; i != n_lr; i++) {
1940 		if (verbose == 0 && lr[i].lr_nlb == 0)
1941 			continue;
1942 
1943 		nvme_print(4, "LBA Range", i, NULL);
1944 		if (lr[i].lr_type < ARRAYSIZE(lba_range_types))
1945 			nvme_print_str(6, "Type", -1,
1946 			    lba_range_types[lr[i].lr_type], 0);
1947 		else
1948 			nvme_print_uint64(6, "Type",
1949 			    lr[i].lr_type, NULL, NULL);
1950 		nvme_print(6, "Attributes", -1, NULL);
1951 		nvme_print_bit(8, "Writable",
1952 		    nvme_version_check(version, 1, 0),
1953 		    lr[i].lr_attr.lr_write, "yes", "no");
1954 		nvme_print_bit(8, "Hidden",
1955 		    nvme_version_check(version, 1, 0),
1956 		    lr[i].lr_attr.lr_hidden, "yes", "no");
1957 		nvme_print_uint64(6, "Starting LBA",
1958 		    lr[i].lr_slba, NULL, NULL);
1959 		nvme_print_uint64(6, "Number of Logical Blocks",
1960 		    lr[i].lr_nlb, NULL, NULL);
1961 		nvme_print(6, "Unique Identifier", -1,
1962 		    "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x"
1963 		    "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
1964 		    lr[i].lr_guid[0], lr[i].lr_guid[1],
1965 		    lr[i].lr_guid[2], lr[i].lr_guid[3],
1966 		    lr[i].lr_guid[4], lr[i].lr_guid[5],
1967 		    lr[i].lr_guid[6], lr[i].lr_guid[7],
1968 		    lr[i].lr_guid[8], lr[i].lr_guid[9],
1969 		    lr[i].lr_guid[10], lr[i].lr_guid[11],
1970 		    lr[i].lr_guid[12], lr[i].lr_guid[13],
1971 		    lr[i].lr_guid[14], lr[i].lr_guid[15]);
1972 	}
1973 }
1974 
1975 void
1976 nvme_print_feat_temperature(uint64_t res, void *b, size_t s,
1977     nvme_identify_ctrl_t *id, nvme_version_t *version)
1978 {
1979 	_NOTE(ARGUNUSED(s));
1980 	_NOTE(ARGUNUSED(id));
1981 	nvme_temp_threshold_t tt;
1982 	char *label = b;
1983 
1984 	tt.r = (uint32_t)res;
1985 	nvme_print_temp(4, label, tt.b.tt_tmpth);
1986 }
1987 
1988 void
1989 nvme_print_feat_error(uint64_t res, void *b, size_t s,
1990     nvme_identify_ctrl_t *id, nvme_version_t *version)
1991 {
1992 	_NOTE(ARGUNUSED(b));
1993 	_NOTE(ARGUNUSED(s));
1994 	_NOTE(ARGUNUSED(id));
1995 	nvme_error_recovery_t er;
1996 
1997 	er.r = (uint32_t)res;
1998 	if (er.b.er_tler > 0)
1999 		nvme_print_uint64(4, "Time Limited Error Recovery",
2000 		    (uint32_t)er.b.er_tler * 100, NULL, "ms");
2001 	else
2002 		nvme_print_str(4, "Time Limited Error Recovery", -1,
2003 		    "no time limit", 0);
2004 }
2005 
2006 void
2007 nvme_print_feat_write_cache(uint64_t res, void *b, size_t s,
2008     nvme_identify_ctrl_t *id, nvme_version_t *version)
2009 {
2010 	_NOTE(ARGUNUSED(b));
2011 	_NOTE(ARGUNUSED(s));
2012 	_NOTE(ARGUNUSED(id));
2013 	nvme_write_cache_t wc;
2014 
2015 	wc.r = (uint32_t)res;
2016 	nvme_print_bit(4, "Volatile Write Cache",
2017 	    nvme_version_check(version, 1, 0),
2018 	    wc.b.wc_wce, "enabled", "disabled");
2019 }
2020 
2021 void
2022 nvme_print_feat_nqueues(uint64_t res, void *b, size_t s,
2023     nvme_identify_ctrl_t *id, nvme_version_t *version)
2024 {
2025 	_NOTE(ARGUNUSED(b));
2026 	_NOTE(ARGUNUSED(s));
2027 	_NOTE(ARGUNUSED(id));
2028 	nvme_nqueues_t nq;
2029 
2030 	nq.r = (uint32_t)res;
2031 	nvme_print_uint64(4, "Number of Submission Queues",
2032 	    nq.b.nq_nsq + 1, NULL, NULL);
2033 	nvme_print_uint64(4, "Number of Completion Queues",
2034 	    nq.b.nq_ncq + 1, NULL, NULL);
2035 }
2036 
2037 void
2038 nvme_print_feat_intr_coal(uint64_t res, void *b, size_t s,
2039     nvme_identify_ctrl_t *id, nvme_version_t *version)
2040 {
2041 	_NOTE(ARGUNUSED(b));
2042 	_NOTE(ARGUNUSED(s));
2043 	_NOTE(ARGUNUSED(id));
2044 	nvme_intr_coal_t ic;
2045 
2046 	ic.r = (uint32_t)res;
2047 	nvme_print_uint64(4, "Aggregation Threshold",
2048 	    ic.b.ic_thr + 1, NULL, NULL);
2049 	nvme_print_uint64(4, "Aggregation Time",
2050 	    (uint16_t)ic.b.ic_time * 100, NULL, "us");
2051 }
2052 void
2053 nvme_print_feat_intr_vect(uint64_t res, void *b, size_t s,
2054     nvme_identify_ctrl_t *id, nvme_version_t *version)
2055 {
2056 	_NOTE(ARGUNUSED(b));
2057 	_NOTE(ARGUNUSED(s));
2058 	_NOTE(ARGUNUSED(id));
2059 	nvme_intr_vect_t iv;
2060 	char *tmp;
2061 
2062 	iv.r = (uint32_t)res;
2063 	if (asprintf(&tmp, "Vector %d Coalescing Disable", iv.b.iv_iv) < 0)
2064 		err(-1, "nvme_print_feat_common()");
2065 
2066 	nvme_print_bit(4, tmp, iv.b.iv_cd,
2067 	    nvme_version_check(version, 1, 0),
2068 	    "yes", "no");
2069 }
2070 
2071 void
2072 nvme_print_feat_write_atom(uint64_t res, void *b, size_t s,
2073     nvme_identify_ctrl_t *id, nvme_version_t *version)
2074 {
2075 	_NOTE(ARGUNUSED(b));
2076 	_NOTE(ARGUNUSED(s));
2077 	_NOTE(ARGUNUSED(id));
2078 	nvme_write_atomicity_t wa;
2079 
2080 	wa.r = (uint32_t)res;
2081 	nvme_print_bit(4, "Disable Normal", wa.b.wa_dn,
2082 	    nvme_version_check(version, 1, 0),
2083 	    "yes", "no");
2084 }
2085 
2086 void
2087 nvme_print_feat_async_event(uint64_t res, void *b, size_t s,
2088     nvme_identify_ctrl_t *idctl, nvme_version_t *version)
2089 {
2090 	_NOTE(ARGUNUSED(b));
2091 	_NOTE(ARGUNUSED(s));
2092 	nvme_async_event_conf_t aec;
2093 
2094 	aec.r = (uint32_t)res;
2095 	nvme_print_bit(4, "Available Space below threshold",
2096 	    nvme_version_check(version, 1, 0),
2097 	    aec.b.aec_avail, "enabled", "disabled");
2098 	nvme_print_bit(4, "Temperature above threshold",
2099 	    nvme_version_check(version, 1, 0),
2100 	    aec.b.aec_temp, "enabled", "disabled");
2101 	nvme_print_bit(4, "Device Reliability compromised",
2102 	    nvme_version_check(version, 1, 0),
2103 	    aec.b.aec_reliab, "enabled", "disabled");
2104 	nvme_print_bit(4, "Media read-only",
2105 	    nvme_version_check(version, 1, 0),
2106 	    aec.b.aec_readonly, "enabled", "disabled");
2107 	if (idctl->id_vwc.vwc_present != 0) {
2108 		nvme_print_bit(4, "Volatile Memory Backup failed",
2109 		    nvme_version_check(version, 1, 0),
2110 		    aec.b.aec_volatile, "enabled", "disabled");
2111 	}
2112 }
2113 
2114 void
2115 nvme_print_feat_auto_pst(uint64_t res, void *buf, size_t bufsize,
2116     nvme_identify_ctrl_t *id, nvme_version_t *version)
2117 {
2118 	_NOTE(ARGUNUSED(id));
2119 
2120 	nvme_auto_power_state_trans_t apst;
2121 	nvme_auto_power_state_t *aps;
2122 	int i;
2123 	int cnt = bufsize / sizeof (nvme_auto_power_state_t);
2124 
2125 	if (buf == NULL)
2126 		return;
2127 
2128 	apst.r = res;
2129 	aps = buf;
2130 
2131 	nvme_print_bit(4, "Autonomous Power State Transition",
2132 	    nvme_version_check(version, 1, 0),
2133 	    apst.b.apst_apste, "enabled", "disabled");
2134 	for (i = 0; i != cnt; i++) {
2135 		if (aps[i].apst_itps == 0 && aps[i].apst_itpt == 0)
2136 			break;
2137 
2138 		nvme_print(4, "Power State", i, NULL);
2139 		nvme_print_uint64(6, "Idle Transition Power State",
2140 		    (uint16_t)aps[i].apst_itps, NULL, NULL);
2141 		nvme_print_uint64(6, "Idle Time Prior to Transition",
2142 		    aps[i].apst_itpt, NULL, "ms");
2143 	}
2144 }
2145 
2146 void
2147 nvme_print_feat_progress(uint64_t res, void *b, size_t s,
2148     nvme_identify_ctrl_t *id, nvme_version_t *version)
2149 {
2150 	_NOTE(ARGUNUSED(b));
2151 	_NOTE(ARGUNUSED(s));
2152 	_NOTE(ARGUNUSED(id));
2153 	nvme_software_progress_marker_t spm;
2154 
2155 	spm.r = (uint32_t)res;
2156 	nvme_print_uint64(4, "Pre-Boot Software Load Count",
2157 	    spm.b.spm_pbslc, NULL, NULL);
2158 }
2159 
2160 static const char *
2161 nvme_str_generic_error(int sc)
2162 {
2163 	switch (sc) {
2164 	case NVME_CQE_SC_GEN_SUCCESS:
2165 		return ("Success");
2166 	default:
2167 		return ("See message log (usually /var/adm/messages) "
2168 		    "for details");
2169 	}
2170 }
2171 
2172 static const char *
2173 nvme_str_specific_error(int sc)
2174 {
2175 	switch (sc) {
2176 	case NVME_CQE_SC_SPC_INV_FW_SLOT:
2177 		return ("Invalid firmware slot");
2178 	case NVME_CQE_SC_SPC_INV_FW_IMG:
2179 		return ("Invalid firmware image");
2180 	case NVME_CQE_SC_SPC_FW_RESET:
2181 		return ("Conventional reset required - use "
2182 		    "'reboot -p' or similar");
2183 	case NVME_CQE_SC_SPC_FW_NSSR:
2184 		return ("NVM subsystem reset required - power cycle "
2185 		    "your system");
2186 	case NVME_CQE_SC_SPC_FW_NEXT_RESET:
2187 		return ("Image will be activated at next reset");
2188 	case NVME_CQE_SC_SPC_FW_MTFA:
2189 		return ("Activation requires maximum time violation");
2190 	case NVME_CQE_SC_SPC_FW_PROHIBITED:
2191 		return ("Activation prohibited");
2192 	default:
2193 		return ("See message log (usually /var/adm/messages) "
2194 		    "for details");
2195 	}
2196 }
2197 
2198 const char *
2199 nvme_str_error(int sct, int sc)
2200 {
2201 	switch (sct) {
2202 	case NVME_CQE_SCT_GENERIC:
2203 		return (nvme_str_generic_error(sc));
2204 
2205 	case NVME_CQE_SCT_SPECIFIC:
2206 		return (nvme_str_specific_error(sc));
2207 
2208 	default:
2209 		return ("See message log (usually /var/adm/messages) "
2210 		    "for details");
2211 	}
2212 }
2213