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