13d9b1a2aSHans Rosenfeld /*
23d9b1a2aSHans Rosenfeld * This file and its contents are supplied under the terms of the
33d9b1a2aSHans Rosenfeld * Common Development and Distribution License ("CDDL"), version 1.0.
43d9b1a2aSHans Rosenfeld * You may only use this file in accordance with the terms of version
53d9b1a2aSHans Rosenfeld * 1.0 of the CDDL.
63d9b1a2aSHans Rosenfeld *
73d9b1a2aSHans Rosenfeld * A full copy of the text of the CDDL should have accompanied this
83d9b1a2aSHans Rosenfeld * source. A copy of the CDDL is also available via the Internet at
93d9b1a2aSHans Rosenfeld * http://www.illumos.org/license/CDDL.
103d9b1a2aSHans Rosenfeld */
113d9b1a2aSHans Rosenfeld
123d9b1a2aSHans Rosenfeld /*
13*533affcbSRobert Mustacchi * Copyright 2024 Oxide Computer Company
1404be5853SAndy Fiddaman * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
158466ab88SHans Rosenfeld * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
163d9b1a2aSHans Rosenfeld */
173d9b1a2aSHans Rosenfeld
183d9b1a2aSHans Rosenfeld /*
193d9b1a2aSHans Rosenfeld * functions for printing of NVMe data structures and their members
203d9b1a2aSHans Rosenfeld */
213d9b1a2aSHans Rosenfeld
22153f3212SHans Rosenfeld #include <sys/sysmacros.h>
233d9b1a2aSHans Rosenfeld #include <sys/byteorder.h>
243d9b1a2aSHans Rosenfeld #include <sys/types.h>
253d9b1a2aSHans Rosenfeld #include <inttypes.h>
263d9b1a2aSHans Rosenfeld #include <stdio.h>
273d9b1a2aSHans Rosenfeld #include <stdlib.h>
283d9b1a2aSHans Rosenfeld #include <strings.h>
293d9b1a2aSHans Rosenfeld #include <stdarg.h>
303d9b1a2aSHans Rosenfeld #include <err.h>
313d9b1a2aSHans Rosenfeld #include <assert.h>
32a713ecffSHans Rosenfeld #include <libcmdutils.h>
33*533affcbSRobert Mustacchi #include <ctype.h>
343d9b1a2aSHans Rosenfeld
353d9b1a2aSHans Rosenfeld #include "nvmeadm.h"
363d9b1a2aSHans Rosenfeld
374a663bacSRobert Mustacchi static void nvme_print_str(int, const char *, int, const char *, int);
384a663bacSRobert Mustacchi static void nvme_print_double(int, const char *, double, int, const char *);
394a663bacSRobert Mustacchi static void nvme_print_int64(int, const char *, uint64_t, const char *,
404a663bacSRobert Mustacchi const char *);
414a663bacSRobert Mustacchi static void nvme_print_uint64(int, const char *, uint64_t, const char *,
424a663bacSRobert Mustacchi const char *);
434a663bacSRobert Mustacchi static void nvme_print_uint128(int, const char *, nvme_uint128_t, const char *,
444a663bacSRobert Mustacchi int, int);
458d5300d3SRobert Mustacchi static void nvme_print_bit(int, const char *, boolean_t, uint_t, const char *,
468d5300d3SRobert Mustacchi const char *);
47153f3212SHans Rosenfeld static void nvme_print_hexbuf(int, const char *, const uint8_t *, size_t);
48153f3212SHans Rosenfeld static void nvme_print_eui64(int, const char *, const uint8_t *);
49153f3212SHans Rosenfeld static void nvme_print_guid(int, const char *, const uint8_t *);
50153f3212SHans Rosenfeld static void nvme_print_uuid(int, const char *, const uint8_t *);
513d9b1a2aSHans Rosenfeld
523d9b1a2aSHans Rosenfeld static const char *generic_status_codes[] = {
533d9b1a2aSHans Rosenfeld "Successful Completion",
543d9b1a2aSHans Rosenfeld "Invalid Command Opcode",
553d9b1a2aSHans Rosenfeld "Invalid Field in Command",
563d9b1a2aSHans Rosenfeld "Command ID Conflict",
573d9b1a2aSHans Rosenfeld "Data Transfer Error",
583d9b1a2aSHans Rosenfeld "Commands Aborted due to Power Loss Notification",
593d9b1a2aSHans Rosenfeld "Internal Error",
603d9b1a2aSHans Rosenfeld "Command Abort Requested",
613d9b1a2aSHans Rosenfeld "Command Aborted due to SQ Deletion",
623d9b1a2aSHans Rosenfeld "Command Aborted due to Failed Fused Command",
633d9b1a2aSHans Rosenfeld "Command Aborted due to Missing Fused Command",
643d9b1a2aSHans Rosenfeld "Invalid Namespace or Format",
653d9b1a2aSHans Rosenfeld "Command Sequence Error",
66d1efd556SRobert Mustacchi /* NVMe 1.1 -- 0xd */
673d9b1a2aSHans Rosenfeld "Invalid SGL Segment Descriptor",
683d9b1a2aSHans Rosenfeld "Invalid Number of SGL Descriptors",
693d9b1a2aSHans Rosenfeld "Data SGL Length Invalid",
703d9b1a2aSHans Rosenfeld "Metadata SGL Length Invalid",
713d9b1a2aSHans Rosenfeld "SGL Descriptor Type Invalid",
72d1efd556SRobert Mustacchi /* NVMe 1.2 -- 0x12 */
733d9b1a2aSHans Rosenfeld "Invalid Use of Controller Memory Buffer",
743d9b1a2aSHans Rosenfeld "PRP Offset Invalid",
75d1efd556SRobert Mustacchi "Atomic Write Unit Exceeded",
76d1efd556SRobert Mustacchi /* NVMe 1.3 -- 0x15 */
77d1efd556SRobert Mustacchi "Operation Denied",
78d1efd556SRobert Mustacchi "SGL Offset Invalid",
79d1efd556SRobert Mustacchi "Reserved",
80d1efd556SRobert Mustacchi "Host Identifier Inconsistent Format",
81d1efd556SRobert Mustacchi "Keep Alive Timeout Expired",
82d1efd556SRobert Mustacchi "Keep Alive Timeout Invalid",
83d1efd556SRobert Mustacchi "Command Aborted due to Preempt and Abort",
84d1efd556SRobert Mustacchi "Sanitize Failed",
85d1efd556SRobert Mustacchi "Sanitize in Progress",
86d1efd556SRobert Mustacchi "SGL Data Block Granularity Invalid",
87d1efd556SRobert Mustacchi "Command Not Supported for Queue in CMB",
88d1efd556SRobert Mustacchi /* NVMe 1.4 -- 0x20 */
89d1efd556SRobert Mustacchi "Namespace is Write Protected",
90d1efd556SRobert Mustacchi "Command Interrupted",
91d1efd556SRobert Mustacchi "Transient Transport Error"
923d9b1a2aSHans Rosenfeld };
933d9b1a2aSHans Rosenfeld
943d9b1a2aSHans Rosenfeld static const char *specific_status_codes[] = {
953d9b1a2aSHans Rosenfeld "Completion Queue Invalid",
963d9b1a2aSHans Rosenfeld "Invalid Queue Identifier",
973d9b1a2aSHans Rosenfeld "Invalid Queue Size",
983d9b1a2aSHans Rosenfeld "Abort Command Limit Exceeded",
993d9b1a2aSHans Rosenfeld "Reserved",
1003d9b1a2aSHans Rosenfeld "Asynchronous Event Request Limit Exceeded",
1013d9b1a2aSHans Rosenfeld "Invalid Firmware Slot",
1023d9b1a2aSHans Rosenfeld "Invalid Firmware Image",
1033d9b1a2aSHans Rosenfeld "Invalid Interrupt Vector",
1043d9b1a2aSHans Rosenfeld "Invalid Log Page",
1053d9b1a2aSHans Rosenfeld "Invalid Format",
1063d9b1a2aSHans Rosenfeld "Firmware Activation Requires Conventional Reset",
1073d9b1a2aSHans Rosenfeld "Invalid Queue Deletion",
108d1efd556SRobert Mustacchi /* NVMe 1.1 -- 0xd */
1093d9b1a2aSHans Rosenfeld "Feature Identifier Not Saveable",
1103d9b1a2aSHans Rosenfeld "Feature Not Changeable",
1113d9b1a2aSHans Rosenfeld "Feature Not Namespace Specific",
1123d9b1a2aSHans Rosenfeld "Firmware Activation Requires NVM Subsystem Reset",
113d1efd556SRobert Mustacchi /* NVMe 1.2 -- 0x12 */
1143d9b1a2aSHans Rosenfeld "Firmware Activation Requires Reset",
1153d9b1a2aSHans Rosenfeld "Firmware Activation Requires Maximum Time Violation",
1163d9b1a2aSHans Rosenfeld "Firmware Activation Prohibited",
1173d9b1a2aSHans Rosenfeld "Overlapping Range",
1183d9b1a2aSHans Rosenfeld "Namespace Insufficient Capacity",
1193d9b1a2aSHans Rosenfeld "Namespace Identifier Unavailable",
1203d9b1a2aSHans Rosenfeld "Reserved",
1213d9b1a2aSHans Rosenfeld "Namespace Already Attached",
1223d9b1a2aSHans Rosenfeld "Namespace Is Private",
1233d9b1a2aSHans Rosenfeld "Namespace Not Attached",
1243d9b1a2aSHans Rosenfeld "Thin Provisioning Not Supported",
125d1efd556SRobert Mustacchi "Controller List Invalid",
126d1efd556SRobert Mustacchi /* NVMe 1.3 -- 0x1e */
127d1efd556SRobert Mustacchi "Boot Partition Write Prohibited",
128d1efd556SRobert Mustacchi "Invalid Controller Identifier",
129d1efd556SRobert Mustacchi "Invalid Secondary Controller State",
130d1efd556SRobert Mustacchi "Invalid Number of Controller Resources",
131d1efd556SRobert Mustacchi "Invalid Resource Identifier",
132d1efd556SRobert Mustacchi /* NVMe 1.4 -- 0x23 */
133d1efd556SRobert Mustacchi "Sanitize Prohibited While Persistent Memory Region is Enabled",
134d1efd556SRobert Mustacchi "ANA Group Identifier Invalid",
135d1efd556SRobert Mustacchi "ANA Attach Failed"
1363d9b1a2aSHans Rosenfeld };
1373d9b1a2aSHans Rosenfeld
1383d9b1a2aSHans Rosenfeld static const char *generic_nvm_status_codes[] = {
1393d9b1a2aSHans Rosenfeld "LBA Out Of Range",
1403d9b1a2aSHans Rosenfeld "Capacity Exceeded",
1413d9b1a2aSHans Rosenfeld "Namespace Not Ready",
1423d9b1a2aSHans Rosenfeld /* NVMe 1.1 */
1433d9b1a2aSHans Rosenfeld "Reservation Conflict",
1443d9b1a2aSHans Rosenfeld /* NVMe 1.2 */
1453d9b1a2aSHans Rosenfeld "Format In Progress",
1463d9b1a2aSHans Rosenfeld };
1473d9b1a2aSHans Rosenfeld
1483d9b1a2aSHans Rosenfeld static const char *specific_nvm_status_codes[] = {
1493d9b1a2aSHans Rosenfeld "Conflicting Attributes",
1503d9b1a2aSHans Rosenfeld "Invalid Protection Information",
1513d9b1a2aSHans Rosenfeld "Attempted Write to Read Only Range"
1523d9b1a2aSHans Rosenfeld };
1533d9b1a2aSHans Rosenfeld
1543d9b1a2aSHans Rosenfeld static const char *media_nvm_status_codes[] = {
1553d9b1a2aSHans Rosenfeld "Write Fault",
1563d9b1a2aSHans Rosenfeld "Unrecovered Read Error",
1573d9b1a2aSHans Rosenfeld "End-to-End Guard Check Error",
1583d9b1a2aSHans Rosenfeld "End-to-End Application Tag Check Error",
1593d9b1a2aSHans Rosenfeld "End-to-End Reference Tag Check Error",
1603d9b1a2aSHans Rosenfeld "Compare Failure",
1613d9b1a2aSHans Rosenfeld "Access Denied",
162d1efd556SRobert Mustacchi /* NVMe 1.2 -- 0x87 (0x7) */
1633d9b1a2aSHans Rosenfeld "Deallocated or Unwritten Logical Block"
1643d9b1a2aSHans Rosenfeld };
1653d9b1a2aSHans Rosenfeld
166d1efd556SRobert Mustacchi static const char *path_status_codes[] = {
167d1efd556SRobert Mustacchi /* NVMe 1.4 -- 0x00 */
168d1efd556SRobert Mustacchi "Internal Path Error",
169d1efd556SRobert Mustacchi "Asymmetric Access Persistent Loss",
170d1efd556SRobert Mustacchi "Asymmetric Access Inaccessible",
171d1efd556SRobert Mustacchi "Asymmetric Access Transition"
172d1efd556SRobert Mustacchi };
173d1efd556SRobert Mustacchi
174d1efd556SRobert Mustacchi static const char *path_controller_codes[] = {
175d1efd556SRobert Mustacchi /* NVMe 1.4 -- 0x60 */
176d1efd556SRobert Mustacchi "Controller Pathing Error"
177d1efd556SRobert Mustacchi };
178d1efd556SRobert Mustacchi
179d1efd556SRobert Mustacchi static const char *path_host_codes[] = {
180d1efd556SRobert Mustacchi /* NVMe 1.4 -- 0x70 */
181d1efd556SRobert Mustacchi "Host Pathing Error",
182d1efd556SRobert Mustacchi "Command Aborted by Host"
183d1efd556SRobert Mustacchi };
184d1efd556SRobert Mustacchi
1853d9b1a2aSHans Rosenfeld static const char *status_code_types[] = {
1863d9b1a2aSHans Rosenfeld "Generic Command Status",
1873d9b1a2aSHans Rosenfeld "Command Specific Status",
188d1efd556SRobert Mustacchi "Media and Data Integrity Errors",
189d1efd556SRobert Mustacchi "Path Related Status",
1903d9b1a2aSHans Rosenfeld "Reserved",
1913d9b1a2aSHans Rosenfeld "Reserved",
1923d9b1a2aSHans Rosenfeld "Reserved",
1933d9b1a2aSHans Rosenfeld "Vendor Specific"
1943d9b1a2aSHans Rosenfeld };
1953d9b1a2aSHans Rosenfeld
1963d9b1a2aSHans Rosenfeld static const char *lbaf_relative_performance[] = {
1973d9b1a2aSHans Rosenfeld "Best", "Better", "Good", "Degraded"
1983d9b1a2aSHans Rosenfeld };
1993d9b1a2aSHans Rosenfeld
2003d9b1a2aSHans Rosenfeld static const char *lba_range_types[] = {
2013d9b1a2aSHans Rosenfeld "Reserved", "Filesystem", "RAID", "Cache", "Page/Swap File"
2023d9b1a2aSHans Rosenfeld };
2033d9b1a2aSHans Rosenfeld
204153f3212SHans Rosenfeld static const char *ns_identifier_type[] = {
205153f3212SHans Rosenfeld "Reserved", "IEEE Extended Unique Identifier", "Namespace GUID", "UUID"
206153f3212SHans Rosenfeld };
207153f3212SHans Rosenfeld
2083d9b1a2aSHans Rosenfeld /*
2093d9b1a2aSHans Rosenfeld * nvme_print
2103d9b1a2aSHans Rosenfeld *
2113d9b1a2aSHans Rosenfeld * This function prints a string indented by the specified number of spaces,
2123d9b1a2aSHans Rosenfeld * optionally followed by the specified index if it is >= 0. If a format string
2133d9b1a2aSHans Rosenfeld * is specified, a single colon and the required number of spaces for alignment
2143d9b1a2aSHans Rosenfeld * are printed before the format string and any remaining arguments are passed
2153d9b1a2aSHans Rosenfeld * vprintf.
2163d9b1a2aSHans Rosenfeld *
2173d9b1a2aSHans Rosenfeld * NVME_PRINT_ALIGN was chosen so that all values will be lined up nicely even
2183d9b1a2aSHans Rosenfeld * for the longest name at its default indentation.
2193d9b1a2aSHans Rosenfeld */
2203d9b1a2aSHans Rosenfeld
2213d9b1a2aSHans Rosenfeld #define NVME_PRINT_ALIGN 43
2223d9b1a2aSHans Rosenfeld
2233d9b1a2aSHans Rosenfeld void
nvme_print(int indent,const char * name,int index,const char * fmt,...)2244a663bacSRobert Mustacchi nvme_print(int indent, const char *name, int index, const char *fmt, ...)
2253d9b1a2aSHans Rosenfeld {
226153f3212SHans Rosenfeld int align = NVME_PRINT_ALIGN - (indent + 1);
2273d9b1a2aSHans Rosenfeld va_list ap;
2283d9b1a2aSHans Rosenfeld
229153f3212SHans Rosenfeld if (name != NULL)
230153f3212SHans Rosenfeld align -= strlen(name);
231153f3212SHans Rosenfeld
2323d9b1a2aSHans Rosenfeld if (index >= 0)
2333d9b1a2aSHans Rosenfeld align -= snprintf(NULL, 0, " %d", index);
2343d9b1a2aSHans Rosenfeld
2353d9b1a2aSHans Rosenfeld if (align < 0)
2363d9b1a2aSHans Rosenfeld align = 0;
2373d9b1a2aSHans Rosenfeld
2383d9b1a2aSHans Rosenfeld va_start(ap, fmt);
2393d9b1a2aSHans Rosenfeld
240153f3212SHans Rosenfeld (void) printf("%*s%s", indent, "", name != NULL ? name : "");
2413d9b1a2aSHans Rosenfeld
2423d9b1a2aSHans Rosenfeld if (index >= 0)
2433d9b1a2aSHans Rosenfeld (void) printf(" %d", index);
2443d9b1a2aSHans Rosenfeld
2453d9b1a2aSHans Rosenfeld if (fmt != NULL) {
246153f3212SHans Rosenfeld if (name != NULL || index >= 0)
247153f3212SHans Rosenfeld (void) printf(": ");
248153f3212SHans Rosenfeld else
249153f3212SHans Rosenfeld (void) printf(" ");
250153f3212SHans Rosenfeld (void) printf("%*s", align, "");
2513d9b1a2aSHans Rosenfeld (void) vprintf(fmt, ap);
2523d9b1a2aSHans Rosenfeld }
2533d9b1a2aSHans Rosenfeld
2543d9b1a2aSHans Rosenfeld (void) printf("\n");
2553d9b1a2aSHans Rosenfeld va_end(ap);
2563d9b1a2aSHans Rosenfeld }
2573d9b1a2aSHans Rosenfeld
2583d9b1a2aSHans Rosenfeld /*
2593d9b1a2aSHans Rosenfeld * nvme_strlen -- return length of string without trailing whitespace
2603d9b1a2aSHans Rosenfeld */
261e4cc4004SRobert Mustacchi int
nvme_strlen(const char * str,int len)2623d9b1a2aSHans Rosenfeld nvme_strlen(const char *str, int len)
2633d9b1a2aSHans Rosenfeld {
2643281964bSHans Rosenfeld if (len <= 0)
2653d9b1a2aSHans Rosenfeld return (0);
2663d9b1a2aSHans Rosenfeld
2673d9b1a2aSHans Rosenfeld while (str[--len] == ' ')
2683d9b1a2aSHans Rosenfeld ;
2693d9b1a2aSHans Rosenfeld
2703d9b1a2aSHans Rosenfeld return (++len);
2713d9b1a2aSHans Rosenfeld }
2723d9b1a2aSHans Rosenfeld
2733d9b1a2aSHans Rosenfeld /*
2743d9b1a2aSHans Rosenfeld * nvme_print_str -- print a string up to the specified length
2753d9b1a2aSHans Rosenfeld */
2763d9b1a2aSHans Rosenfeld static void
nvme_print_str(int indent,const char * name,int index,const char * value,int len)2774a663bacSRobert Mustacchi nvme_print_str(int indent, const char *name, int index, const char *value,
2784a663bacSRobert Mustacchi int len)
2793d9b1a2aSHans Rosenfeld {
2803d9b1a2aSHans Rosenfeld if (len == 0)
2813d9b1a2aSHans Rosenfeld len = strlen(value);
2823d9b1a2aSHans Rosenfeld
2833d9b1a2aSHans Rosenfeld nvme_print(indent, name, index, "%.*s", nvme_strlen(value, len), value);
2843d9b1a2aSHans Rosenfeld }
2853d9b1a2aSHans Rosenfeld
2863d9b1a2aSHans Rosenfeld /*
2873d9b1a2aSHans Rosenfeld * nvme_print_double -- print a double up to a specified number of places with
2883d9b1a2aSHans Rosenfeld * optional unit
2893d9b1a2aSHans Rosenfeld */
2903d9b1a2aSHans Rosenfeld static void
nvme_print_double(int indent,const char * name,double value,int places,const char * unit)2914a663bacSRobert Mustacchi nvme_print_double(int indent, const char *name, double value, int places,
2924a663bacSRobert Mustacchi const char *unit)
2933d9b1a2aSHans Rosenfeld {
2943d9b1a2aSHans Rosenfeld if (unit == NULL)
2953d9b1a2aSHans Rosenfeld unit = "";
2963d9b1a2aSHans Rosenfeld
2973d9b1a2aSHans Rosenfeld nvme_print(indent, name, -1, "%.*g%s", places, value, unit);
2983d9b1a2aSHans Rosenfeld }
2993d9b1a2aSHans Rosenfeld
3003d9b1a2aSHans Rosenfeld /*
3014a663bacSRobert Mustacchi * nvme_print_int64 -- print int64_t with optional unit in decimal or another
3023d9b1a2aSHans Rosenfeld * format specified
3033d9b1a2aSHans Rosenfeld */
3043d9b1a2aSHans Rosenfeld static void
nvme_print_int64(int indent,const char * name,uint64_t value,const char * fmt,const char * unit)3054a663bacSRobert Mustacchi nvme_print_int64(int indent, const char *name, uint64_t value, const char *fmt,
3064a663bacSRobert Mustacchi const char *unit)
3073d9b1a2aSHans Rosenfeld {
3083d9b1a2aSHans Rosenfeld char *tmp_fmt;
3093d9b1a2aSHans Rosenfeld
3103d9b1a2aSHans Rosenfeld if (unit == NULL)
3113d9b1a2aSHans Rosenfeld unit = "";
3123d9b1a2aSHans Rosenfeld
3133d9b1a2aSHans Rosenfeld if (fmt == NULL)
3143d9b1a2aSHans Rosenfeld fmt = "%"PRId64;
3153d9b1a2aSHans Rosenfeld
3164a663bacSRobert Mustacchi if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0)
3174a663bacSRobert Mustacchi err(-1, "nvme_print_int64()");
3184a663bacSRobert Mustacchi
3194a663bacSRobert Mustacchi nvme_print(indent, name, -1, tmp_fmt, value, unit);
3204a663bacSRobert Mustacchi
3214a663bacSRobert Mustacchi free(tmp_fmt);
3224a663bacSRobert Mustacchi }
3234a663bacSRobert Mustacchi
3244a663bacSRobert Mustacchi /*
3254a663bacSRobert Mustacchi * nvme_print_temp -- The NVMe specification passes most temperature values as
3264a663bacSRobert Mustacchi * uint16_t values that are encoded in kelvin. This converts them in one place
3274a663bacSRobert Mustacchi * to Celsius.
3284a663bacSRobert Mustacchi */
3294a663bacSRobert Mustacchi static void
nvme_print_temp(int indent,const char * name,uint16_t value)3304a663bacSRobert Mustacchi nvme_print_temp(int indent, const char *name, uint16_t value)
3314a663bacSRobert Mustacchi {
3324a663bacSRobert Mustacchi int64_t temp = (int64_t)value;
3334a663bacSRobert Mustacchi temp -= 273;
3344a663bacSRobert Mustacchi nvme_print_int64(indent, name, temp, NULL, "C");
3354a663bacSRobert Mustacchi }
3364a663bacSRobert Mustacchi
3374a663bacSRobert Mustacchi /*
3384a663bacSRobert Mustacchi * nvme_print_uint64 -- print uint64_t with optional unit in decimal or another
3394a663bacSRobert Mustacchi * format specified
3404a663bacSRobert Mustacchi */
3414a663bacSRobert Mustacchi static void
nvme_print_uint64(int indent,const char * name,uint64_t value,const char * fmt,const char * unit)3424a663bacSRobert Mustacchi nvme_print_uint64(int indent, const char *name, uint64_t value, const char *fmt,
3434a663bacSRobert Mustacchi const char *unit)
3444a663bacSRobert Mustacchi {
3454a663bacSRobert Mustacchi char *tmp_fmt;
3464a663bacSRobert Mustacchi
3474a663bacSRobert Mustacchi if (unit == NULL)
3484a663bacSRobert Mustacchi unit = "";
3494a663bacSRobert Mustacchi
3504a663bacSRobert Mustacchi if (fmt == NULL)
3514a663bacSRobert Mustacchi fmt = "%"PRIu64;
3524a663bacSRobert Mustacchi
3533d9b1a2aSHans Rosenfeld if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0)
3543d9b1a2aSHans Rosenfeld err(-1, "nvme_print_uint64()");
3553d9b1a2aSHans Rosenfeld
3563d9b1a2aSHans Rosenfeld nvme_print(indent, name, -1, tmp_fmt, value, unit);
3573d9b1a2aSHans Rosenfeld
3583d9b1a2aSHans Rosenfeld free(tmp_fmt);
3593d9b1a2aSHans Rosenfeld }
3603d9b1a2aSHans Rosenfeld
3613d9b1a2aSHans Rosenfeld /*
362b3266bebSHans Rosenfeld * nvme_snprint_uint128 -- format a 128bit uint with optional unit, after
363b3266bebSHans Rosenfeld * applying binary and/or decimal shifting
3643d9b1a2aSHans Rosenfeld */
365b3266bebSHans Rosenfeld int
nvme_snprint_uint128(char * buf,size_t buflen,nvme_uint128_t value,int scale_bits,int scale_tens)366b3266bebSHans Rosenfeld nvme_snprint_uint128(char *buf, size_t buflen, nvme_uint128_t value,
367b3266bebSHans Rosenfeld int scale_bits, int scale_tens)
3683d9b1a2aSHans Rosenfeld {
3693d9b1a2aSHans Rosenfeld const char hex[] = "0123456789abcdef";
3703d9b1a2aSHans Rosenfeld uint8_t o[(128 + scale_bits) / 3];
3713d9b1a2aSHans Rosenfeld char p[sizeof (o) * 2];
3723d9b1a2aSHans Rosenfeld char *pp = &p[0];
3733d9b1a2aSHans Rosenfeld int i, x;
3743d9b1a2aSHans Rosenfeld uint64_t rem = 0;
3753d9b1a2aSHans Rosenfeld
3763d9b1a2aSHans Rosenfeld /*
3773d9b1a2aSHans Rosenfeld * Don't allow binary shifting by more than 64 bits to keep the
3783d9b1a2aSHans Rosenfeld * arithmetic simple. Also limit decimal shifting based on the size
3793d9b1a2aSHans Rosenfeld * of any possible remainder from binary shifting.
3803d9b1a2aSHans Rosenfeld */
3813d9b1a2aSHans Rosenfeld assert(scale_bits <= 64);
3823d9b1a2aSHans Rosenfeld assert(scale_tens <= (64 - scale_bits) / 3);
3833d9b1a2aSHans Rosenfeld
3843d9b1a2aSHans Rosenfeld bzero(o, sizeof (o));
3853d9b1a2aSHans Rosenfeld bzero(p, sizeof (p));
3863d9b1a2aSHans Rosenfeld
3873d9b1a2aSHans Rosenfeld /*
3883d9b1a2aSHans Rosenfeld * Convert the two 64-bit numbers into a series of BCD digits using
3893d9b1a2aSHans Rosenfeld * a double-dabble algorithm. By using more or less iterations than
3903d9b1a2aSHans Rosenfeld * 128 we can do a binary shift in either direction.
3913d9b1a2aSHans Rosenfeld */
3923d9b1a2aSHans Rosenfeld for (x = 0; x != 128 - scale_bits; x++) {
3933d9b1a2aSHans Rosenfeld for (i = 0; i != sizeof (o); i++) {
3943d9b1a2aSHans Rosenfeld if ((o[i] & 0xf0) > 0x40)
3953d9b1a2aSHans Rosenfeld o[i] += 0x30;
3963d9b1a2aSHans Rosenfeld
3973d9b1a2aSHans Rosenfeld if ((o[i] & 0xf) > 4)
3983d9b1a2aSHans Rosenfeld o[i] += 3;
3993d9b1a2aSHans Rosenfeld }
4003d9b1a2aSHans Rosenfeld
4013d9b1a2aSHans Rosenfeld for (i = 0; i != sizeof (o) - 1; i++)
4023d9b1a2aSHans Rosenfeld o[i] = (o[i] << 1) + (o[i+1] >> 7);
4033d9b1a2aSHans Rosenfeld
4043d9b1a2aSHans Rosenfeld o[i] = (o[i] << 1) + (value.hi >> 63);
4053d9b1a2aSHans Rosenfeld
4063d9b1a2aSHans Rosenfeld value.hi = (value.hi << 1) + (value.lo >> 63);
4073d9b1a2aSHans Rosenfeld value.lo = (value.lo << 1);
4083d9b1a2aSHans Rosenfeld }
4093d9b1a2aSHans Rosenfeld
4103d9b1a2aSHans Rosenfeld /*
4113d9b1a2aSHans Rosenfeld * If we're supposed to do a decimal left shift (* 10^x), too,
4123d9b1a2aSHans Rosenfeld * calculate the remainder of the previous binary shift operation.
4133d9b1a2aSHans Rosenfeld */
4143d9b1a2aSHans Rosenfeld if (scale_tens > 0) {
4153d9b1a2aSHans Rosenfeld rem = value.hi >> (64 - scale_bits);
4163d9b1a2aSHans Rosenfeld
4173d9b1a2aSHans Rosenfeld for (i = 0; i != scale_tens; i++)
4183d9b1a2aSHans Rosenfeld rem *= 10;
4193d9b1a2aSHans Rosenfeld
4203d9b1a2aSHans Rosenfeld rem >>= scale_bits;
4213d9b1a2aSHans Rosenfeld }
4223d9b1a2aSHans Rosenfeld
4233d9b1a2aSHans Rosenfeld /*
4243d9b1a2aSHans Rosenfeld * Construct the decimal number for printing. Skip leading zeros.
4253d9b1a2aSHans Rosenfeld */
4263d9b1a2aSHans Rosenfeld for (i = 0; i < sizeof (o); i++)
4273d9b1a2aSHans Rosenfeld if (o[i] != 0)
4283d9b1a2aSHans Rosenfeld break;
4293d9b1a2aSHans Rosenfeld
4303d9b1a2aSHans Rosenfeld if (i == sizeof (o)) {
4313d9b1a2aSHans Rosenfeld /*
4323d9b1a2aSHans Rosenfeld * The converted number is 0. Just print the calculated
4333d9b1a2aSHans Rosenfeld * remainder and return.
4343d9b1a2aSHans Rosenfeld */
435b3266bebSHans Rosenfeld return (snprintf(buf, buflen, "%"PRId64, rem));
4363d9b1a2aSHans Rosenfeld } else {
4373d9b1a2aSHans Rosenfeld if (o[i] > 0xf)
4383d9b1a2aSHans Rosenfeld *pp++ = hex[o[i] >> 4];
4393d9b1a2aSHans Rosenfeld
4403d9b1a2aSHans Rosenfeld *pp++ = hex[o[i] & 0xf];
4413d9b1a2aSHans Rosenfeld
4423d9b1a2aSHans Rosenfeld for (i++; i < sizeof (o); i++) {
4433d9b1a2aSHans Rosenfeld *pp++ = hex[o[i] >> 4];
4443d9b1a2aSHans Rosenfeld *pp++ = hex[o[i] & 0xf];
4453d9b1a2aSHans Rosenfeld }
4463d9b1a2aSHans Rosenfeld }
4473d9b1a2aSHans Rosenfeld
4483d9b1a2aSHans Rosenfeld /*
449b3266bebSHans Rosenfeld * For negative decimal scaling, use the snprintf precision specifier to
4503d9b1a2aSHans Rosenfeld * truncate the results according to the requested decimal scaling. For
4513d9b1a2aSHans Rosenfeld * positive decimal scaling we print the remainder padded with 0.
4523d9b1a2aSHans Rosenfeld */
453b3266bebSHans Rosenfeld return (snprintf(buf, buflen, "%.*s%0.*"PRId64,
4543d9b1a2aSHans Rosenfeld strlen(p) + scale_tens, p,
455b3266bebSHans Rosenfeld scale_tens > 0 ? scale_tens : 0, rem));
456b3266bebSHans Rosenfeld }
457b3266bebSHans Rosenfeld
458b3266bebSHans Rosenfeld /*
459b3266bebSHans Rosenfeld * nvme_print_uint128 -- print a 128bit uint with optional unit, after applying
460b3266bebSHans Rosenfeld * binary and/or decimal shifting
461b3266bebSHans Rosenfeld */
462b3266bebSHans Rosenfeld static void
nvme_print_uint128(int indent,const char * name,nvme_uint128_t value,const char * unit,int scale_bits,int scale_tens)463b3266bebSHans Rosenfeld nvme_print_uint128(int indent, const char *name, nvme_uint128_t value,
464b3266bebSHans Rosenfeld const char *unit, int scale_bits, int scale_tens)
465b3266bebSHans Rosenfeld {
466b3266bebSHans Rosenfeld char buf[64];
467b3266bebSHans Rosenfeld
468b3266bebSHans Rosenfeld if (unit == NULL)
469b3266bebSHans Rosenfeld unit = "";
470b3266bebSHans Rosenfeld
471b3266bebSHans Rosenfeld (void) nvme_snprint_uint128(buf, sizeof (buf), value, scale_bits,
472b3266bebSHans Rosenfeld scale_tens);
473b3266bebSHans Rosenfeld
474b3266bebSHans Rosenfeld nvme_print(indent, name, -1, "%s%s", buf, unit);
4753d9b1a2aSHans Rosenfeld }
4763d9b1a2aSHans Rosenfeld
4773d9b1a2aSHans Rosenfeld /*
4783d9b1a2aSHans Rosenfeld * nvme_print_bit -- print a bit with optional names for both states
4793d9b1a2aSHans Rosenfeld */
4803d9b1a2aSHans Rosenfeld static void
nvme_print_bit(int indent,const char * name,boolean_t valid_vers,uint_t value,const char * s_true,const char * s_false)4818d5300d3SRobert Mustacchi nvme_print_bit(int indent, const char *name, boolean_t valid_vers, uint_t value,
4828d5300d3SRobert Mustacchi const char *s_true, const char *s_false)
4833d9b1a2aSHans Rosenfeld {
4843d9b1a2aSHans Rosenfeld if (s_true == NULL)
4853d9b1a2aSHans Rosenfeld s_true = "supported";
4863d9b1a2aSHans Rosenfeld if (s_false == NULL)
4873d9b1a2aSHans Rosenfeld s_false = "unsupported";
4883d9b1a2aSHans Rosenfeld
4898d5300d3SRobert Mustacchi if (!valid_vers)
4908d5300d3SRobert Mustacchi value = 0;
4918d5300d3SRobert Mustacchi
4923d9b1a2aSHans Rosenfeld nvme_print(indent, name, -1, "%s", value ? s_true : s_false);
4933d9b1a2aSHans Rosenfeld }
4943d9b1a2aSHans Rosenfeld
495153f3212SHans Rosenfeld /*
496153f3212SHans Rosenfeld * nvme_print_hexbuf -- print a buffer of bytes as a hex dump
497153f3212SHans Rosenfeld */
498153f3212SHans Rosenfeld static void
nvme_print_hexbuf(int indent,const char * name,const uint8_t * buf,size_t len)499153f3212SHans Rosenfeld nvme_print_hexbuf(int indent, const char *name, const uint8_t *buf, size_t len)
500153f3212SHans Rosenfeld {
501153f3212SHans Rosenfeld /*
502153f3212SHans Rosenfeld * The format string is kept in this variable so it can be cut
503153f3212SHans Rosenfeld * short to print the remainder after the loop.
504153f3212SHans Rosenfeld */
505153f3212SHans Rosenfeld char fmt[] = { "%02x %02x %02x %02x %02x %02x %02x %02x" };
506153f3212SHans Rosenfeld size_t lines = len / 8;
507153f3212SHans Rosenfeld size_t rem = len % 8;
508153f3212SHans Rosenfeld size_t i;
509153f3212SHans Rosenfeld
510153f3212SHans Rosenfeld for (i = 0; i < lines; i++) {
511153f3212SHans Rosenfeld nvme_print(indent, name, -1, fmt,
512153f3212SHans Rosenfeld buf[i*8 + 0], buf[i*8 + 1], buf[i*8 + 2], buf[i*8 + 3],
513153f3212SHans Rosenfeld buf[i*8 + 4], buf[i*8 + 5], buf[i*8 + 6], buf[i*8 + 7]);
514153f3212SHans Rosenfeld name = NULL;
515153f3212SHans Rosenfeld }
516153f3212SHans Rosenfeld
517153f3212SHans Rosenfeld if (rem > 0) {
518153f3212SHans Rosenfeld fmt[rem * 5] = '\0';
519153f3212SHans Rosenfeld
520153f3212SHans Rosenfeld nvme_print(indent, name, -1, fmt,
521153f3212SHans Rosenfeld buf[i*8 + 0], buf[i*8 + 1], buf[i*8 + 2], buf[i*8 + 3],
522153f3212SHans Rosenfeld buf[i*8 + 4], buf[i*8 + 5], buf[i*8 + 6], buf[i*8 + 7]);
523153f3212SHans Rosenfeld }
524153f3212SHans Rosenfeld }
525153f3212SHans Rosenfeld
526153f3212SHans Rosenfeld /*
527153f3212SHans Rosenfeld * nvme_print_uuid -- print a UUID in canonical form
528153f3212SHans Rosenfeld */
529153f3212SHans Rosenfeld static void
nvme_print_uuid(int indent,const char * name,const uint8_t * uuid)530153f3212SHans Rosenfeld nvme_print_uuid(int indent, const char *name, const uint8_t *uuid)
531153f3212SHans Rosenfeld {
532153f3212SHans Rosenfeld nvme_print(indent, name, -1,
533153f3212SHans Rosenfeld "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
534153f3212SHans Rosenfeld "%02x%02x%02x%02x%02x%02x",
535153f3212SHans Rosenfeld uuid[0], uuid[1], uuid[2], uuid[3],
536153f3212SHans Rosenfeld uuid[4], uuid[5], uuid[6], uuid[7],
537153f3212SHans Rosenfeld uuid[8], uuid[9], uuid[10], uuid[11],
538153f3212SHans Rosenfeld uuid[12], uuid[13], uuid[14], uuid[15]);
539153f3212SHans Rosenfeld }
540153f3212SHans Rosenfeld
541153f3212SHans Rosenfeld /*
542153f3212SHans Rosenfeld * nvme_print_guid -- print a namespace GUID
543153f3212SHans Rosenfeld */
544153f3212SHans Rosenfeld static void
nvme_print_guid(int indent,const char * name,const uint8_t * guid)545153f3212SHans Rosenfeld nvme_print_guid(int indent, const char *name, const uint8_t *guid)
546153f3212SHans Rosenfeld {
547153f3212SHans Rosenfeld nvme_print(indent, name, -1,
548153f3212SHans Rosenfeld "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
549153f3212SHans Rosenfeld guid[0], guid[1], guid[2], guid[3],
550153f3212SHans Rosenfeld guid[4], guid[5], guid[6], guid[7],
551153f3212SHans Rosenfeld guid[8], guid[9], guid[10], guid[11],
552153f3212SHans Rosenfeld guid[12], guid[13], guid[14], guid[15]);
553153f3212SHans Rosenfeld }
554153f3212SHans Rosenfeld
555153f3212SHans Rosenfeld /*
556153f3212SHans Rosenfeld * nvme_print_eui64 -- print a namespace EUI64
557153f3212SHans Rosenfeld */
558153f3212SHans Rosenfeld static void
nvme_print_eui64(int indent,const char * name,const uint8_t * eui64)559153f3212SHans Rosenfeld nvme_print_eui64(int indent, const char *name, const uint8_t *eui64)
560153f3212SHans Rosenfeld {
561153f3212SHans Rosenfeld nvme_print(indent, name, -1,
562153f3212SHans Rosenfeld "%02X%02X%02X%02X%02X%02X%02X%02X",
563153f3212SHans Rosenfeld eui64[0], eui64[1], eui64[2], eui64[3],
564153f3212SHans Rosenfeld eui64[4], eui64[5], eui64[6], eui64[7]);
565153f3212SHans Rosenfeld }
566153f3212SHans Rosenfeld
5678d5300d3SRobert Mustacchi /*
5688d5300d3SRobert Mustacchi * nvme_print_version -- print a uint32_t encoded nvme version
5698d5300d3SRobert Mustacchi */
5708d5300d3SRobert Mustacchi static void
nvme_print_version(int indent,const char * name,uint32_t value)5718d5300d3SRobert Mustacchi nvme_print_version(int indent, const char *name, uint32_t value)
5728d5300d3SRobert Mustacchi {
5738d5300d3SRobert Mustacchi nvme_reg_vs_t vers;
5748d5300d3SRobert Mustacchi
5758d5300d3SRobert Mustacchi vers.r = value;
5768d5300d3SRobert Mustacchi nvme_print(indent, name, -1, "%u.%u", vers.b.vs_mjr, vers.b.vs_mnr);
5778d5300d3SRobert Mustacchi }
5788d5300d3SRobert Mustacchi
5793d9b1a2aSHans Rosenfeld /*
5803d9b1a2aSHans Rosenfeld * nvme_print_ctrl_summary -- print a 1-line summary of the IDENTIFY CONTROLLER
5813d9b1a2aSHans Rosenfeld * data structure
5823d9b1a2aSHans Rosenfeld */
5833d9b1a2aSHans Rosenfeld void
nvme_print_ctrl_summary(nvme_ctrl_info_t * info)584*533affcbSRobert Mustacchi nvme_print_ctrl_summary(nvme_ctrl_info_t *info)
5853d9b1a2aSHans Rosenfeld {
586*533affcbSRobert Mustacchi nvme_uint128_t u128;
587*533affcbSRobert Mustacchi char buf[64];
588b3266bebSHans Rosenfeld
589*533affcbSRobert Mustacchi const nvme_version_t *version = nvme_ctrl_info_version(info);
590*533affcbSRobert Mustacchi
591*533affcbSRobert Mustacchi (void) printf("model: %s, serial: %s, FW rev: %s, NVMe v%u.%u",
592*533affcbSRobert Mustacchi nvme_ctrl_info_model(info), nvme_ctrl_info_serial(info),
593*533affcbSRobert Mustacchi nvme_ctrl_info_fwrev(info), version->v_major, version->v_minor);
594b3266bebSHans Rosenfeld
595*533affcbSRobert Mustacchi /*
596*533affcbSRobert Mustacchi * This can fail because a device isn't at NVMe version 1.2 or it
597*533affcbSRobert Mustacchi * doesn't support namespace management.
598*533affcbSRobert Mustacchi */
599*533affcbSRobert Mustacchi if (nvme_ctrl_info_cap(info, &u128)) {
600*533affcbSRobert Mustacchi (void) nvme_snprint_uint128(buf, sizeof (buf), u128, 20, 0);
601b3266bebSHans Rosenfeld (void) printf(", Capacity = %s MB", buf);
602*533affcbSRobert Mustacchi }
603*533affcbSRobert Mustacchi
604*533affcbSRobert Mustacchi if (nvme_ctrl_info_unalloc_cap(info, &u128) && (u128.lo != 0 ||
605*533affcbSRobert Mustacchi u128.hi != 0)) {
606*533affcbSRobert Mustacchi (void) nvme_snprint_uint128(buf, sizeof (buf), u128, 20, 0);
607*533affcbSRobert Mustacchi (void) printf(", Unallocated = %s MB", buf);
608b3266bebSHans Rosenfeld }
609b3266bebSHans Rosenfeld
610b3266bebSHans Rosenfeld (void) printf("\n");
6113d9b1a2aSHans Rosenfeld }
6123d9b1a2aSHans Rosenfeld
6133d9b1a2aSHans Rosenfeld /*
6143d9b1a2aSHans Rosenfeld * nvme_print_nsid_summary -- print a 1-line summary of the IDENTIFY NAMESPACE
6153d9b1a2aSHans Rosenfeld * data structure
6163d9b1a2aSHans Rosenfeld */
6173d9b1a2aSHans Rosenfeld void
nvme_print_nsid_summary(nvme_ns_info_t * ns)618*533affcbSRobert Mustacchi nvme_print_nsid_summary(nvme_ns_info_t *ns)
6193d9b1a2aSHans Rosenfeld {
620*533affcbSRobert Mustacchi const nvme_nvm_lba_fmt_t *fmt = NULL;
621*533affcbSRobert Mustacchi const char *comma = "";
622*533affcbSRobert Mustacchi uint64_t val;
623a713ecffSHans Rosenfeld char numbuf[40];
6243d9b1a2aSHans Rosenfeld
625*533affcbSRobert Mustacchi (void) nvme_ns_info_curformat(ns, &fmt);
626*533affcbSRobert Mustacchi
627*533affcbSRobert Mustacchi if (nvme_ns_info_size(ns, &val) && fmt != NULL) {
628*533affcbSRobert Mustacchi nicenum_scale(val, nvme_nvm_lba_fmt_data_size(fmt), numbuf,
629*533affcbSRobert Mustacchi sizeof (numbuf), NN_UNIT_SPACE);
630*533affcbSRobert Mustacchi (void) printf("Size = %sB", numbuf);
631*533affcbSRobert Mustacchi comma = ", ";
632*533affcbSRobert Mustacchi }
6333d9b1a2aSHans Rosenfeld
634*533affcbSRobert Mustacchi if (nvme_ns_info_cap(ns, &val) && fmt != NULL) {
635*533affcbSRobert Mustacchi nicenum_scale(val, nvme_nvm_lba_fmt_data_size(fmt), numbuf,
636*533affcbSRobert Mustacchi sizeof (numbuf), NN_UNIT_SPACE);
637*533affcbSRobert Mustacchi (void) printf("%sCapacity = %sB", comma, numbuf);
638*533affcbSRobert Mustacchi comma = ", ";
639*533affcbSRobert Mustacchi }
640a713ecffSHans Rosenfeld
641*533affcbSRobert Mustacchi if (nvme_ns_info_use(ns, &val) && fmt != NULL) {
642*533affcbSRobert Mustacchi nicenum_scale(val, nvme_nvm_lba_fmt_data_size(fmt), numbuf,
643*533affcbSRobert Mustacchi sizeof (numbuf), NN_UNIT_SPACE);
644*533affcbSRobert Mustacchi (void) printf("%sUsed = %sB", comma, numbuf);
645*533affcbSRobert Mustacchi }
646*533affcbSRobert Mustacchi (void) printf("\n");
6473d9b1a2aSHans Rosenfeld }
6483d9b1a2aSHans Rosenfeld
6493d9b1a2aSHans Rosenfeld /*
6503d9b1a2aSHans Rosenfeld * nvme_print_identify_ctrl
6513d9b1a2aSHans Rosenfeld *
6523d9b1a2aSHans Rosenfeld * This function pretty-prints the structure returned by the IDENTIFY CONTROLLER
6533d9b1a2aSHans Rosenfeld * command.
6543d9b1a2aSHans Rosenfeld */
6553d9b1a2aSHans Rosenfeld void
nvme_print_identify_ctrl(const nvme_identify_ctrl_t * idctl,uint32_t mpsmin,const nvme_version_t * version)656*533affcbSRobert Mustacchi nvme_print_identify_ctrl(const nvme_identify_ctrl_t *idctl, uint32_t mpsmin,
657*533affcbSRobert Mustacchi const nvme_version_t *version)
6583d9b1a2aSHans Rosenfeld {
6593d9b1a2aSHans Rosenfeld int i;
6603d9b1a2aSHans Rosenfeld
6613d9b1a2aSHans Rosenfeld nvme_print(0, "Identify Controller", -1, NULL);
6623d9b1a2aSHans Rosenfeld nvme_print(2, "Controller Capabilities and Features", -1, NULL);
6633d9b1a2aSHans Rosenfeld nvme_print_str(4, "Model", -1,
6643d9b1a2aSHans Rosenfeld idctl->id_model, sizeof (idctl->id_model));
6653d9b1a2aSHans Rosenfeld nvme_print_str(4, "Serial", -1,
6663d9b1a2aSHans Rosenfeld idctl->id_serial, sizeof (idctl->id_serial));
6673d9b1a2aSHans Rosenfeld nvme_print_str(4, "Firmware Revision", -1,
6683d9b1a2aSHans Rosenfeld idctl->id_fwrev, sizeof (idctl->id_fwrev));
6693d9b1a2aSHans Rosenfeld if (verbose) {
6703d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "PCI vendor ID",
6713d9b1a2aSHans Rosenfeld idctl->id_vid, "0x%0.4"PRIx64, NULL);
6723d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "subsystem vendor ID",
6733d9b1a2aSHans Rosenfeld idctl->id_ssvid, "0x%0.4"PRIx64, NULL);
6743d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Recommended Arbitration Burst",
6753d9b1a2aSHans Rosenfeld idctl->id_rab, NULL, NULL);
6763d9b1a2aSHans Rosenfeld nvme_print(4, "Vendor IEEE OUI", -1, "%0.2X-%0.2X-%0.2X",
6773d9b1a2aSHans Rosenfeld idctl->id_oui[0], idctl->id_oui[1], idctl->id_oui[2]);
6783d9b1a2aSHans Rosenfeld }
6793d9b1a2aSHans Rosenfeld nvme_print(4, "Multi-Interface Capabilities", -1, NULL);
6803d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Multiple PCI Express ports",
681*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
6823d9b1a2aSHans Rosenfeld idctl->id_mic.m_multi_pci, NULL, NULL);
6838d5300d3SRobert Mustacchi nvme_print_bit(6, "Multiple Controller Support",
684*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
6858d5300d3SRobert Mustacchi idctl->id_mic.m_multi_ctrl, NULL, NULL);
6868d5300d3SRobert Mustacchi nvme_print_bit(6, "Controller is an SR-IOV Virtual Function",
687*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
6888d5300d3SRobert Mustacchi idctl->id_mic.m_sr_iov, NULL, NULL);
6898d5300d3SRobert Mustacchi nvme_print_bit(6, "Asymmetric Namespace Access Reporting",
690*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
6918d5300d3SRobert Mustacchi idctl->id_mic.m_anar_sup, NULL, NULL);
6923d9b1a2aSHans Rosenfeld
6933d9b1a2aSHans Rosenfeld if (idctl->id_mdts > 0)
6943d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Maximum Data Transfer Size",
695*533affcbSRobert Mustacchi (1 << idctl->id_mdts) * mpsmin / 1024, NULL, "kB");
6963d9b1a2aSHans Rosenfeld else
6973d9b1a2aSHans Rosenfeld nvme_print_str(4, "Maximum Data Transfer Size", -1,
6983d9b1a2aSHans Rosenfeld "unlimited", 0);
6993d9b1a2aSHans Rosenfeld
700*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v1)) {
7013d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Unique Controller Identifier",
702153f3212SHans Rosenfeld idctl->id_cntlid, NULL, NULL);
7033d9b1a2aSHans Rosenfeld }
7043d9b1a2aSHans Rosenfeld
705*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v2)) {
7068d5300d3SRobert Mustacchi nvme_print_version(4, "NVMe Version",
7078d5300d3SRobert Mustacchi idctl->id_ver);
7088d5300d3SRobert Mustacchi
7098d5300d3SRobert Mustacchi if (idctl->id_rtd3r != 0) {
7108d5300d3SRobert Mustacchi nvme_print_uint64(4, "RTD3 Resume Latency",
7118d5300d3SRobert Mustacchi idctl->id_rtd3r, NULL, "us");
7128d5300d3SRobert Mustacchi }
7138d5300d3SRobert Mustacchi
7148d5300d3SRobert Mustacchi if (idctl->id_rtd3e != 0) {
7158d5300d3SRobert Mustacchi nvme_print_uint64(4, "RTD3 Entry Latency",
7168d5300d3SRobert Mustacchi idctl->id_rtd3e, NULL, "us");
7178d5300d3SRobert Mustacchi }
7188d5300d3SRobert Mustacchi }
7198d5300d3SRobert Mustacchi
7208d5300d3SRobert Mustacchi if (verbose) {
7218d5300d3SRobert Mustacchi nvme_print(4, "Optional Asynchronous Events Supported", -1,
7228d5300d3SRobert Mustacchi NULL);
7238d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace Attribute Notices",
724*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
7258d5300d3SRobert Mustacchi idctl->id_oaes.oaes_nsan, NULL, NULL);
7268d5300d3SRobert Mustacchi nvme_print_bit(6, "Firmware Activation Notices",
727*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
7288d5300d3SRobert Mustacchi idctl->id_oaes.oaes_fwact, NULL, NULL);
7298d5300d3SRobert Mustacchi nvme_print_bit(6, "Asynchronous Namespace Access Change "
7308d5300d3SRobert Mustacchi "Notices",
731*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7328d5300d3SRobert Mustacchi idctl->id_oaes.oaes_ansacn, NULL, NULL);
7338d5300d3SRobert Mustacchi nvme_print_bit(6, "Predictable Latency Event Aggregation",
734*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7358d5300d3SRobert Mustacchi idctl->id_oaes.oaes_plat, NULL, NULL);
7368d5300d3SRobert Mustacchi nvme_print_bit(6, "LBA Status Information Notices",
737*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7388d5300d3SRobert Mustacchi idctl->id_oaes.oaes_lbasi, NULL, NULL);
7398d5300d3SRobert Mustacchi nvme_print_bit(6, "Endurance Group Event Aggregate Log Page "
7408d5300d3SRobert Mustacchi "Change Notices",
741*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7428d5300d3SRobert Mustacchi idctl->id_oaes.oaes_egeal, NULL, NULL);
7438d5300d3SRobert Mustacchi
7448d5300d3SRobert Mustacchi nvme_print(4, "Controller Attributes", -1,
7458d5300d3SRobert Mustacchi NULL);
7468d5300d3SRobert Mustacchi nvme_print_bit(6, "128-bit Host Identifier",
747*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
7488d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_hid, NULL, NULL);
7498d5300d3SRobert Mustacchi nvme_print_bit(6, "Non-Operational Power State Permissive Mode",
750*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
7518d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_nops, NULL, NULL);
7528d5300d3SRobert Mustacchi nvme_print_bit(6, "NVM Sets",
753*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7548d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_nvmset, NULL, NULL);
7558d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Levels",
756*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7578d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_rrl, NULL, NULL);
7588d5300d3SRobert Mustacchi nvme_print_bit(6, "Endurance Groups",
759*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7608d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_engrp, NULL, NULL);
7618d5300d3SRobert Mustacchi nvme_print_bit(6, "Predictable Latency Mode",
762*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7638d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_plm, NULL, NULL);
7648d5300d3SRobert Mustacchi nvme_print_bit(6, "Traffic Based Keep Alive",
765*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7668d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_tbkas, NULL, NULL);
7678d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace Granularity",
768*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7698d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_nsg, NULL, NULL);
7708d5300d3SRobert Mustacchi nvme_print_bit(6, "SQ Associations",
771*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7728d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_sqass, NULL, NULL);
7738d5300d3SRobert Mustacchi nvme_print_bit(6, "UUID List",
774*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7758d5300d3SRobert Mustacchi idctl->id_ctratt.ctrat_uuid, NULL, NULL);
7768d5300d3SRobert Mustacchi
7778d5300d3SRobert Mustacchi nvme_print(4, "Read Recovery Levels", -1,
7788d5300d3SRobert Mustacchi NULL);
7798d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 0",
780*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7818d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 0), NULL, NULL);
7828d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 1",
783*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7848d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 1), NULL, NULL);
7858d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 2",
786*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7878d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 2), NULL, NULL);
7888d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 3",
789*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7908d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 3), NULL, NULL);
7918d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 4 - Default",
792*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7938d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 4), NULL, NULL);
7948d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 5",
795*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7968d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 5), NULL, NULL);
7978d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 6",
798*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
7998d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 6), NULL, NULL);
8008d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 7",
801*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8028d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 7), NULL, NULL);
8038d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 8",
804*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8058d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 8), NULL, NULL);
8068d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 9",
807*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8088d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 9), NULL, NULL);
8098d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 10",
810*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8118d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 10), NULL, NULL);
8128d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 11",
813*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8148d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 11), NULL, NULL);
8158d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 12",
816*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8178d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 12), NULL, NULL);
8188d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 13",
819*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8208d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 13), NULL, NULL);
8218d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 14",
822*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8238d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 14), NULL, NULL);
8248d5300d3SRobert Mustacchi nvme_print_bit(6, "Read Recovery Level 15 - Fast Fail",
825*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
8268d5300d3SRobert Mustacchi idctl->id_rrls & (1 << 15), NULL, NULL);
8278d5300d3SRobert Mustacchi }
8288d5300d3SRobert Mustacchi
829*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v4)) {
8308d5300d3SRobert Mustacchi switch (idctl->id_cntrltype) {
8318d5300d3SRobert Mustacchi case NVME_CNTRLTYPE_RSVD:
8328d5300d3SRobert Mustacchi nvme_print_str(4, "Controller Type", -1,
8338d5300d3SRobert Mustacchi "not reported", 0);
8348d5300d3SRobert Mustacchi break;
8358d5300d3SRobert Mustacchi case NVME_CNTRLTYPE_IO:
8368d5300d3SRobert Mustacchi nvme_print_str(4, "Controller Type", -1, "I/O", 0);
8378d5300d3SRobert Mustacchi break;
8388d5300d3SRobert Mustacchi case NVME_CNTRLTYPE_DISC:
8398d5300d3SRobert Mustacchi nvme_print_str(4, "Controller Type", -1, "discovery",
8408d5300d3SRobert Mustacchi 0);
8418d5300d3SRobert Mustacchi break;
8428d5300d3SRobert Mustacchi case NVME_CNTRLTYPE_ADMIN:
8438d5300d3SRobert Mustacchi nvme_print_str(4, "Controller Type", -1,
8448d5300d3SRobert Mustacchi "administrative", 0);
8458d5300d3SRobert Mustacchi break;
8468d5300d3SRobert Mustacchi default:
8478d5300d3SRobert Mustacchi nvme_print(4, "Controller Type", -1,
8488d5300d3SRobert Mustacchi "unknown reserved value: %u", idctl->id_cntrltype);
8498d5300d3SRobert Mustacchi break;
8508d5300d3SRobert Mustacchi }
8518d5300d3SRobert Mustacchi } else {
8528d5300d3SRobert Mustacchi nvme_print_str(4, "Controller Type", -1, "not reported", 0);
8538d5300d3SRobert Mustacchi }
8548d5300d3SRobert Mustacchi
855*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v3)) {
8568d5300d3SRobert Mustacchi uint8_t zguid[16] = { 0 };
8578d5300d3SRobert Mustacchi
8588d5300d3SRobert Mustacchi if (memcmp(zguid, idctl->id_frguid, sizeof (zguid)) != 0) {
859153f3212SHans Rosenfeld nvme_print_guid(4, "FRU GUID", idctl->id_frguid);
8608d5300d3SRobert Mustacchi } else {
8618d5300d3SRobert Mustacchi nvme_print_str(4, "FRU GUID", -1, "unsupported", 0);
8628d5300d3SRobert Mustacchi }
8638d5300d3SRobert Mustacchi } else {
8648d5300d3SRobert Mustacchi nvme_print_str(4, "FRU GUID", -1, "unsupported", 0);
8658d5300d3SRobert Mustacchi }
8668d5300d3SRobert Mustacchi
867*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v4)) {
8688d5300d3SRobert Mustacchi nvme_print_uint64(4, "Command Retry Delay Time 1",
8698d5300d3SRobert Mustacchi idctl->id_crdt1 * 100, NULL, "ms");
8708d5300d3SRobert Mustacchi nvme_print_uint64(4, "Command Retry Delay Time 2",
8718d5300d3SRobert Mustacchi idctl->id_crdt2 * 100, NULL, "ms");
8728d5300d3SRobert Mustacchi nvme_print_uint64(4, "Command Retry Delay Time 3",
8738d5300d3SRobert Mustacchi idctl->id_crdt3 * 100, NULL, "ms");
8748d5300d3SRobert Mustacchi } else {
8758d5300d3SRobert Mustacchi nvme_print_str(4, "Command Retry Delay Time 1", -1,
8768d5300d3SRobert Mustacchi "unsupported", 0);
8778d5300d3SRobert Mustacchi nvme_print_str(4, "Command Retry Delay Time 2", -1,
8788d5300d3SRobert Mustacchi "unsupported", 0);
8798d5300d3SRobert Mustacchi nvme_print_str(4, "Command Retry Delay Time 3", -1,
8808d5300d3SRobert Mustacchi "unsupported", 0);
8818d5300d3SRobert Mustacchi }
8828d5300d3SRobert Mustacchi
8838d5300d3SRobert Mustacchi /*
8848d5300d3SRobert Mustacchi * The NVMe-MI spec claimed a portion of the identify controller data;
8858d5300d3SRobert Mustacchi * however, there's no way to actually figure out if this data is valid
8868d5300d3SRobert Mustacchi * or not. We basically have to rely on the NVMe spec's initialized to
8878d5300d3SRobert Mustacchi * zero behavior for this region. Unfortunately, there's no way to get
8888d5300d3SRobert Mustacchi * the NVMe-MI version to know when fields were added here so we
8898d5300d3SRobert Mustacchi * basically treat the minimum version required as that of when the
8908d5300d3SRobert Mustacchi * NVMe-MI region was reserved in the NVMe spec, which is 1.2. Note,
8918d5300d3SRobert Mustacchi * these bytes go in reverse order because they're allocating them in
8928d5300d3SRobert Mustacchi * reverse order.
8938d5300d3SRobert Mustacchi */
8948d5300d3SRobert Mustacchi if (verbose) {
8958d5300d3SRobert Mustacchi nvme_print(2, "NVMe Management Interface", -1, NULL);
8968d5300d3SRobert Mustacchi nvme_print(4, "Management Endpoint Capabilities", -1, NULL);
8978d5300d3SRobert Mustacchi nvme_print_bit(6, "SMBus/I2C Port Management Endpoint",
898*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
8998d5300d3SRobert Mustacchi idctl->id_mec.mec_smbusme, NULL, NULL);
9008d5300d3SRobert Mustacchi nvme_print_bit(6, "PCIe Port Management Endpoint",
901*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9028d5300d3SRobert Mustacchi idctl->id_mec.mec_pcieme, NULL, NULL);
9038d5300d3SRobert Mustacchi
9048d5300d3SRobert Mustacchi if (idctl->id_vpdwc.vwci_valid != 0) {
9058d5300d3SRobert Mustacchi nvme_print_uint64(4, "VPD Write Cycles Remaining",
9068d5300d3SRobert Mustacchi idctl->id_vpdwc.vwci_crem, NULL, NULL);
9078d5300d3SRobert Mustacchi } else {
9088d5300d3SRobert Mustacchi nvme_print_str(4, "VPD Write Cycles Remaining", -1,
9098d5300d3SRobert Mustacchi "invalid or unsupported", 0);
9108d5300d3SRobert Mustacchi }
9118d5300d3SRobert Mustacchi
9128d5300d3SRobert Mustacchi if (idctl->id_nvmsr.nvmsr_nvmesd == 0 &&
9138d5300d3SRobert Mustacchi idctl->id_nvmsr.nvmsr_nvmee == 0 &&
9148d5300d3SRobert Mustacchi idctl->id_nvmsr.nvmsr_rsvd == 0) {
9158d5300d3SRobert Mustacchi nvme_print_str(4, "NVM Subsystem Report", -1,
9168d5300d3SRobert Mustacchi "unsupported", 0);
9178d5300d3SRobert Mustacchi } else {
9188d5300d3SRobert Mustacchi nvme_print(4, "NVM Subsystem Report", -1, NULL);
9198d5300d3SRobert Mustacchi nvme_print_bit(6, "NVMe Storage Device",
920*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9218d5300d3SRobert Mustacchi idctl->id_nvmsr.nvmsr_nvmesd, NULL, NULL);
9228d5300d3SRobert Mustacchi nvme_print_bit(6, "NVMe Enclosure",
923*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9248d5300d3SRobert Mustacchi idctl->id_nvmsr.nvmsr_nvmee, NULL, NULL);
9258d5300d3SRobert Mustacchi }
9268d5300d3SRobert Mustacchi }
9278d5300d3SRobert Mustacchi
9283d9b1a2aSHans Rosenfeld nvme_print(2, "Admin Command Set Attributes", -1, NULL);
9293d9b1a2aSHans Rosenfeld nvme_print(4, "Optional Admin Command Support", -1, NULL);
9303d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Security Send & Receive",
931*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
9323d9b1a2aSHans Rosenfeld idctl->id_oacs.oa_security, NULL, NULL);
9333d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Format NVM",
934*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
9353d9b1a2aSHans Rosenfeld idctl->id_oacs.oa_format, NULL, NULL);
9363d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Firmware Activate & Download",
937*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
9383d9b1a2aSHans Rosenfeld idctl->id_oacs.oa_firmware, NULL, NULL);
9398d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace Management",
940*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9418d5300d3SRobert Mustacchi idctl->id_oacs.oa_nsmgmt, NULL, NULL);
9428d5300d3SRobert Mustacchi nvme_print_bit(6, "Device Self-test",
943*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9448d5300d3SRobert Mustacchi idctl->id_oacs.oa_selftest, NULL, NULL);
9458d5300d3SRobert Mustacchi nvme_print_bit(6, "Directives",
946*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9478d5300d3SRobert Mustacchi idctl->id_oacs.oa_direct, NULL, NULL);
9488d5300d3SRobert Mustacchi nvme_print_bit(6, "NVME-MI Send and Receive",
949*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9508d5300d3SRobert Mustacchi idctl->id_oacs.oa_nvmemi, NULL, NULL);
9518d5300d3SRobert Mustacchi nvme_print_bit(6, "Virtualization Management",
952*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9538d5300d3SRobert Mustacchi idctl->id_oacs.oa_virtmgmt, NULL, NULL);
9548d5300d3SRobert Mustacchi nvme_print_bit(6, "Doorbell Buffer Config",
955*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9568d5300d3SRobert Mustacchi idctl->id_oacs.oa_doorbell, NULL, NULL);
9578d5300d3SRobert Mustacchi nvme_print_bit(6, "Get LBA Status",
958*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
9598d5300d3SRobert Mustacchi idctl->id_oacs.oa_lbastat, NULL, NULL);
9603d9b1a2aSHans Rosenfeld if (verbose) {
9613d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Abort Command Limit",
9623d9b1a2aSHans Rosenfeld (uint16_t)idctl->id_acl + 1, NULL, NULL);
9633d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Asynchronous Event Request Limit",
9643d9b1a2aSHans Rosenfeld (uint16_t)idctl->id_aerl + 1, NULL, NULL);
9653d9b1a2aSHans Rosenfeld }
9663d9b1a2aSHans Rosenfeld nvme_print(4, "Firmware Updates", -1, NULL);
9673d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Firmware Slot 1",
968*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
9693d9b1a2aSHans Rosenfeld idctl->id_frmw.fw_readonly, "read-only", "writable");
9703d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "No. of Firmware Slots",
9713d9b1a2aSHans Rosenfeld idctl->id_frmw.fw_nslot, NULL, NULL);
9728d5300d3SRobert Mustacchi nvme_print_bit(6, "Activate Without Reset",
973*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9748d5300d3SRobert Mustacchi idctl->id_frmw.fw_norst, NULL, NULL);
9758d5300d3SRobert Mustacchi
9763d9b1a2aSHans Rosenfeld nvme_print(2, "Log Page Attributes", -1, NULL);
9778d5300d3SRobert Mustacchi nvme_print_bit(6, "Per Namespace SMART/Health info",
978*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
9793d9b1a2aSHans Rosenfeld idctl->id_lpa.lp_smart, NULL, NULL);
9808d5300d3SRobert Mustacchi nvme_print_bit(6, "Commands Supported and Effects",
981*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9828d5300d3SRobert Mustacchi idctl->id_lpa.lp_cmdeff, NULL, NULL);
9838d5300d3SRobert Mustacchi nvme_print_bit(6, "Get Log Page Extended Data",
984*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
9858d5300d3SRobert Mustacchi idctl->id_lpa.lp_extsup, NULL, NULL);
9868d5300d3SRobert Mustacchi nvme_print_bit(6, "Telemetry Log Pages",
987*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
9888d5300d3SRobert Mustacchi idctl->id_lpa.lp_telemetry, NULL, NULL);
9898d5300d3SRobert Mustacchi nvme_print_bit(6, "Persistent Event Log",
990*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
9918d5300d3SRobert Mustacchi idctl->id_lpa.lp_persist, NULL, NULL);
9928d5300d3SRobert Mustacchi
9933d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Error Log Page Entries",
9943d9b1a2aSHans Rosenfeld (uint16_t)idctl->id_elpe + 1, NULL, NULL);
9953d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of Power States",
9963d9b1a2aSHans Rosenfeld (uint16_t)idctl->id_npss + 1, NULL, NULL);
9973d9b1a2aSHans Rosenfeld if (verbose) {
9983d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Admin Vendor-specific Command Format",
999*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
10003d9b1a2aSHans Rosenfeld idctl->id_avscc.av_spec, "standard", "vendor-specific");
10013d9b1a2aSHans Rosenfeld }
10023d9b1a2aSHans Rosenfeld
10038d5300d3SRobert Mustacchi nvme_print_bit(4, "Autonomous Power State Transitions",
1004*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
10058d5300d3SRobert Mustacchi idctl->id_apsta.ap_sup, NULL, NULL);
10068d5300d3SRobert Mustacchi
1007*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v2)) {
10088d5300d3SRobert Mustacchi nvme_print_temp(4, "Warning Composite Temperature Threshold",
10098d5300d3SRobert Mustacchi idctl->ap_wctemp);
10108d5300d3SRobert Mustacchi nvme_print_temp(4, "Critical Composite Temperature Threshold",
10118d5300d3SRobert Mustacchi idctl->ap_cctemp);
10128d5300d3SRobert Mustacchi } else {
10138d5300d3SRobert Mustacchi nvme_print_str(4, "Warning Composite Temperature Threshold",
10148d5300d3SRobert Mustacchi -1, "unspecified", 0);
10158d5300d3SRobert Mustacchi nvme_print_str(4, "Critical Composite Temperature Threshold",
10168d5300d3SRobert Mustacchi -1, "unspecified", 0);
10178d5300d3SRobert Mustacchi }
10188d5300d3SRobert Mustacchi
10198d5300d3SRobert Mustacchi if (verbose) {
10208d5300d3SRobert Mustacchi if (idctl->ap_mtfa != 0) {
10218d5300d3SRobert Mustacchi nvme_print_uint64(4, "Maximum Firmware Activation Time",
10228d5300d3SRobert Mustacchi idctl->ap_mtfa * 100, NULL, "ms");
10238d5300d3SRobert Mustacchi } else {
10248d5300d3SRobert Mustacchi nvme_print_str(4, "Maximum Firmware Activation Time",
10258d5300d3SRobert Mustacchi -1, "unknown", 0);
10268d5300d3SRobert Mustacchi }
10278d5300d3SRobert Mustacchi
10288d5300d3SRobert Mustacchi if (idctl->ap_hmpre != 0) {
10298d5300d3SRobert Mustacchi nvme_print_uint64(4, "Host Memory Buffer Preferred "
10308d5300d3SRobert Mustacchi "Size", idctl->ap_hmpre * 4, NULL, "KiB");
10318d5300d3SRobert Mustacchi } else {
10328d5300d3SRobert Mustacchi nvme_print_str(4, "Host Memory Buffer Preferred "
10338d5300d3SRobert Mustacchi "Size", -1, "unsupported", 0);
10348d5300d3SRobert Mustacchi }
10358d5300d3SRobert Mustacchi
10368d5300d3SRobert Mustacchi if (idctl->ap_hmmin != 0) {
10378d5300d3SRobert Mustacchi nvme_print_uint64(4, "Host Memory Buffer Minimum Size",
10388d5300d3SRobert Mustacchi idctl->ap_hmmin * 4, NULL, "KiB");
10398d5300d3SRobert Mustacchi } else {
10408d5300d3SRobert Mustacchi nvme_print_str(4, "Host Memory Buffer Minimum Size",
10418d5300d3SRobert Mustacchi -1, "unsupported", 0);
10428d5300d3SRobert Mustacchi }
1043153f3212SHans Rosenfeld }
10448d5300d3SRobert Mustacchi
1045153f3212SHans Rosenfeld if (idctl->id_oacs.oa_nsmgmt != 0) {
1046153f3212SHans Rosenfeld nvme_print_uint128(4, "Total NVM Capacity",
1047153f3212SHans Rosenfeld idctl->ap_tnvmcap, "B", 0, 0);
1048153f3212SHans Rosenfeld nvme_print_uint128(4, "Unallocated NVM Capacity",
1049153f3212SHans Rosenfeld idctl->ap_unvmcap, "B", 0, 0);
1050153f3212SHans Rosenfeld } else if (verbose) {
1051153f3212SHans Rosenfeld nvme_print_str(4, "Total NVM Capacity", -1,
1052153f3212SHans Rosenfeld "unsupported", 0);
1053153f3212SHans Rosenfeld nvme_print_str(4, "Unallocated NVM Capacity", -1,
1054153f3212SHans Rosenfeld "unsupported", 0);
1055153f3212SHans Rosenfeld }
10568d5300d3SRobert Mustacchi
1057153f3212SHans Rosenfeld if (verbose) {
10588d5300d3SRobert Mustacchi if (idctl->ap_rpmbs.rpmbs_units != 0) {
10598d5300d3SRobert Mustacchi nvme_print(4, "Replay Protected Memory Block", -1,
10608d5300d3SRobert Mustacchi NULL);
10618d5300d3SRobert Mustacchi nvme_print_uint64(6, "Number of RPMB Units",
10628d5300d3SRobert Mustacchi idctl->ap_rpmbs.rpmbs_units, NULL, NULL);
10638d5300d3SRobert Mustacchi switch (idctl->ap_rpmbs.rpmbs_auth) {
10648d5300d3SRobert Mustacchi case NVME_RPMBS_AUTH_HMAC_SHA256:
10658d5300d3SRobert Mustacchi nvme_print_str(6, "Authentication Method", -1,
10668d5300d3SRobert Mustacchi "HMAC SHA-256", 0);
10678d5300d3SRobert Mustacchi break;
10688d5300d3SRobert Mustacchi default:
10698d5300d3SRobert Mustacchi nvme_print(6, "Authentication Method", -1,
10708d5300d3SRobert Mustacchi "unknown reserved value: %u",
10718d5300d3SRobert Mustacchi idctl->ap_rpmbs.rpmbs_auth);
10728d5300d3SRobert Mustacchi break;
10738d5300d3SRobert Mustacchi }
10748d5300d3SRobert Mustacchi nvme_print_uint64(6, "Total Size",
10758d5300d3SRobert Mustacchi (idctl->ap_rpmbs.rpmbs_tot + 1) * 128, NULL, "KiB");
10768d5300d3SRobert Mustacchi nvme_print_uint64(6, "Access Size",
10778d5300d3SRobert Mustacchi (idctl->ap_rpmbs.rpmbs_acc + 1) * 512, NULL, "KiB");
10788d5300d3SRobert Mustacchi } else {
10798d5300d3SRobert Mustacchi nvme_print_str(4, "Replay Protected Memory Block", -1,
10808d5300d3SRobert Mustacchi "unsupported", 0);
10818d5300d3SRobert Mustacchi }
10828d5300d3SRobert Mustacchi
10838d5300d3SRobert Mustacchi if (idctl->id_oacs.oa_selftest != 0) {
10848d5300d3SRobert Mustacchi nvme_print_uint64(4, "Extended Device Self-test Time",
10858d5300d3SRobert Mustacchi idctl->ap_edstt, NULL, "min");
10868d5300d3SRobert Mustacchi nvme_print(4, "Device Self-test Options", -1, NULL);
10878d5300d3SRobert Mustacchi nvme_print_bit(6, "Self-test operation granularity",
1088*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
10898d5300d3SRobert Mustacchi idctl->ap_dsto.dsto_sub, "subsystem", "controller");
10908d5300d3SRobert Mustacchi } else {
10918d5300d3SRobert Mustacchi nvme_print_str(4, "Extended Device Self-test Time", -1,
10928d5300d3SRobert Mustacchi "unsupported", 0);
10938d5300d3SRobert Mustacchi nvme_print_str(4, "Device Self-test Options", -1,
10948d5300d3SRobert Mustacchi "unsupported", 0);
10958d5300d3SRobert Mustacchi }
10968d5300d3SRobert Mustacchi }
10978d5300d3SRobert Mustacchi
10988d5300d3SRobert Mustacchi switch (idctl->ap_fwug) {
10998d5300d3SRobert Mustacchi case 0x00:
11008d5300d3SRobert Mustacchi nvme_print_str(4, "Firmware Update Granularity", -1, "unknown",
11018d5300d3SRobert Mustacchi 0);
11028d5300d3SRobert Mustacchi break;
11038d5300d3SRobert Mustacchi case 0xff:
11048d5300d3SRobert Mustacchi nvme_print_str(4, "Firmware Update Granularity", -1,
11058d5300d3SRobert Mustacchi "unrestricted", 0);
11068d5300d3SRobert Mustacchi break;
11078d5300d3SRobert Mustacchi default:
11088d5300d3SRobert Mustacchi nvme_print_uint64(4, "Firmware Update Granularity",
11098d5300d3SRobert Mustacchi idctl->ap_fwug * 4, NULL, "KiB");
11108d5300d3SRobert Mustacchi break;
11118d5300d3SRobert Mustacchi }
11128d5300d3SRobert Mustacchi
11138d5300d3SRobert Mustacchi if (verbose) {
11148d5300d3SRobert Mustacchi if (idctl->ap_kas != 0) {
11158d5300d3SRobert Mustacchi nvme_print_uint64(4, "Keep Alive Support",
11168d5300d3SRobert Mustacchi idctl->ap_kas * 100, NULL, "ms");
11178d5300d3SRobert Mustacchi } else {
11188d5300d3SRobert Mustacchi nvme_print_str(4, "Keep Alive Support", -1,
11198d5300d3SRobert Mustacchi "unsupported", 0);
11208d5300d3SRobert Mustacchi }
11218d5300d3SRobert Mustacchi
11228d5300d3SRobert Mustacchi nvme_print(4, "Host Controlled Thermal Management Attributes",
11238d5300d3SRobert Mustacchi -1, NULL);
11248d5300d3SRobert Mustacchi nvme_print_bit(6, "Host Controlled Thermal Management",
1125*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
11268d5300d3SRobert Mustacchi idctl->ap_hctma.hctma_hctm, NULL, NULL);
1127*533affcbSRobert Mustacchi if (idctl->ap_mntmt != 0 && nvme_vers_atleast(version,
1128*533affcbSRobert Mustacchi &nvme_vers_1v3)) {
11298d5300d3SRobert Mustacchi nvme_print_temp(6, "Minimum Thermal Management "
11308d5300d3SRobert Mustacchi "Temperature", idctl->ap_mntmt);
11318d5300d3SRobert Mustacchi } else {
11328d5300d3SRobert Mustacchi nvme_print_str(6, "Minimum Thermal Management "
11338d5300d3SRobert Mustacchi "Temperature", -1, "unsupported", -1);
11348d5300d3SRobert Mustacchi }
11358d5300d3SRobert Mustacchi
1136*533affcbSRobert Mustacchi if (idctl->ap_mxtmt != 0 && nvme_vers_atleast(version,
1137*533affcbSRobert Mustacchi &nvme_vers_1v3)) {
11388d5300d3SRobert Mustacchi nvme_print_temp(6, "Maximum Thermal Management "
11398d5300d3SRobert Mustacchi "Temperature", idctl->ap_mxtmt);
11408d5300d3SRobert Mustacchi } else {
11418d5300d3SRobert Mustacchi nvme_print_str(6, "Maximum Thermal Management "
11428d5300d3SRobert Mustacchi "Temperature", -1, "unsupported", -1);
11438d5300d3SRobert Mustacchi }
11448d5300d3SRobert Mustacchi
11458d5300d3SRobert Mustacchi nvme_print(4, "Sanitize Capabilities", -1, NULL);
11468d5300d3SRobert Mustacchi nvme_print_bit(6, "Crypto Erase Support",
1147*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
11488d5300d3SRobert Mustacchi idctl->ap_sanitize.san_ces, NULL, NULL);
11498d5300d3SRobert Mustacchi nvme_print_bit(6, "Block Erase Support",
1150*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
11518d5300d3SRobert Mustacchi idctl->ap_sanitize.san_bes, NULL, NULL);
11528d5300d3SRobert Mustacchi nvme_print_bit(6, "Overwrite Support",
1153*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
11548d5300d3SRobert Mustacchi idctl->ap_sanitize.san_ows, NULL, NULL);
11558d5300d3SRobert Mustacchi nvme_print_bit(6, "No-Deallocate Inhibited",
1156*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
11578d5300d3SRobert Mustacchi idctl->ap_sanitize.san_ndi, NULL, NULL);
1158*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v4)) {
11598d5300d3SRobert Mustacchi uint_t val = idctl->ap_sanitize.san_nodmmas;
11608d5300d3SRobert Mustacchi switch (val) {
11618d5300d3SRobert Mustacchi case NVME_NODMMAS_UNDEF:
11628d5300d3SRobert Mustacchi nvme_print_str(6, "No-Deallocate Modifies "
11638d5300d3SRobert Mustacchi "Media after Sanitize", -1,
11648d5300d3SRobert Mustacchi "undefined", 0);
11658d5300d3SRobert Mustacchi break;
11668d5300d3SRobert Mustacchi case NVME_NODMMAS_NOMOD:
11678d5300d3SRobert Mustacchi nvme_print_str(6, "No-Deallocate Modifies "
11688d5300d3SRobert Mustacchi "Media after Sanitize", -1,
11698d5300d3SRobert Mustacchi "no modification", 0);
11708d5300d3SRobert Mustacchi break;
11718d5300d3SRobert Mustacchi case NVME_NODMMAS_DOMOD:
11728d5300d3SRobert Mustacchi nvme_print_str(6, "No-Deallocate Modifies "
11738d5300d3SRobert Mustacchi "Media after Sanitize", -1,
11748d5300d3SRobert Mustacchi "modification required", 0);
11758d5300d3SRobert Mustacchi break;
11768d5300d3SRobert Mustacchi default:
11778d5300d3SRobert Mustacchi nvme_print(6, "No-Deallocate Modifies "
11788d5300d3SRobert Mustacchi "Media after Sanitize", -1,
11798d5300d3SRobert Mustacchi "unknown reserved value: %u", val);
11808d5300d3SRobert Mustacchi break;
11818d5300d3SRobert Mustacchi }
11828d5300d3SRobert Mustacchi } else {
11838d5300d3SRobert Mustacchi nvme_print_str(6, "No-Deallocate Modifies Media after "
11848d5300d3SRobert Mustacchi "Sanitize", -1, "undefined", 0);
11858d5300d3SRobert Mustacchi }
11868d5300d3SRobert Mustacchi
11878d5300d3SRobert Mustacchi if (idctl->ap_hmminds != 0) {
11888d5300d3SRobert Mustacchi nvme_print_uint64(4, "Host Memory Buffer Minimum "
11898d5300d3SRobert Mustacchi "Descriptor Entry Size", idctl->ap_hmminds * 4,
11908d5300d3SRobert Mustacchi NULL, "KiB");
11918d5300d3SRobert Mustacchi } else {
11928d5300d3SRobert Mustacchi nvme_print_str(4, "Host Memory Buffer Minimum "
11938d5300d3SRobert Mustacchi "Descriptor Entry Size", -1, "unsupported", 0);
11948d5300d3SRobert Mustacchi }
11958d5300d3SRobert Mustacchi
11968d5300d3SRobert Mustacchi if (idctl->ap_hmmaxd != 0) {
11978d5300d3SRobert Mustacchi nvme_print_uint64(4, "Host Memory Buffer Maximum "
11988d5300d3SRobert Mustacchi "Descriptor Entries", idctl->ap_hmmaxd,
11998d5300d3SRobert Mustacchi NULL, NULL);
12008d5300d3SRobert Mustacchi } else {
12018d5300d3SRobert Mustacchi nvme_print_str(4, "Host Memory Buffer Maximum "
12028d5300d3SRobert Mustacchi "Descriptor Entries", -1, "unsupported", 0);
12038d5300d3SRobert Mustacchi }
12048d5300d3SRobert Mustacchi
12058d5300d3SRobert Mustacchi if (idctl->id_ctratt.ctrat_engrp != 0) {
12068d5300d3SRobert Mustacchi nvme_print_uint64(4, "Max Endurance Group Identifier",
12078d5300d3SRobert Mustacchi idctl->ap_engidmax, NULL, NULL);
12088d5300d3SRobert Mustacchi } else {
12098d5300d3SRobert Mustacchi nvme_print_str(4, "Max Endurance Group Identifier",
12108d5300d3SRobert Mustacchi -1, "unsupported", 0);
12118d5300d3SRobert Mustacchi }
12128d5300d3SRobert Mustacchi
12138d5300d3SRobert Mustacchi if (idctl->id_mic.m_anar_sup != 0) {
12148d5300d3SRobert Mustacchi nvme_print_uint64(4, "ANA Transition Time",
12158d5300d3SRobert Mustacchi idctl->ap_anatt, NULL, "secs");
12168d5300d3SRobert Mustacchi } else {
12178d5300d3SRobert Mustacchi nvme_print_str(4, "ANA Transition Time", -1,
12188d5300d3SRobert Mustacchi "unsupported", 0);
12198d5300d3SRobert Mustacchi }
12208d5300d3SRobert Mustacchi
12218d5300d3SRobert Mustacchi nvme_print(4, "Asymmetric Namespace Access Capabilities",
12228d5300d3SRobert Mustacchi -1, NULL);
12238d5300d3SRobert Mustacchi nvme_print_bit(6, "ANA Optimized state",
1224*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12258d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_opt, NULL, NULL);
12268d5300d3SRobert Mustacchi nvme_print_bit(6, "ANA Non-Optimized state",
1227*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12288d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_unopt, NULL, NULL);
12298d5300d3SRobert Mustacchi nvme_print_bit(6, "ANA Inaccessible state",
1230*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12318d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_inacc, NULL, NULL);
12328d5300d3SRobert Mustacchi nvme_print_bit(6, "ANA Persistent Loss state",
1233*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12348d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_ploss, NULL, NULL);
12358d5300d3SRobert Mustacchi nvme_print_bit(6, "ANA Persistent Change state",
1236*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12378d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_chg, NULL, NULL);
12388d5300d3SRobert Mustacchi nvme_print_bit(6, "ANAGRPID doesn't change with attached NS",
1239*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12408d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_grpns, "yes", "no");
12418d5300d3SRobert Mustacchi nvme_print_bit(6, "Non-zero ANAGRPID in Namespace Management",
1242*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
12438d5300d3SRobert Mustacchi idctl->ap_anacap.anacap_grpid, NULL, NULL);
12448d5300d3SRobert Mustacchi
12458d5300d3SRobert Mustacchi if (idctl->id_mic.m_anar_sup != 0) {
12468d5300d3SRobert Mustacchi nvme_print_uint64(4, "Max ANA Group Identifier",
12478d5300d3SRobert Mustacchi idctl->ap_anagrpmax, NULL, NULL);
12488d5300d3SRobert Mustacchi nvme_print_uint64(4, "Number of ANA Group Identifiers",
12498d5300d3SRobert Mustacchi idctl->ap_nanagrpid, NULL, NULL);
12508d5300d3SRobert Mustacchi } else {
12518d5300d3SRobert Mustacchi nvme_print_str(4, "Max ANA Group Identifier",
12528d5300d3SRobert Mustacchi -1, "unsupported", 0);
12538d5300d3SRobert Mustacchi nvme_print_str(4, "Number of ANA Group Identifiers",
12548d5300d3SRobert Mustacchi -1, "unsupported", 0);
12558d5300d3SRobert Mustacchi }
12568d5300d3SRobert Mustacchi
12578d5300d3SRobert Mustacchi if (idctl->id_lpa.lp_persist != 0) {
12588d5300d3SRobert Mustacchi nvme_print_uint64(4, "Persistent Event Log Size",
12598d5300d3SRobert Mustacchi idctl->ap_pels * 64, NULL, "KiB");
12608d5300d3SRobert Mustacchi } else {
12618d5300d3SRobert Mustacchi nvme_print_str(4, "Persistent Event Log Size",
12628d5300d3SRobert Mustacchi -1, "unsupported", 0);
12638d5300d3SRobert Mustacchi }
12643d9b1a2aSHans Rosenfeld }
12653d9b1a2aSHans Rosenfeld
12668d5300d3SRobert Mustacchi
12673d9b1a2aSHans Rosenfeld nvme_print(2, "NVM Command Set Attributes", -1, NULL);
12683d9b1a2aSHans Rosenfeld if (verbose) {
12693d9b1a2aSHans Rosenfeld nvme_print(4, "Submission Queue Entry Size", -1,
12703d9b1a2aSHans Rosenfeld "min %d, max %d",
12713d9b1a2aSHans Rosenfeld 1 << idctl->id_sqes.qes_min, 1 << idctl->id_sqes.qes_max);
12723d9b1a2aSHans Rosenfeld nvme_print(4, "Completion Queue Entry Size", -1,
12733d9b1a2aSHans Rosenfeld "min %d, max %d",
12743d9b1a2aSHans Rosenfeld 1 << idctl->id_cqes.qes_min, 1 << idctl->id_cqes.qes_max);
12758d5300d3SRobert Mustacchi
1276*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v2)) {
12778d5300d3SRobert Mustacchi nvme_print_uint64(4, "Maximum Outstanding Commands",
12788d5300d3SRobert Mustacchi idctl->id_maxcmd, NULL, NULL);
12798d5300d3SRobert Mustacchi } else {
12808d5300d3SRobert Mustacchi nvme_print_str(4, "Maximum Outstanding Commands",
12818d5300d3SRobert Mustacchi -1, "unknown", 0);
12828d5300d3SRobert Mustacchi }
12833d9b1a2aSHans Rosenfeld }
12843d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of Namespaces",
12853d9b1a2aSHans Rosenfeld idctl->id_nn, NULL, NULL);
12863d9b1a2aSHans Rosenfeld nvme_print(4, "Optional NVM Command Support", -1, NULL);
12873d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Compare",
1288*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
12893d9b1a2aSHans Rosenfeld idctl->id_oncs.on_compare, NULL, NULL);
12903d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Write Uncorrectable",
1291*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
12923d9b1a2aSHans Rosenfeld idctl->id_oncs.on_wr_unc, NULL, NULL);
12933d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Dataset Management",
1294*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
12953d9b1a2aSHans Rosenfeld idctl->id_oncs.on_dset_mgmt, NULL, NULL);
12968d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Zeros",
1297*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
12988d5300d3SRobert Mustacchi idctl->id_oncs.on_wr_zero, NULL, NULL);
12998d5300d3SRobert Mustacchi nvme_print_bit(6, "Save/Select in Get/Set Features",
1300*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
13018d5300d3SRobert Mustacchi idctl->id_oncs.on_save, NULL, NULL);
13028d5300d3SRobert Mustacchi nvme_print_bit(6, "Reservations",
1303*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
13048d5300d3SRobert Mustacchi idctl->id_oncs.on_reserve, NULL, NULL);
13058d5300d3SRobert Mustacchi nvme_print_bit(6, "Timestamp Feature",
1306*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
13078d5300d3SRobert Mustacchi idctl->id_oncs.on_ts, NULL, NULL);
13088d5300d3SRobert Mustacchi nvme_print_bit(6, "Verify",
1309*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
13108d5300d3SRobert Mustacchi idctl->id_oncs.on_verify, NULL, NULL);
13113d9b1a2aSHans Rosenfeld
13123d9b1a2aSHans Rosenfeld nvme_print(4, "Fused Operation Support", -1, NULL);
13133d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Compare and Write",
1314*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13153d9b1a2aSHans Rosenfeld idctl->id_fuses.f_cmp_wr, NULL, NULL);
13163d9b1a2aSHans Rosenfeld nvme_print(4, "Format NVM Attributes", -1, NULL);
13178d5300d3SRobert Mustacchi nvme_print_bit(6, "Per Namespace Format",
1318*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13193d9b1a2aSHans Rosenfeld idctl->id_fna.fn_format == 0, NULL, NULL);
13208d5300d3SRobert Mustacchi nvme_print_bit(6, "Per Namespace Secure Erase",
1321*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13223d9b1a2aSHans Rosenfeld idctl->id_fna.fn_sec_erase == 0, NULL, NULL);
13233d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Cryptographic Erase",
1324*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13253d9b1a2aSHans Rosenfeld idctl->id_fna.fn_crypt_erase, NULL, NULL);
13268d5300d3SRobert Mustacchi nvme_print(4, "Volatile Write Cache", -1, NULL);
13278d5300d3SRobert Mustacchi nvme_print_bit(6, "Present",
1328*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13298d5300d3SRobert Mustacchi idctl->id_vwc.vwc_present, "yes", "no");
13308d5300d3SRobert Mustacchi if (verbose) {
13318d5300d3SRobert Mustacchi switch (idctl->id_vwc.vwc_nsflush) {
13328d5300d3SRobert Mustacchi case NVME_VWCNS_UNKNOWN:
13338d5300d3SRobert Mustacchi nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
13348d5300d3SRobert Mustacchi -1, "unknown", 0);
13358d5300d3SRobert Mustacchi break;
13368d5300d3SRobert Mustacchi case NVME_VWCNS_UNSUP:
13378d5300d3SRobert Mustacchi nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
13388d5300d3SRobert Mustacchi -1, "unsupported", 0);
13398d5300d3SRobert Mustacchi break;
13408d5300d3SRobert Mustacchi case NVME_VWCNS_SUP:
13418d5300d3SRobert Mustacchi nvme_print_str(6, "Flush with NSID 0xFFFFFFFF",
13428d5300d3SRobert Mustacchi -1, "supported", 0);
13438d5300d3SRobert Mustacchi break;
13448d5300d3SRobert Mustacchi default:
13458d5300d3SRobert Mustacchi nvme_print(6, "Flush with NSID 0xFFFFFFFF",
13468d5300d3SRobert Mustacchi -1, "unknown reserved value: %u",
13478d5300d3SRobert Mustacchi idctl->id_vwc.vwc_nsflush);
13488d5300d3SRobert Mustacchi break;
13498d5300d3SRobert Mustacchi }
13508d5300d3SRobert Mustacchi }
13513d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Atomic Write Unit Normal",
13523d9b1a2aSHans Rosenfeld (uint32_t)idctl->id_awun + 1, NULL,
13533d9b1a2aSHans Rosenfeld idctl->id_awun == 0 ? " block" : " blocks");
13543d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Atomic Write Unit Power Fail",
13553d9b1a2aSHans Rosenfeld (uint32_t)idctl->id_awupf + 1, NULL,
13563d9b1a2aSHans Rosenfeld idctl->id_awupf == 0 ? " block" : " blocks");
13573d9b1a2aSHans Rosenfeld
13588d5300d3SRobert Mustacchi if (verbose != 0) {
13593d9b1a2aSHans Rosenfeld nvme_print_bit(4, "NVM Vendor-specific Command Format",
1360*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
13613d9b1a2aSHans Rosenfeld idctl->id_nvscc.nv_spec, "standard", "vendor-specific");
13623d9b1a2aSHans Rosenfeld
13638d5300d3SRobert Mustacchi nvme_print(4, "Namespace Write Protection Capabilities",
13648d5300d3SRobert Mustacchi -1, NULL);
13658d5300d3SRobert Mustacchi nvme_print_bit(6, "Core Support",
1366*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
13678d5300d3SRobert Mustacchi idctl->id_nwpc.nwpc_base, NULL, NULL);
13688d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Protect Until Power Cycle",
1369*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
13708d5300d3SRobert Mustacchi idctl->id_nwpc.nwpc_wpupc, NULL, NULL);
13718d5300d3SRobert Mustacchi nvme_print_bit(6, "Permanent Write Protect",
1372*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
13738d5300d3SRobert Mustacchi idctl->id_nwpc.nwpc_permwp, NULL, NULL);
13748d5300d3SRobert Mustacchi }
13758d5300d3SRobert Mustacchi
1376*533affcbSRobert Mustacchi if (idctl->id_fuses.f_cmp_wr && nvme_vers_atleast(version,
1377*533affcbSRobert Mustacchi &nvme_vers_1v1)) {
13783d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Atomic Compare & Write Size",
13793d9b1a2aSHans Rosenfeld (uint32_t)idctl->id_acwu + 1, NULL,
13803d9b1a2aSHans Rosenfeld idctl->id_acwu == 0 ? " block" : " blocks");
13818d5300d3SRobert Mustacchi } else {
13828d5300d3SRobert Mustacchi nvme_print_str(4, "Atomic Compare & Write Size", -1,
13838d5300d3SRobert Mustacchi "unsupported", 0);
13848d5300d3SRobert Mustacchi }
13858d5300d3SRobert Mustacchi
13868d5300d3SRobert Mustacchi nvme_print(4, "SGL Support", -1, NULL);
13878d5300d3SRobert Mustacchi switch (idctl->id_sgls.sgl_sup) {
13888d5300d3SRobert Mustacchi case NVME_SGL_UNSUP:
13898d5300d3SRobert Mustacchi nvme_print_str(6, "Command Set", -1, "unsupported", 0);
13908d5300d3SRobert Mustacchi break;
13918d5300d3SRobert Mustacchi case NVME_SGL_SUP_UNALIGN:
13928d5300d3SRobert Mustacchi nvme_print_str(6, "Command Set", -1, "supported, "
13938d5300d3SRobert Mustacchi "no restrictions", 0);
13948d5300d3SRobert Mustacchi break;
13958d5300d3SRobert Mustacchi case NVME_SGL_SUP_ALIGN:
13968d5300d3SRobert Mustacchi nvme_print_str(6, "Command Set", -1, "supported, "
13978d5300d3SRobert Mustacchi "alignment restrictions", 0);
13988d5300d3SRobert Mustacchi break;
13998d5300d3SRobert Mustacchi default:
14008d5300d3SRobert Mustacchi nvme_print(6, "Command Set", -1, "unknown reserved value: %u",
14018d5300d3SRobert Mustacchi idctl->id_sgls.sgl_sup);
14028d5300d3SRobert Mustacchi break;
14038d5300d3SRobert Mustacchi }
14048d5300d3SRobert Mustacchi nvme_print_bit(6, "Keyed SGL Block Descriptor",
1405*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
14068d5300d3SRobert Mustacchi idctl->id_sgls.sgl_keyed, NULL, NULL);
14078d5300d3SRobert Mustacchi nvme_print_bit(6, "SGL Bit Bucket Descriptor",
1408*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
14098d5300d3SRobert Mustacchi idctl->id_sgls.sgl_bucket, NULL, NULL);
14108d5300d3SRobert Mustacchi nvme_print_bit(6, "Byte Aligned Contiguous Metadata",
1411*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
14128d5300d3SRobert Mustacchi idctl->id_sgls.sgl_balign, NULL, NULL);
14138d5300d3SRobert Mustacchi nvme_print_bit(6, "SGL Longer than Data Transferred",
1414*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
14158d5300d3SRobert Mustacchi idctl->id_sgls.sgl_sglgtd, NULL, NULL);
14168d5300d3SRobert Mustacchi nvme_print_bit(6, "MPTR with SGL",
1417*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
14188d5300d3SRobert Mustacchi idctl->id_sgls.sgl_mptr, NULL, NULL);
14198d5300d3SRobert Mustacchi nvme_print_bit(6, "SGL Address as Offset",
1420*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
14218d5300d3SRobert Mustacchi idctl->id_sgls.sgl_offset, NULL, NULL);
14228d5300d3SRobert Mustacchi nvme_print_bit(6, "Transport SGL Data Block",
1423*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
14248d5300d3SRobert Mustacchi idctl->id_sgls.sgl_tport, NULL, NULL);
14258d5300d3SRobert Mustacchi if (verbose) {
142698f586d7SAndy Fiddaman if (idctl->id_mnan != 0) {
14278d5300d3SRobert Mustacchi nvme_print_uint64(4, "Maximum Number of Allowed "
142898f586d7SAndy Fiddaman "Namespaces", idctl->id_mnan, NULL, NULL);
14298d5300d3SRobert Mustacchi } else {
14308d5300d3SRobert Mustacchi nvme_print(4, "Maximum Number of Allowed "
14318d5300d3SRobert Mustacchi "Namespaces", -1, "at most %u", idctl->id_nn);
14328d5300d3SRobert Mustacchi }
14338d5300d3SRobert Mustacchi }
14348d5300d3SRobert Mustacchi
1435*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v2) &&
1436*533affcbSRobert Mustacchi idctl->id_subnqn[0] != '\0') {
14378d5300d3SRobert Mustacchi nvme_print_str(4, "NVMe Subsystem Qualified Name", -1,
14388d5300d3SRobert Mustacchi (char *)idctl->id_subnqn, sizeof (idctl->id_subnqn));
14398d5300d3SRobert Mustacchi } else {
14408d5300d3SRobert Mustacchi nvme_print_str(4, "NVMe Subsystem Qualified Name", -1,
14418d5300d3SRobert Mustacchi "unknown", 0);
14423d9b1a2aSHans Rosenfeld }
14433d9b1a2aSHans Rosenfeld
14443d9b1a2aSHans Rosenfeld for (i = 0; i != idctl->id_npss + 1; i++) {
14453d9b1a2aSHans Rosenfeld double scale = 0.01;
14463d9b1a2aSHans Rosenfeld double power = 0;
14473d9b1a2aSHans Rosenfeld int places = 2;
14483d9b1a2aSHans Rosenfeld char *unit = "W";
14493d9b1a2aSHans Rosenfeld
1450*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v1) &&
14513d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_mps == 1) {
14523d9b1a2aSHans Rosenfeld scale = 0.0001;
14533d9b1a2aSHans Rosenfeld places = 4;
14543d9b1a2aSHans Rosenfeld }
14553d9b1a2aSHans Rosenfeld
14563d9b1a2aSHans Rosenfeld power = (double)idctl->id_psd[i].psd_mp * scale;
14573d9b1a2aSHans Rosenfeld if (power < 1.0) {
14583d9b1a2aSHans Rosenfeld power *= 1000.0;
14593d9b1a2aSHans Rosenfeld unit = "mW";
14603d9b1a2aSHans Rosenfeld }
14613d9b1a2aSHans Rosenfeld
14623d9b1a2aSHans Rosenfeld nvme_print(4, "Power State Descriptor", i, NULL);
14633d9b1a2aSHans Rosenfeld nvme_print_double(6, "Maximum Power", power, places, unit);
14643d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Non-Operational State",
1465*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
14663d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_nops, "yes", "no");
14673d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Entry Latency",
14683d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_enlat, NULL, "us");
14693d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Exit Latency",
14703d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_exlat, NULL, "us");
14713d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Relative Read Throughput (0 = best)",
14723d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_rrt, NULL, NULL);
14733d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Relative Read Latency (0 = best)",
14743d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_rrl, NULL, NULL);
14753d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Relative Write Throughput (0 = best)",
14763d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_rwt, NULL, NULL);
14773d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Relative Write Latency (0 = best)",
14783d9b1a2aSHans Rosenfeld idctl->id_psd[i].psd_rwl, NULL, NULL);
14793d9b1a2aSHans Rosenfeld }
14803d9b1a2aSHans Rosenfeld }
14813d9b1a2aSHans Rosenfeld
14823d9b1a2aSHans Rosenfeld /*
14833d9b1a2aSHans Rosenfeld * nvme_print_identify_nsid
14843d9b1a2aSHans Rosenfeld *
14853d9b1a2aSHans Rosenfeld * This function pretty-prints the structure returned by the IDENTIFY NAMESPACE
14863d9b1a2aSHans Rosenfeld * command.
14873d9b1a2aSHans Rosenfeld */
14883d9b1a2aSHans Rosenfeld void
nvme_print_identify_nsid(const nvme_identify_nsid_t * idns,const nvme_version_t * version)1489*533affcbSRobert Mustacchi nvme_print_identify_nsid(const nvme_identify_nsid_t *idns,
1490*533affcbSRobert Mustacchi const nvme_version_t *version)
14913d9b1a2aSHans Rosenfeld {
14923d9b1a2aSHans Rosenfeld int bsize = 1 << idns->id_lbaf[idns->id_flbas.lba_format].lbaf_lbads;
14933d9b1a2aSHans Rosenfeld int i;
14943d9b1a2aSHans Rosenfeld
14953d9b1a2aSHans Rosenfeld nvme_print(0, "Identify Namespace", -1, NULL);
14963d9b1a2aSHans Rosenfeld nvme_print(2, "Namespace Capabilities and Features", -1, NULL);
14973d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Namespace Size",
14983d9b1a2aSHans Rosenfeld idns->id_nsize * bsize / 1024 / 1024, NULL, "MB");
14993d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Namespace Capacity",
15003d9b1a2aSHans Rosenfeld idns->id_ncap * bsize / 1024 / 1024, NULL, "MB");
15013d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Namespace Utilization",
15023d9b1a2aSHans Rosenfeld idns->id_nuse * bsize / 1024 / 1024, NULL, "MB");
15033d9b1a2aSHans Rosenfeld nvme_print(4, "Namespace Features", -1, NULL);
15043d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Thin Provisioning",
1505*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15063d9b1a2aSHans Rosenfeld idns->id_nsfeat.f_thin, NULL, NULL);
15078d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace-specific Atomic Units",
1508*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
15098d5300d3SRobert Mustacchi idns->id_nsfeat.f_nsabp, NULL, NULL);
15108d5300d3SRobert Mustacchi nvme_print_bit(6, "Deallocate errors",
1511*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
15128d5300d3SRobert Mustacchi idns->id_nsfeat.f_dae, NULL, NULL);
15138d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace GUID Reuse",
1514*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
15158d5300d3SRobert Mustacchi idns->id_nsfeat.f_uidreuse, "impossible", "possible");
15168d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace-specific I/O Optimized Sizes",
1517*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
15188d5300d3SRobert Mustacchi idns->id_nsfeat.f_optperf, NULL, NULL);
15198d5300d3SRobert Mustacchi
15203d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of LBA Formats",
15213d9b1a2aSHans Rosenfeld (uint16_t)idns->id_nlbaf + 1, NULL, NULL);
15223d9b1a2aSHans Rosenfeld nvme_print(4, "Formatted LBA Size", -1, NULL);
15233d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "LBA Format",
15243d9b1a2aSHans Rosenfeld (uint16_t)idns->id_flbas.lba_format, NULL, NULL);
15253d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Extended Data LBA",
1526*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15273d9b1a2aSHans Rosenfeld idns->id_flbas.lba_extlba, "yes", "no");
15288d5300d3SRobert Mustacchi
15293d9b1a2aSHans Rosenfeld nvme_print(4, "Metadata Capabilities", -1, NULL);
15303d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Extended Data LBA",
1531*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15323d9b1a2aSHans Rosenfeld idns->id_mc.mc_extlba, NULL, NULL);
15333d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Separate Metadata",
1534*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15353d9b1a2aSHans Rosenfeld idns->id_mc.mc_separate, NULL, NULL);
15368d5300d3SRobert Mustacchi
15373d9b1a2aSHans Rosenfeld nvme_print(4, "End-to-End Data Protection Capabilities", -1, NULL);
15383d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information Type 1",
1539*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15403d9b1a2aSHans Rosenfeld idns->id_dpc.dp_type1, NULL, NULL);
15413d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information Type 2",
1542*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15433d9b1a2aSHans Rosenfeld idns->id_dpc.dp_type2, NULL, NULL);
15443d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information Type 3",
1545*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15463d9b1a2aSHans Rosenfeld idns->id_dpc.dp_type3, NULL, NULL);
15473d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information first",
1548*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15493d9b1a2aSHans Rosenfeld idns->id_dpc.dp_first, NULL, NULL);
15503d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information last",
1551*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15523d9b1a2aSHans Rosenfeld idns->id_dpc.dp_last, NULL, NULL);
15533d9b1a2aSHans Rosenfeld nvme_print(4, "End-to-End Data Protection Settings", -1, NULL);
15548d5300d3SRobert Mustacchi if (idns->id_dps.dp_pinfo == 0) {
15553d9b1a2aSHans Rosenfeld nvme_print_str(6, "Protection Information", -1,
15563d9b1a2aSHans Rosenfeld "disabled", 0);
15578d5300d3SRobert Mustacchi } else {
15583d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Protection Information Type",
15593d9b1a2aSHans Rosenfeld idns->id_dps.dp_pinfo, NULL, NULL);
15608d5300d3SRobert Mustacchi }
15613d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Protection Information in Metadata",
1562*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
15633d9b1a2aSHans Rosenfeld idns->id_dps.dp_first, "first 8 bytes", "last 8 bytes");
15643d9b1a2aSHans Rosenfeld
15658d5300d3SRobert Mustacchi nvme_print(4, "Namespace Multi-Path I/O and Namespace Sharing "
15668d5300d3SRobert Mustacchi "Capabilities", -1, NULL);
15678d5300d3SRobert Mustacchi
15688d5300d3SRobert Mustacchi nvme_print_bit(6, "Namespace is shared",
1569*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15708d5300d3SRobert Mustacchi idns->id_nmic.nm_shared, "yes", "no");
15718d5300d3SRobert Mustacchi nvme_print(2, "Reservation Capabilities", -1, NULL);
15728d5300d3SRobert Mustacchi nvme_print_bit(6, "Persist Through Power Loss",
1573*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15748d5300d3SRobert Mustacchi idns->id_rescap.rc_persist, NULL, NULL);
15758d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Exclusive",
1576*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15778d5300d3SRobert Mustacchi idns->id_rescap.rc_wr_excl, NULL, NULL);
15788d5300d3SRobert Mustacchi nvme_print_bit(6, "Exclusive Access",
1579*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15808d5300d3SRobert Mustacchi idns->id_rescap.rc_excl, NULL, NULL);
15818d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Exclusive - Registrants Only",
1582*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15838d5300d3SRobert Mustacchi idns->id_rescap.rc_wr_excl_r, NULL, NULL);
15848d5300d3SRobert Mustacchi nvme_print_bit(6, "Exclusive Access - Registrants Only",
1585*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15868d5300d3SRobert Mustacchi idns->id_rescap.rc_excl_r, NULL, NULL);
15878d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Exclusive - All Registrants",
1588*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15898d5300d3SRobert Mustacchi idns->id_rescap.rc_wr_excl_a, NULL, NULL);
15908d5300d3SRobert Mustacchi nvme_print_bit(6, "Exclusive Access - All Registrants",
1591*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v1),
15928d5300d3SRobert Mustacchi idns->id_rescap.rc_excl_a, NULL, NULL);
15938d5300d3SRobert Mustacchi nvme_print_bit(6, "Ignore Existing Key Behavior",
1594*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
15958d5300d3SRobert Mustacchi idns->id_rescap.rc_ign_ekey, "NVMe 1.3 behavior", "pre-NVMe 1.3");
15968d5300d3SRobert Mustacchi
15978d5300d3SRobert Mustacchi if (idns->id_fpi.fpi_sup != 0) {
15988d5300d3SRobert Mustacchi nvme_print_uint64(4, "NVM Format Remaining",
15998d5300d3SRobert Mustacchi idns->id_fpi.fpi_remp, NULL, "%");
16008d5300d3SRobert Mustacchi } else {
16018d5300d3SRobert Mustacchi nvme_print_str(4, "NVM Format Remaining", -1, "unsupported", 0);
16028d5300d3SRobert Mustacchi }
16038d5300d3SRobert Mustacchi
16048d5300d3SRobert Mustacchi if (verbose) {
16058d5300d3SRobert Mustacchi if (idns->id_nawun != 0) {
16068d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Atomic Write Unit "
16078d5300d3SRobert Mustacchi "Normal", idns->id_nawun + 1, NULL, " blocks");
16088d5300d3SRobert Mustacchi } else {
16098d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Write Unit "
16108d5300d3SRobert Mustacchi "Normal", -1, "unspecified", 0);
16118d5300d3SRobert Mustacchi }
16128d5300d3SRobert Mustacchi
16138d5300d3SRobert Mustacchi if (idns->id_nawupf != 0) {
16148d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Atomic Write Unit "
16158d5300d3SRobert Mustacchi "Power Fail", idns->id_nawupf + 1, NULL, " blocks");
16168d5300d3SRobert Mustacchi } else {
16178d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Write Unit "
16188d5300d3SRobert Mustacchi "Power Fail", -1, "unspecified", 0);
16198d5300d3SRobert Mustacchi }
16208d5300d3SRobert Mustacchi
16218d5300d3SRobert Mustacchi if (idns->id_nacwu != 0) {
16228d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Atomic Compare & Write "
16238d5300d3SRobert Mustacchi "Unit", idns->id_nacwu + 1, NULL, " blocks");
16248d5300d3SRobert Mustacchi } else {
16258d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Compare & Write "
16268d5300d3SRobert Mustacchi "Unit", -1, "unspecified", 0);
16278d5300d3SRobert Mustacchi }
16288d5300d3SRobert Mustacchi
16298d5300d3SRobert Mustacchi if (idns->id_nabsn != 0) {
16308d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Atomic Boundary Size "
16318d5300d3SRobert Mustacchi "Normal", idns->id_nabsn + 1, NULL, " blocks");
16328d5300d3SRobert Mustacchi } else {
16338d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Boundary Size "
16348d5300d3SRobert Mustacchi "Normal", -1, "unspecified", 0);
16358d5300d3SRobert Mustacchi }
16368d5300d3SRobert Mustacchi
16378d5300d3SRobert Mustacchi if (idns->id_nbao != 0) {
16388d5300d3SRobert Mustacchi nvme_print(4, "Namespace Atomic Boundary Offset", -1,
16398d5300d3SRobert Mustacchi "LBA %u", idns->id_nbao);
16408d5300d3SRobert Mustacchi } else {
16418d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Boundary Offset",
16428d5300d3SRobert Mustacchi -1, "unspecified", 0);
16438d5300d3SRobert Mustacchi }
16448d5300d3SRobert Mustacchi
16458d5300d3SRobert Mustacchi if (idns->id_nabspf != 0) {
16468d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Atomic Boundary Size "
16478d5300d3SRobert Mustacchi "Power Fail", idns->id_nabspf + 1, NULL,
16488d5300d3SRobert Mustacchi idns->id_nabspf == 0 ? " block" : " blocks");
16498d5300d3SRobert Mustacchi } else {
16508d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Atomic Boundary Size "
16518d5300d3SRobert Mustacchi "Power Fail", -1, "unspecified", 0);
16528d5300d3SRobert Mustacchi }
16538d5300d3SRobert Mustacchi
16548d5300d3SRobert Mustacchi if (idns->id_noiob != 0) {
16558d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Optional I/O Boundary",
16568d5300d3SRobert Mustacchi idns->id_noiob, NULL,
16578d5300d3SRobert Mustacchi idns->id_noiob == 1 ? " block" : " blocks");
16588d5300d3SRobert Mustacchi } else {
16598d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Optimal I/O Boundary",
16608d5300d3SRobert Mustacchi -1, "unspecified", 0);
16618d5300d3SRobert Mustacchi }
16628d5300d3SRobert Mustacchi }
16638d5300d3SRobert Mustacchi
16648d5300d3SRobert Mustacchi if (idns->id_nvmcap.lo != 0 || idns->id_nvmcap.hi != 0) {
16658d5300d3SRobert Mustacchi nvme_print_uint128(4, "NVM Capacity", idns->id_nvmcap,
16668d5300d3SRobert Mustacchi "B", 0, 0);
16678d5300d3SRobert Mustacchi } else {
16688d5300d3SRobert Mustacchi nvme_print_str(4, "NVM Capacity", -1, "unknown", 0);
16698d5300d3SRobert Mustacchi }
16708d5300d3SRobert Mustacchi
16718d5300d3SRobert Mustacchi if (verbose) {
16728d5300d3SRobert Mustacchi if (idns->id_npwg != 0) {
16738d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Preferred Write "
16748d5300d3SRobert Mustacchi "Granularity", idns->id_npwg + 1, NULL, " blocks");
16758d5300d3SRobert Mustacchi } else {
16768d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Preferred Write "
16778d5300d3SRobert Mustacchi "Granularity", -1, "unspecified", 0);
16788d5300d3SRobert Mustacchi }
16798d5300d3SRobert Mustacchi
16808d5300d3SRobert Mustacchi if (idns->id_npwa != 0) {
16818d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Preferred Write "
16828d5300d3SRobert Mustacchi "Alignment", idns->id_npwa + 1, NULL, " blocks");
16838d5300d3SRobert Mustacchi } else {
16848d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Preferred Write "
16858d5300d3SRobert Mustacchi "Alignment", -1, "unspecified", 0);
16868d5300d3SRobert Mustacchi }
16878d5300d3SRobert Mustacchi
16888d5300d3SRobert Mustacchi if (idns->id_npdg != 0) {
16898d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Preferred Deallocate "
16908d5300d3SRobert Mustacchi "Granularity", idns->id_npdg + 1, NULL, " blocks");
16918d5300d3SRobert Mustacchi } else {
16928d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Preferred Deallocate "
16938d5300d3SRobert Mustacchi "Granularity", -1, "unspecified", 0);
16948d5300d3SRobert Mustacchi }
16958d5300d3SRobert Mustacchi
16968d5300d3SRobert Mustacchi if (idns->id_npda != 0) {
16978d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Preferred Deallocate "
16988d5300d3SRobert Mustacchi "Alignment", idns->id_npda + 1, NULL, " blocks");
16998d5300d3SRobert Mustacchi } else {
17008d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Preferred Deallocate "
17018d5300d3SRobert Mustacchi "Alignment", -1, "unspecified", 0);
17028d5300d3SRobert Mustacchi }
17038d5300d3SRobert Mustacchi
17048d5300d3SRobert Mustacchi if (idns->id_nows != 0) {
17058d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Optimal Write Size",
17068d5300d3SRobert Mustacchi idns->id_nows + 1, NULL, " blocks");
17078d5300d3SRobert Mustacchi } else {
17088d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Optimal Write Size",
17098d5300d3SRobert Mustacchi -1, "unspecified", 0);
17108d5300d3SRobert Mustacchi }
17118d5300d3SRobert Mustacchi
17128d5300d3SRobert Mustacchi if (idns->id_anagrpid != 0) {
17138d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace ANA Group Identifier",
17148d5300d3SRobert Mustacchi idns->id_anagrpid, NULL, NULL);
17158d5300d3SRobert Mustacchi } else {
17168d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace ANA Group Identifier",
17178d5300d3SRobert Mustacchi -1, "unsupported", 0);
17188d5300d3SRobert Mustacchi }
17198d5300d3SRobert Mustacchi }
17208d5300d3SRobert Mustacchi
17218d5300d3SRobert Mustacchi nvme_print(4, "Namespace Attributes", -1, NULL);
17228d5300d3SRobert Mustacchi nvme_print_bit(6, "Write Protected",
1723*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
17248d5300d3SRobert Mustacchi idns->id_nsattr.nsa_wprot, "yes", "no");
17258d5300d3SRobert Mustacchi
17268d5300d3SRobert Mustacchi if (verbose) {
17278d5300d3SRobert Mustacchi if (idns->id_nvmsetid != 0) {
17288d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Set Identifier",
17298d5300d3SRobert Mustacchi idns->id_nvmsetid, NULL, NULL);
17308d5300d3SRobert Mustacchi } else {
17318d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Set Identifier",
17328d5300d3SRobert Mustacchi -1, "unsupported", 0);
17338d5300d3SRobert Mustacchi }
17348d5300d3SRobert Mustacchi
17358d5300d3SRobert Mustacchi if (idns->id_endgid != 0) {
17368d5300d3SRobert Mustacchi nvme_print_uint64(4, "Namespace Endurance Group "
17378d5300d3SRobert Mustacchi "Identifier", idns->id_endgid, NULL, NULL);
17388d5300d3SRobert Mustacchi } else {
17398d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace Endurance Group "
17408d5300d3SRobert Mustacchi "Identifier", -1, "unsupported", 0);
17418d5300d3SRobert Mustacchi }
17428d5300d3SRobert Mustacchi }
17438d5300d3SRobert Mustacchi
1744*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v2)) {
17458d5300d3SRobert Mustacchi uint8_t guid[16] = { 0 };
17468d5300d3SRobert Mustacchi if (memcmp(guid, idns->id_nguid, sizeof (guid) != 0)) {
1747153f3212SHans Rosenfeld nvme_print_guid(4, "Namespace GUID", idns->id_nguid);
17488d5300d3SRobert Mustacchi } else {
17498d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace GUID",
17508d5300d3SRobert Mustacchi -1, "unsupported", 0);
17518d5300d3SRobert Mustacchi }
17528d5300d3SRobert Mustacchi } else {
17538d5300d3SRobert Mustacchi nvme_print_str(4, "Namespace GUID", -1, "unsupported", 0);
17548d5300d3SRobert Mustacchi }
17558d5300d3SRobert Mustacchi
17568d5300d3SRobert Mustacchi
1757*533affcbSRobert Mustacchi if (nvme_vers_atleast(version, &nvme_vers_1v1)) {
17588d5300d3SRobert Mustacchi uint8_t oui[8] = { 0 };
17598d5300d3SRobert Mustacchi if (memcmp(oui, idns->id_eui64, sizeof (oui)) != 0) {
1760153f3212SHans Rosenfeld nvme_print_eui64(4, "IEEE Extended Unique Identifier",
1761153f3212SHans Rosenfeld idns->id_eui64);
17628d5300d3SRobert Mustacchi } else {
17638d5300d3SRobert Mustacchi nvme_print_str(4, "IEEE Extended Unique Identifier",
17648d5300d3SRobert Mustacchi -1, "unsupported", 0);
17658d5300d3SRobert Mustacchi }
17668d5300d3SRobert Mustacchi } else {
17678d5300d3SRobert Mustacchi nvme_print_str(4, "IEEE Extended Unique Identifier", -1,
17688d5300d3SRobert Mustacchi "unsupported", 0);
17693d9b1a2aSHans Rosenfeld }
17703d9b1a2aSHans Rosenfeld
17713d9b1a2aSHans Rosenfeld for (i = 0; i <= idns->id_nlbaf; i++) {
17723d9b1a2aSHans Rosenfeld if (verbose == 0 && idns->id_lbaf[i].lbaf_ms != 0)
17733d9b1a2aSHans Rosenfeld continue;
17743d9b1a2aSHans Rosenfeld
17753d9b1a2aSHans Rosenfeld nvme_print(4, "LBA Format", i, NULL);
17763d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Metadata Size",
17773d9b1a2aSHans Rosenfeld idns->id_lbaf[i].lbaf_ms, NULL, " bytes");
17783d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "LBA Data Size",
17793d9b1a2aSHans Rosenfeld 1 << idns->id_lbaf[i].lbaf_lbads, NULL, " bytes");
17803d9b1a2aSHans Rosenfeld nvme_print_str(6, "Relative Performance", -1,
17813d9b1a2aSHans Rosenfeld lbaf_relative_performance[idns->id_lbaf[i].lbaf_rp], 0);
17823d9b1a2aSHans Rosenfeld }
17833d9b1a2aSHans Rosenfeld }
17843d9b1a2aSHans Rosenfeld
1785153f3212SHans Rosenfeld /*
1786153f3212SHans Rosenfeld * nvme_print_identify_nsid_list
1787153f3212SHans Rosenfeld *
1788153f3212SHans Rosenfeld * Print a NVMe Namespace List.
1789153f3212SHans Rosenfeld */
1790153f3212SHans Rosenfeld void
nvme_print_identify_nsid_list(const char * header,const nvme_identify_nsid_list_t * nslist)1791153f3212SHans Rosenfeld nvme_print_identify_nsid_list(const char *header,
1792*533affcbSRobert Mustacchi const nvme_identify_nsid_list_t *nslist)
1793153f3212SHans Rosenfeld {
1794153f3212SHans Rosenfeld uint32_t i;
1795153f3212SHans Rosenfeld
1796153f3212SHans Rosenfeld nvme_print(0, header, -1, NULL);
1797153f3212SHans Rosenfeld
1798153f3212SHans Rosenfeld /*
1799153f3212SHans Rosenfeld * The namespace ID list is ordered, unused entries are 0.
1800153f3212SHans Rosenfeld */
1801153f3212SHans Rosenfeld for (i = 0;
1802153f3212SHans Rosenfeld i < ARRAY_SIZE(nslist->nl_nsid) && nslist->nl_nsid[i] != 0;
1803153f3212SHans Rosenfeld i++) {
1804153f3212SHans Rosenfeld nvme_print_uint64(2, "Namespace Identifier", nslist->nl_nsid[i],
1805153f3212SHans Rosenfeld NULL, NULL);
1806153f3212SHans Rosenfeld }
1807153f3212SHans Rosenfeld }
1808153f3212SHans Rosenfeld
1809153f3212SHans Rosenfeld /*
1810153f3212SHans Rosenfeld * nvme_print_identify_nsid_desc
1811153f3212SHans Rosenfeld *
1812153f3212SHans Rosenfeld * Print a NVMe Namespace Identifier Descriptor list.
1813153f3212SHans Rosenfeld */
1814153f3212SHans Rosenfeld void
nvme_print_identify_nsid_desc(void * nsdesc)1815153f3212SHans Rosenfeld nvme_print_identify_nsid_desc(void *nsdesc)
1816153f3212SHans Rosenfeld {
1817*533affcbSRobert Mustacchi const nvme_identify_nsid_desc_t *desc = nsdesc;
1818153f3212SHans Rosenfeld int i = 0;
1819153f3212SHans Rosenfeld uintptr_t ptr, end;
1820153f3212SHans Rosenfeld
1821153f3212SHans Rosenfeld nvme_print(0, "Namespace Identification Descriptors", -1, NULL);
1822153f3212SHans Rosenfeld
1823153f3212SHans Rosenfeld for (ptr = (uintptr_t)desc, end = ptr + NVME_IDENTIFY_BUFSIZE;
1824153f3212SHans Rosenfeld desc->nd_nidl != 0 && ptr + desc->nd_nidl + 4 <= end;
1825153f3212SHans Rosenfeld desc = (nvme_identify_nsid_desc_t *)(ptr += desc->nd_nidl + 4)) {
1826153f3212SHans Rosenfeld const char *nidt;
1827153f3212SHans Rosenfeld
1828153f3212SHans Rosenfeld if (desc->nd_nidt >= ARRAY_SIZE(ns_identifier_type))
1829153f3212SHans Rosenfeld nidt = "Reserved";
1830153f3212SHans Rosenfeld else
1831153f3212SHans Rosenfeld nidt = ns_identifier_type[desc->nd_nidt];
1832153f3212SHans Rosenfeld
1833153f3212SHans Rosenfeld nvme_print(2, "Namespace Identifier Descriptor", i++, NULL);
1834153f3212SHans Rosenfeld nvme_print_str(4, "Namespace Identifier Type", -1, nidt, 0);
1835153f3212SHans Rosenfeld nvme_print_uint64(4, "Namespace Identifier Length",
1836153f3212SHans Rosenfeld desc->nd_nidl, NULL, NULL);
1837153f3212SHans Rosenfeld
1838153f3212SHans Rosenfeld if (desc->nd_nidt == NVME_NSID_DESC_EUI64 &&
1839153f3212SHans Rosenfeld desc->nd_nidl == NVME_NSID_DESC_LEN_EUI64) {
1840153f3212SHans Rosenfeld nvme_print_eui64(4, "IEEE Extended Unique Identifier",
1841153f3212SHans Rosenfeld desc->nd_nid);
1842153f3212SHans Rosenfeld } else if (desc->nd_nidt == NVME_NSID_DESC_NGUID &&
1843153f3212SHans Rosenfeld desc->nd_nidl == NVME_NSID_DESC_LEN_NGUID) {
1844153f3212SHans Rosenfeld nvme_print_guid(4, "Namespace GUID", desc->nd_nid);
1845153f3212SHans Rosenfeld } else if (desc->nd_nidt == NVME_NSID_DESC_NUUID &&
1846153f3212SHans Rosenfeld desc->nd_nidl == NVME_NSID_DESC_LEN_NUUID) {
1847153f3212SHans Rosenfeld nvme_print_uuid(4, "Namespace UUID", desc->nd_nid);
1848153f3212SHans Rosenfeld } else if (desc->nd_nidt < NVME_NSID_DESC_MIN ||
1849153f3212SHans Rosenfeld desc->nd_nidt > NVME_NSID_DESC_MAX) {
1850153f3212SHans Rosenfeld nvme_print_hexbuf(4, "Raw Bytes", desc->nd_nid,
1851153f3212SHans Rosenfeld desc->nd_nidl);
1852153f3212SHans Rosenfeld } else {
1853153f3212SHans Rosenfeld nvme_print_hexbuf(4,
1854153f3212SHans Rosenfeld "Raw Bytes (Invalid Descriptor Length)",
1855153f3212SHans Rosenfeld desc->nd_nid, desc->nd_nidl);
1856153f3212SHans Rosenfeld }
1857153f3212SHans Rosenfeld }
1858153f3212SHans Rosenfeld }
1859153f3212SHans Rosenfeld
1860153f3212SHans Rosenfeld /*
1861153f3212SHans Rosenfeld * nvme_print_identify_ctrl_list
1862153f3212SHans Rosenfeld *
1863153f3212SHans Rosenfeld * Print a NVMe Controller List.
1864153f3212SHans Rosenfeld */
1865153f3212SHans Rosenfeld void
nvme_print_identify_ctrl_list(const char * header,const nvme_identify_ctrl_list_t * ctlist)1866153f3212SHans Rosenfeld nvme_print_identify_ctrl_list(const char *header,
1867*533affcbSRobert Mustacchi const nvme_identify_ctrl_list_t *ctlist)
1868153f3212SHans Rosenfeld {
1869153f3212SHans Rosenfeld int i;
1870153f3212SHans Rosenfeld
1871153f3212SHans Rosenfeld nvme_print(0, header, -1, NULL);
1872153f3212SHans Rosenfeld for (i = 0; i != ctlist->cl_nid; i++) {
1873153f3212SHans Rosenfeld nvme_print_uint64(2, "Controller Identifier",
1874153f3212SHans Rosenfeld ctlist->cl_ctlid[i], NULL, NULL);
1875153f3212SHans Rosenfeld }
1876153f3212SHans Rosenfeld }
1877153f3212SHans Rosenfeld
18783d9b1a2aSHans Rosenfeld /*
18793d9b1a2aSHans Rosenfeld * nvme_print_error_log
18803d9b1a2aSHans Rosenfeld *
18813d9b1a2aSHans Rosenfeld * This function pretty-prints all non-zero error log entries, or all entries
18823d9b1a2aSHans Rosenfeld * if verbose is set.
18833d9b1a2aSHans Rosenfeld */
18843d9b1a2aSHans Rosenfeld void
nvme_print_error_log(int nlog,const nvme_error_log_entry_t * elog,const nvme_version_t * version)1885*533affcbSRobert Mustacchi nvme_print_error_log(int nlog, const nvme_error_log_entry_t *elog,
1886*533affcbSRobert Mustacchi const nvme_version_t *version)
18873d9b1a2aSHans Rosenfeld {
18883d9b1a2aSHans Rosenfeld int i;
18893d9b1a2aSHans Rosenfeld
18903d9b1a2aSHans Rosenfeld nvme_print(0, "Error Log", -1, NULL);
18913d9b1a2aSHans Rosenfeld for (i = 0; i != nlog; i++)
18923d9b1a2aSHans Rosenfeld if (elog[i].el_count == 0)
18933d9b1a2aSHans Rosenfeld break;
18943d9b1a2aSHans Rosenfeld nvme_print_uint64(2, "Number of Error Log Entries", i, NULL, NULL);
18953d9b1a2aSHans Rosenfeld
18963d9b1a2aSHans Rosenfeld for (i = 0; i != nlog; i++) {
18973d9b1a2aSHans Rosenfeld int sc = elog[i].el_sf.sf_sc;
1898d1efd556SRobert Mustacchi const char *sc_str = "Unknown";
18993d9b1a2aSHans Rosenfeld
19003d9b1a2aSHans Rosenfeld if (elog[i].el_count == 0 && verbose == 0)
19013d9b1a2aSHans Rosenfeld break;
19023d9b1a2aSHans Rosenfeld
19033d9b1a2aSHans Rosenfeld switch (elog[i].el_sf.sf_sct) {
19043d9b1a2aSHans Rosenfeld case 0: /* Generic Command Status */
1905153f3212SHans Rosenfeld if (sc < ARRAY_SIZE(generic_status_codes)) {
19063d9b1a2aSHans Rosenfeld sc_str = generic_status_codes[sc];
1907d1efd556SRobert Mustacchi } else if (sc >= 0x80 &&
1908153f3212SHans Rosenfeld sc - 0x80 < ARRAY_SIZE(generic_nvm_status_codes)) {
19093d9b1a2aSHans Rosenfeld sc_str = generic_nvm_status_codes[sc - 0x80];
1910d1efd556SRobert Mustacchi }
19113d9b1a2aSHans Rosenfeld break;
19123d9b1a2aSHans Rosenfeld case 1: /* Specific Command Status */
1913153f3212SHans Rosenfeld if (sc < ARRAY_SIZE(specific_status_codes)) {
19143d9b1a2aSHans Rosenfeld sc_str = specific_status_codes[sc];
1915d1efd556SRobert Mustacchi } else if (sc >= 0x80 &&
1916153f3212SHans Rosenfeld sc - 0x80 < ARRAY_SIZE(specific_nvm_status_codes)) {
19173d9b1a2aSHans Rosenfeld sc_str = specific_nvm_status_codes[sc - 0x80];
1918d1efd556SRobert Mustacchi }
19193d9b1a2aSHans Rosenfeld break;
19203d9b1a2aSHans Rosenfeld case 2: /* Media Errors */
19213d9b1a2aSHans Rosenfeld if (sc >= 0x80 &&
1922153f3212SHans Rosenfeld sc - 0x80 < ARRAY_SIZE(media_nvm_status_codes)) {
19233d9b1a2aSHans Rosenfeld sc_str = media_nvm_status_codes[sc - 0x80];
1924d1efd556SRobert Mustacchi }
1925d1efd556SRobert Mustacchi break;
1926d1efd556SRobert Mustacchi case 3: /* Path Related Status */
1927153f3212SHans Rosenfeld if (sc < ARRAY_SIZE(path_status_codes)) {
1928d1efd556SRobert Mustacchi sc_str = path_status_codes[sc];
1929d1efd556SRobert Mustacchi } else if (sc >= 0x60 &&
1930153f3212SHans Rosenfeld sc - 0x60 < ARRAY_SIZE(path_controller_codes)) {
1931d1efd556SRobert Mustacchi sc_str = path_controller_codes[sc - 0x60];
1932d1efd556SRobert Mustacchi } else if (sc >= 0x70 &&
1933153f3212SHans Rosenfeld sc - 0x70 < ARRAY_SIZE(path_host_codes)) {
1934d1efd556SRobert Mustacchi sc_str = path_host_codes[sc - 0x70];
1935d1efd556SRobert Mustacchi }
19363d9b1a2aSHans Rosenfeld break;
19373d9b1a2aSHans Rosenfeld case 7: /* Vendor Specific */
19383d9b1a2aSHans Rosenfeld sc_str = "Unknown Vendor Specific";
19393d9b1a2aSHans Rosenfeld break;
19403d9b1a2aSHans Rosenfeld default:
19413d9b1a2aSHans Rosenfeld sc_str = "Reserved";
19423d9b1a2aSHans Rosenfeld break;
19433d9b1a2aSHans Rosenfeld }
19443d9b1a2aSHans Rosenfeld
19453d9b1a2aSHans Rosenfeld nvme_print(2, "Entry", i, NULL);
19463d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Error Count",
19473d9b1a2aSHans Rosenfeld elog[i].el_count, NULL, NULL);
19483d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Submission Queue ID",
19493d9b1a2aSHans Rosenfeld elog[i].el_sqid, NULL, NULL);
19503d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Command ID",
19513d9b1a2aSHans Rosenfeld elog[i].el_cid, NULL, NULL);
19523d9b1a2aSHans Rosenfeld nvme_print(4, "Status Field", -1, NULL);
19533d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Phase Tag",
19543d9b1a2aSHans Rosenfeld elog[i].el_sf.sf_p, NULL, NULL);
19553d9b1a2aSHans Rosenfeld nvme_print(6, "Status Code", -1, "0x%0.2x (%s)",
19563d9b1a2aSHans Rosenfeld sc, sc_str);
19573d9b1a2aSHans Rosenfeld nvme_print(6, "Status Code Type", -1, "0x%x (%s)",
19583d9b1a2aSHans Rosenfeld elog[i].el_sf.sf_sct,
19593d9b1a2aSHans Rosenfeld status_code_types[elog[i].el_sf.sf_sct]);
19603d9b1a2aSHans Rosenfeld nvme_print_bit(6, "More",
1961*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
19623d9b1a2aSHans Rosenfeld elog[i].el_sf.sf_m, "yes", "no");
19633d9b1a2aSHans Rosenfeld nvme_print_bit(6, "Do Not Retry",
1964*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
19653d9b1a2aSHans Rosenfeld elog[i].el_sf.sf_m, "yes", "no");
19663d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Parameter Error Location byte",
19673d9b1a2aSHans Rosenfeld elog[i].el_byte, "0x%0.2"PRIx64, NULL);
19683d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Parameter Error Location bit",
19693d9b1a2aSHans Rosenfeld elog[i].el_bit, NULL, NULL);
19703d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Logical Block Address",
19713d9b1a2aSHans Rosenfeld elog[i].el_lba, NULL, NULL);
19723d9b1a2aSHans Rosenfeld nvme_print(4, "Namespace ID", -1, "%d",
19733d9b1a2aSHans Rosenfeld elog[i].el_nsid == 0xffffffff ?
19743d9b1a2aSHans Rosenfeld 0 : elog[i].el_nsid);
19753d9b1a2aSHans Rosenfeld nvme_print_uint64(4,
19768d5300d3SRobert Mustacchi "Vendor Specific Information Available",
19773d9b1a2aSHans Rosenfeld elog[i].el_vendor, NULL, NULL);
19783d9b1a2aSHans Rosenfeld }
19793d9b1a2aSHans Rosenfeld }
19803d9b1a2aSHans Rosenfeld
19813d9b1a2aSHans Rosenfeld /*
19823d9b1a2aSHans Rosenfeld * nvme_print_health_log
19833d9b1a2aSHans Rosenfeld *
19843d9b1a2aSHans Rosenfeld * This function pretty-prints a summary of the SMART/Health log, or all
19853d9b1a2aSHans Rosenfeld * of the log if verbose is set.
19863d9b1a2aSHans Rosenfeld */
19873d9b1a2aSHans Rosenfeld void
nvme_print_health_log(const nvme_health_log_t * hlog,const nvme_identify_ctrl_t * idctl,const nvme_version_t * version)1988*533affcbSRobert Mustacchi nvme_print_health_log(const nvme_health_log_t *hlog,
1989*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *idctl, const nvme_version_t *version)
19903d9b1a2aSHans Rosenfeld {
19913d9b1a2aSHans Rosenfeld nvme_print(0, "SMART/Health Information", -1, NULL);
19923d9b1a2aSHans Rosenfeld nvme_print(2, "Critical Warnings", -1, NULL);
19933d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Available Space",
1994*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
19953d9b1a2aSHans Rosenfeld hlog->hl_crit_warn.cw_avail, "low", "OK");
19963d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Temperature",
1997*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
19983d9b1a2aSHans Rosenfeld hlog->hl_crit_warn.cw_temp, "too high", "OK");
19993d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Device Reliability",
2000*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
20013d9b1a2aSHans Rosenfeld hlog->hl_crit_warn.cw_reliab, "degraded", "OK");
20023d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Media",
2003*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
20043d9b1a2aSHans Rosenfeld hlog->hl_crit_warn.cw_readonly, "read-only", "OK");
20053d9b1a2aSHans Rosenfeld if (idctl->id_vwc.vwc_present != 0)
20063d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Volatile Memory Backup",
2007*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
20083d9b1a2aSHans Rosenfeld hlog->hl_crit_warn.cw_volatile, "failed", "OK");
20093d9b1a2aSHans Rosenfeld
20104a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature", hlog->hl_temp);
20113d9b1a2aSHans Rosenfeld nvme_print_uint64(2, "Available Spare Capacity",
20123d9b1a2aSHans Rosenfeld hlog->hl_avail_spare, NULL, "%");
20133d9b1a2aSHans Rosenfeld
20143d9b1a2aSHans Rosenfeld if (verbose != 0)
20153d9b1a2aSHans Rosenfeld nvme_print_uint64(2, "Available Spare Threshold",
20163d9b1a2aSHans Rosenfeld hlog->hl_avail_spare_thr, NULL, "%");
20173d9b1a2aSHans Rosenfeld
20183d9b1a2aSHans Rosenfeld nvme_print_uint64(2, "Device Life Used",
20193d9b1a2aSHans Rosenfeld hlog->hl_used, NULL, "%");
20203d9b1a2aSHans Rosenfeld
20213d9b1a2aSHans Rosenfeld if (verbose == 0)
20223d9b1a2aSHans Rosenfeld return;
20233d9b1a2aSHans Rosenfeld
20243d9b1a2aSHans Rosenfeld /*
20253d9b1a2aSHans Rosenfeld * The following two fields are in 1000 512 byte units. Convert that to
20264a663bacSRobert Mustacchi * GB by doing binary shifts (9 left and 30 right) and multiply by 10^3.
20273d9b1a2aSHans Rosenfeld */
20283d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Data Read",
20293d9b1a2aSHans Rosenfeld hlog->hl_data_read, "GB", 30 - 9, 3);
20303d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Data Written",
20313d9b1a2aSHans Rosenfeld hlog->hl_data_write, "GB", 30 - 9, 3);
20323d9b1a2aSHans Rosenfeld
20333d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Read Commands",
20343d9b1a2aSHans Rosenfeld hlog->hl_host_read, NULL, 0, 0);
20353d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Write Commands",
20363d9b1a2aSHans Rosenfeld hlog->hl_host_write, NULL, 0, 0);
20373d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Controller Busy",
20383d9b1a2aSHans Rosenfeld hlog->hl_ctrl_busy, "min", 0, 0);
20393d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Power Cycles",
20403d9b1a2aSHans Rosenfeld hlog->hl_power_cycles, NULL, 0, 0);
20413d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Power On",
20423d9b1a2aSHans Rosenfeld hlog->hl_power_on_hours, "h", 0, 0);
20433d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Unsafe Shutdowns",
20443d9b1a2aSHans Rosenfeld hlog->hl_unsafe_shutdn, NULL, 0, 0);
20453d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Uncorrectable Media Errors",
20463d9b1a2aSHans Rosenfeld hlog->hl_media_errors, NULL, 0, 0);
20473d9b1a2aSHans Rosenfeld nvme_print_uint128(2, "Errors Logged",
20483d9b1a2aSHans Rosenfeld hlog->hl_errors_logged, NULL, 0, 0);
20494a663bacSRobert Mustacchi
2050*533affcbSRobert Mustacchi if (!nvme_vers_atleast(version, &nvme_vers_1v2)) {
20514a663bacSRobert Mustacchi return;
20524a663bacSRobert Mustacchi }
20534a663bacSRobert Mustacchi
20544a663bacSRobert Mustacchi if (idctl->ap_wctemp != 0) {
20554a663bacSRobert Mustacchi nvme_print_uint64(2, "Warning Composite Temperature Time",
20564a663bacSRobert Mustacchi hlog->hl_warn_temp_time, NULL, "min");
20574a663bacSRobert Mustacchi }
20584a663bacSRobert Mustacchi
20594a663bacSRobert Mustacchi if (idctl->ap_cctemp != 0) {
20604a663bacSRobert Mustacchi nvme_print_uint64(2, "Critical Composite Temperature Time",
20614a663bacSRobert Mustacchi hlog->hl_crit_temp_time, NULL, "min");
20624a663bacSRobert Mustacchi }
20634a663bacSRobert Mustacchi
20644a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_1 != 0) {
20654a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 1",
20664a663bacSRobert Mustacchi hlog->hl_temp_sensor_1);
20674a663bacSRobert Mustacchi }
20684a663bacSRobert Mustacchi
20694a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_2 != 0) {
20704a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 2",
20714a663bacSRobert Mustacchi hlog->hl_temp_sensor_2);
20724a663bacSRobert Mustacchi }
20734a663bacSRobert Mustacchi
20744a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_3 != 0) {
20754a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 3",
20764a663bacSRobert Mustacchi hlog->hl_temp_sensor_3);
20774a663bacSRobert Mustacchi }
20784a663bacSRobert Mustacchi
20794a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_4 != 0) {
20804a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 4",
20814a663bacSRobert Mustacchi hlog->hl_temp_sensor_4);
20824a663bacSRobert Mustacchi }
20834a663bacSRobert Mustacchi
20844a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_5 != 0) {
20854a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 5",
20864a663bacSRobert Mustacchi hlog->hl_temp_sensor_5);
20874a663bacSRobert Mustacchi }
20884a663bacSRobert Mustacchi
20894a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_6 != 0) {
20904a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 6",
20914a663bacSRobert Mustacchi hlog->hl_temp_sensor_6);
20924a663bacSRobert Mustacchi }
20934a663bacSRobert Mustacchi
20944a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_7 != 0) {
20954a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 7",
20964a663bacSRobert Mustacchi hlog->hl_temp_sensor_7);
20974a663bacSRobert Mustacchi }
20984a663bacSRobert Mustacchi
20994a663bacSRobert Mustacchi if (hlog->hl_temp_sensor_8 != 0) {
21004a663bacSRobert Mustacchi nvme_print_temp(2, "Temperature Sensor 8",
21014a663bacSRobert Mustacchi hlog->hl_temp_sensor_8);
21024a663bacSRobert Mustacchi }
21034a663bacSRobert Mustacchi
2104*533affcbSRobert Mustacchi if (!nvme_vers_atleast(version, &nvme_vers_1v3)) {
21054a663bacSRobert Mustacchi return;
21064a663bacSRobert Mustacchi }
21074a663bacSRobert Mustacchi
21084a663bacSRobert Mustacchi nvme_print_uint64(2, "Thermal Management Temp 1 Transition Count",
21094a663bacSRobert Mustacchi hlog->hl_tmtemp_1_tc, NULL, NULL);
21104a663bacSRobert Mustacchi
21114a663bacSRobert Mustacchi nvme_print_uint64(2, "Thermal Management Temp 2 Transition Count",
21124a663bacSRobert Mustacchi hlog->hl_tmtemp_2_tc, NULL, NULL);
21134a663bacSRobert Mustacchi
21144a663bacSRobert Mustacchi nvme_print_uint64(2, "Time for Thermal Management Temp 1",
21154a663bacSRobert Mustacchi hlog->hl_tmtemp_1_time, NULL, "sec");
21164a663bacSRobert Mustacchi
21174a663bacSRobert Mustacchi nvme_print_uint64(2, "Time for Thermal Management Temp 2",
21184a663bacSRobert Mustacchi hlog->hl_tmtemp_2_time, NULL, "sec");
21193d9b1a2aSHans Rosenfeld }
21203d9b1a2aSHans Rosenfeld
21213d9b1a2aSHans Rosenfeld /*
21223d9b1a2aSHans Rosenfeld * nvme_print_fwslot_log
21233d9b1a2aSHans Rosenfeld *
21243d9b1a2aSHans Rosenfeld * This function pretty-prints the firmware slot information.
21253d9b1a2aSHans Rosenfeld */
21263d9b1a2aSHans Rosenfeld void
nvme_print_fwslot_log(const nvme_fwslot_log_t * fwlog,const nvme_identify_ctrl_t * idctl)2127*533affcbSRobert Mustacchi nvme_print_fwslot_log(const nvme_fwslot_log_t *fwlog,
2128*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *idctl)
21293d9b1a2aSHans Rosenfeld {
21303d9b1a2aSHans Rosenfeld int i;
21313d9b1a2aSHans Rosenfeld
21328466ab88SHans Rosenfeld char str[NVME_FWVER_SZ + sizeof (" (read-only)")];
21338466ab88SHans Rosenfeld
21343d9b1a2aSHans Rosenfeld nvme_print(0, "Firmware Slot Information", -1, NULL);
21353d9b1a2aSHans Rosenfeld nvme_print_uint64(2, "Active Firmware Slot", fwlog->fw_afi, NULL, NULL);
2136cf840871SPaul Winder if (fwlog->fw_next != 0)
2137cf840871SPaul Winder nvme_print_uint64(2, "Next Firmware Slot", fwlog->fw_next,
2138cf840871SPaul Winder NULL, NULL);
21393d9b1a2aSHans Rosenfeld
21408466ab88SHans Rosenfeld
21418466ab88SHans Rosenfeld (void) snprintf(str, sizeof (str), "%.*s%s",
21428466ab88SHans Rosenfeld nvme_strlen(fwlog->fw_frs[0], sizeof (fwlog->fw_frs[0])),
21438466ab88SHans Rosenfeld fwlog->fw_frs[0], idctl->id_frmw.fw_readonly ? " (read-only)" : "");
21448466ab88SHans Rosenfeld nvme_print_str(2, "Firmware Revision for Slot", 1, str, sizeof (str));
21458466ab88SHans Rosenfeld
21468466ab88SHans Rosenfeld for (i = 1; i < idctl->id_frmw.fw_nslot; i++) {
21473d9b1a2aSHans Rosenfeld nvme_print_str(2, "Firmware Revision for Slot", i + 1,
2148cf840871SPaul Winder fwlog->fw_frs[i][0] == '\0' ? "<Unused>" :
21493d9b1a2aSHans Rosenfeld fwlog->fw_frs[i], sizeof (fwlog->fw_frs[i]));
21503d9b1a2aSHans Rosenfeld }
21513d9b1a2aSHans Rosenfeld }
21523d9b1a2aSHans Rosenfeld
21533d9b1a2aSHans Rosenfeld /*
21543d9b1a2aSHans Rosenfeld * nvme_print_feat_*
21553d9b1a2aSHans Rosenfeld *
21563d9b1a2aSHans Rosenfeld * These functions pretty-print the data structures returned by GET FEATURES.
21573d9b1a2aSHans Rosenfeld */
21583d9b1a2aSHans Rosenfeld void
nvme_print_feat_unknown(nvme_feat_output_t output,uint32_t cdw0,void * b,size_t s)2159*533affcbSRobert Mustacchi nvme_print_feat_unknown(nvme_feat_output_t output, uint32_t cdw0, void *b,
2160*533affcbSRobert Mustacchi size_t s)
2161*533affcbSRobert Mustacchi {
2162*533affcbSRobert Mustacchi if ((output & NVME_FEAT_OUTPUT_CDW0) != 0) {
2163*533affcbSRobert Mustacchi nvme_print_uint64(4, "cdw0", cdw0, "0x%"PRIx64, NULL);
2164*533affcbSRobert Mustacchi }
2165*533affcbSRobert Mustacchi
2166*533affcbSRobert Mustacchi if ((output & NVME_FEAT_OUTPUT_DATA) != 0) {
2167*533affcbSRobert Mustacchi nvme_print_hexbuf(4, "data", b, s);
2168*533affcbSRobert Mustacchi }
2169*533affcbSRobert Mustacchi }
2170*533affcbSRobert Mustacchi
2171*533affcbSRobert Mustacchi void
nvme_print_feat_arbitration(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2172*533affcbSRobert Mustacchi nvme_print_feat_arbitration(uint32_t cdw0, void *b, size_t s,
2173*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
21743d9b1a2aSHans Rosenfeld {
21753d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
21763d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
21773d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
21783d9b1a2aSHans Rosenfeld nvme_arbitration_t arb;
21793d9b1a2aSHans Rosenfeld
2180*533affcbSRobert Mustacchi arb.r = cdw0;
21813d9b1a2aSHans Rosenfeld if (arb.b.arb_ab != 7)
21823d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Arbitration Burst",
21833d9b1a2aSHans Rosenfeld 1 << arb.b.arb_ab, NULL, NULL);
21843d9b1a2aSHans Rosenfeld else
21853d9b1a2aSHans Rosenfeld nvme_print_str(4, "Arbitration Burst", 0,
21863d9b1a2aSHans Rosenfeld "no limit", 0);
21873d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Low Priority Weight",
21883d9b1a2aSHans Rosenfeld (uint16_t)arb.b.arb_lpw + 1, NULL, NULL);
21893d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Medium Priority Weight",
21903d9b1a2aSHans Rosenfeld (uint16_t)arb.b.arb_mpw + 1, NULL, NULL);
21913d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "High Priority Weight",
21923d9b1a2aSHans Rosenfeld (uint16_t)arb.b.arb_hpw + 1, NULL, NULL);
21933d9b1a2aSHans Rosenfeld }
21943d9b1a2aSHans Rosenfeld
21953d9b1a2aSHans Rosenfeld void
nvme_print_feat_power_mgmt(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2196*533affcbSRobert Mustacchi nvme_print_feat_power_mgmt(uint32_t cdw0, void *b, size_t s,
2197*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
21983d9b1a2aSHans Rosenfeld {
21993d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
22003d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
22013d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
22023d9b1a2aSHans Rosenfeld nvme_power_mgmt_t pm;
22033d9b1a2aSHans Rosenfeld
2204*533affcbSRobert Mustacchi pm.r = cdw0;
22053d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Power State", (uint8_t)pm.b.pm_ps,
22063d9b1a2aSHans Rosenfeld NULL, NULL);
22073d9b1a2aSHans Rosenfeld }
22083d9b1a2aSHans Rosenfeld
22093d9b1a2aSHans Rosenfeld void
nvme_print_feat_lba_range(uint32_t cdw0,void * buf,size_t bufsize,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2210*533affcbSRobert Mustacchi nvme_print_feat_lba_range(uint32_t cdw0, void *buf, size_t bufsize,
2211*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
22123d9b1a2aSHans Rosenfeld {
22133d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
22143d9b1a2aSHans Rosenfeld
22153d9b1a2aSHans Rosenfeld nvme_lba_range_type_t lrt;
22163d9b1a2aSHans Rosenfeld nvme_lba_range_t *lr;
22173d9b1a2aSHans Rosenfeld size_t n_lr;
22183d9b1a2aSHans Rosenfeld int i;
22193d9b1a2aSHans Rosenfeld
22203d9b1a2aSHans Rosenfeld if (buf == NULL)
22213d9b1a2aSHans Rosenfeld return;
22223d9b1a2aSHans Rosenfeld
2223*533affcbSRobert Mustacchi lrt.r = cdw0;
22243d9b1a2aSHans Rosenfeld lr = buf;
22253d9b1a2aSHans Rosenfeld
22263d9b1a2aSHans Rosenfeld n_lr = bufsize / sizeof (nvme_lba_range_t);
22273d9b1a2aSHans Rosenfeld if (n_lr > lrt.b.lr_num + 1)
22283d9b1a2aSHans Rosenfeld n_lr = lrt.b.lr_num + 1;
22293d9b1a2aSHans Rosenfeld
22303d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of LBA Ranges",
22313d9b1a2aSHans Rosenfeld (uint8_t)lrt.b.lr_num + 1, NULL, NULL);
22323d9b1a2aSHans Rosenfeld
22333d9b1a2aSHans Rosenfeld for (i = 0; i != n_lr; i++) {
22343d9b1a2aSHans Rosenfeld if (verbose == 0 && lr[i].lr_nlb == 0)
22353d9b1a2aSHans Rosenfeld continue;
22363d9b1a2aSHans Rosenfeld
22373d9b1a2aSHans Rosenfeld nvme_print(4, "LBA Range", i, NULL);
2238153f3212SHans Rosenfeld if (lr[i].lr_type < ARRAY_SIZE(lba_range_types))
22393d9b1a2aSHans Rosenfeld nvme_print_str(6, "Type", -1,
22403d9b1a2aSHans Rosenfeld lba_range_types[lr[i].lr_type], 0);
22413d9b1a2aSHans Rosenfeld else
22423d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Type",
22433d9b1a2aSHans Rosenfeld lr[i].lr_type, NULL, NULL);
22443d9b1a2aSHans Rosenfeld nvme_print(6, "Attributes", -1, NULL);
22453d9b1a2aSHans Rosenfeld nvme_print_bit(8, "Writable",
2246*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
22473d9b1a2aSHans Rosenfeld lr[i].lr_attr.lr_write, "yes", "no");
22483d9b1a2aSHans Rosenfeld nvme_print_bit(8, "Hidden",
2249*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
22503d9b1a2aSHans Rosenfeld lr[i].lr_attr.lr_hidden, "yes", "no");
22513d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Starting LBA",
22523d9b1a2aSHans Rosenfeld lr[i].lr_slba, NULL, NULL);
22533d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Number of Logical Blocks",
22543d9b1a2aSHans Rosenfeld lr[i].lr_nlb, NULL, NULL);
22553d9b1a2aSHans Rosenfeld nvme_print(6, "Unique Identifier", -1,
22563d9b1a2aSHans Rosenfeld "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x"
22573d9b1a2aSHans Rosenfeld "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
22583d9b1a2aSHans Rosenfeld lr[i].lr_guid[0], lr[i].lr_guid[1],
22593d9b1a2aSHans Rosenfeld lr[i].lr_guid[2], lr[i].lr_guid[3],
22603d9b1a2aSHans Rosenfeld lr[i].lr_guid[4], lr[i].lr_guid[5],
22613d9b1a2aSHans Rosenfeld lr[i].lr_guid[6], lr[i].lr_guid[7],
22623d9b1a2aSHans Rosenfeld lr[i].lr_guid[8], lr[i].lr_guid[9],
22633d9b1a2aSHans Rosenfeld lr[i].lr_guid[10], lr[i].lr_guid[11],
22643d9b1a2aSHans Rosenfeld lr[i].lr_guid[12], lr[i].lr_guid[13],
22653d9b1a2aSHans Rosenfeld lr[i].lr_guid[14], lr[i].lr_guid[15]);
22663d9b1a2aSHans Rosenfeld }
22673d9b1a2aSHans Rosenfeld }
22683d9b1a2aSHans Rosenfeld
22693d9b1a2aSHans Rosenfeld void
nvme_print_feat_temperature(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2270*533affcbSRobert Mustacchi nvme_print_feat_temperature(uint32_t cdw0, void *b, size_t s,
2271*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
22723d9b1a2aSHans Rosenfeld {
22733d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
22743d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
22753d9b1a2aSHans Rosenfeld nvme_temp_threshold_t tt;
22764a663bacSRobert Mustacchi char *label = b;
22773d9b1a2aSHans Rosenfeld
2278*533affcbSRobert Mustacchi tt.r = cdw0;
22794a663bacSRobert Mustacchi nvme_print_temp(4, label, tt.b.tt_tmpth);
22803d9b1a2aSHans Rosenfeld }
22813d9b1a2aSHans Rosenfeld
22823d9b1a2aSHans Rosenfeld void
nvme_print_feat_error(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2283*533affcbSRobert Mustacchi nvme_print_feat_error(uint32_t cdw0, void *b, size_t s,
2284*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
22853d9b1a2aSHans Rosenfeld {
22863d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
22873d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
22883d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
22893d9b1a2aSHans Rosenfeld nvme_error_recovery_t er;
22903d9b1a2aSHans Rosenfeld
2291*533affcbSRobert Mustacchi er.r = cdw0;
22923d9b1a2aSHans Rosenfeld if (er.b.er_tler > 0)
22933d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Time Limited Error Recovery",
22943d9b1a2aSHans Rosenfeld (uint32_t)er.b.er_tler * 100, NULL, "ms");
22953d9b1a2aSHans Rosenfeld else
22963d9b1a2aSHans Rosenfeld nvme_print_str(4, "Time Limited Error Recovery", -1,
22973d9b1a2aSHans Rosenfeld "no time limit", 0);
22983d9b1a2aSHans Rosenfeld }
22993d9b1a2aSHans Rosenfeld
23003d9b1a2aSHans Rosenfeld void
nvme_print_feat_write_cache(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2301*533affcbSRobert Mustacchi nvme_print_feat_write_cache(uint32_t cdw0, void *b, size_t s,
2302*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
23033d9b1a2aSHans Rosenfeld {
23043d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23053d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23063d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
23073d9b1a2aSHans Rosenfeld nvme_write_cache_t wc;
23083d9b1a2aSHans Rosenfeld
2309*533affcbSRobert Mustacchi wc.r = cdw0;
23103d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Volatile Write Cache",
2311*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23123d9b1a2aSHans Rosenfeld wc.b.wc_wce, "enabled", "disabled");
23133d9b1a2aSHans Rosenfeld }
23143d9b1a2aSHans Rosenfeld
23153d9b1a2aSHans Rosenfeld void
nvme_print_feat_nqueues(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2316*533affcbSRobert Mustacchi nvme_print_feat_nqueues(uint32_t cdw0, void *b, size_t s,
2317*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
23183d9b1a2aSHans Rosenfeld {
23193d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23203d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23213d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
23223d9b1a2aSHans Rosenfeld nvme_nqueues_t nq;
23233d9b1a2aSHans Rosenfeld
2324*533affcbSRobert Mustacchi nq.r = cdw0;
23253d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of Submission Queues",
23263d9b1a2aSHans Rosenfeld nq.b.nq_nsq + 1, NULL, NULL);
23273d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Number of Completion Queues",
23283d9b1a2aSHans Rosenfeld nq.b.nq_ncq + 1, NULL, NULL);
23293d9b1a2aSHans Rosenfeld }
23303d9b1a2aSHans Rosenfeld
23313d9b1a2aSHans Rosenfeld void
nvme_print_feat_intr_coal(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2332*533affcbSRobert Mustacchi nvme_print_feat_intr_coal(uint32_t cdw0, void *b, size_t s,
2333*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
23343d9b1a2aSHans Rosenfeld {
23353d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23363d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23373d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
23383d9b1a2aSHans Rosenfeld nvme_intr_coal_t ic;
23393d9b1a2aSHans Rosenfeld
2340*533affcbSRobert Mustacchi ic.r = cdw0;
23413d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Aggregation Threshold",
23423d9b1a2aSHans Rosenfeld ic.b.ic_thr + 1, NULL, NULL);
23433d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Aggregation Time",
23443d9b1a2aSHans Rosenfeld (uint16_t)ic.b.ic_time * 100, NULL, "us");
23453d9b1a2aSHans Rosenfeld }
23463d9b1a2aSHans Rosenfeld void
nvme_print_feat_intr_vect(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2347*533affcbSRobert Mustacchi nvme_print_feat_intr_vect(uint32_t cdw0, void *b, size_t s,
2348*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
23493d9b1a2aSHans Rosenfeld {
23503d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23513d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23523d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
23533d9b1a2aSHans Rosenfeld nvme_intr_vect_t iv;
23543d9b1a2aSHans Rosenfeld char *tmp;
23553d9b1a2aSHans Rosenfeld
2356*533affcbSRobert Mustacchi iv.r = cdw0;
23573d9b1a2aSHans Rosenfeld if (asprintf(&tmp, "Vector %d Coalescing Disable", iv.b.iv_iv) < 0)
23583d9b1a2aSHans Rosenfeld err(-1, "nvme_print_feat_common()");
23593d9b1a2aSHans Rosenfeld
23608d5300d3SRobert Mustacchi nvme_print_bit(4, tmp, iv.b.iv_cd,
2361*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23628d5300d3SRobert Mustacchi "yes", "no");
23633d9b1a2aSHans Rosenfeld }
23643d9b1a2aSHans Rosenfeld
23653d9b1a2aSHans Rosenfeld void
nvme_print_feat_write_atom(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2366*533affcbSRobert Mustacchi nvme_print_feat_write_atom(uint32_t cdw0, void *b, size_t s,
2367*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
23683d9b1a2aSHans Rosenfeld {
23693d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23703d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23713d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
23723d9b1a2aSHans Rosenfeld nvme_write_atomicity_t wa;
23733d9b1a2aSHans Rosenfeld
2374*533affcbSRobert Mustacchi wa.r = cdw0;
23758d5300d3SRobert Mustacchi nvme_print_bit(4, "Disable Normal", wa.b.wa_dn,
2376*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23778d5300d3SRobert Mustacchi "yes", "no");
23783d9b1a2aSHans Rosenfeld }
23793d9b1a2aSHans Rosenfeld
23803d9b1a2aSHans Rosenfeld void
nvme_print_feat_async_event(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * idctl,const nvme_version_t * version)2381*533affcbSRobert Mustacchi nvme_print_feat_async_event(uint32_t cdw0, void *b, size_t s,
2382*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *idctl, const nvme_version_t *version)
23833d9b1a2aSHans Rosenfeld {
23843d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
23853d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
23863d9b1a2aSHans Rosenfeld nvme_async_event_conf_t aec;
23873d9b1a2aSHans Rosenfeld
2388*533affcbSRobert Mustacchi aec.r = cdw0;
23893d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Available Space below threshold",
2390*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23913d9b1a2aSHans Rosenfeld aec.b.aec_avail, "enabled", "disabled");
23923d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Temperature above threshold",
2393*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23943d9b1a2aSHans Rosenfeld aec.b.aec_temp, "enabled", "disabled");
23953d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Device Reliability compromised",
2396*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
23973d9b1a2aSHans Rosenfeld aec.b.aec_reliab, "enabled", "disabled");
23983d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Media read-only",
2399*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
24003d9b1a2aSHans Rosenfeld aec.b.aec_readonly, "enabled", "disabled");
24018d5300d3SRobert Mustacchi if (idctl->id_vwc.vwc_present != 0) {
24023d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Volatile Memory Backup failed",
2403*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
24043d9b1a2aSHans Rosenfeld aec.b.aec_volatile, "enabled", "disabled");
24058d5300d3SRobert Mustacchi }
240604be5853SAndy Fiddaman
240704be5853SAndy Fiddaman /* NVMe 1.2 */
240804be5853SAndy Fiddaman nvme_print_bit(4, "Namespace attribute notices",
2409*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
241004be5853SAndy Fiddaman aec.b.aec_nsan, "enabled", "disabled");
241104be5853SAndy Fiddaman nvme_print_bit(4, "Firmware activation notices",
2412*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v2),
241304be5853SAndy Fiddaman aec.b.aec_fwact, "enabled", "disabled");
241404be5853SAndy Fiddaman
241504be5853SAndy Fiddaman /* NVMe 1.3 */
241604be5853SAndy Fiddaman nvme_print_bit(4, "Telemetry log notices",
2417*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v3),
241804be5853SAndy Fiddaman aec.b.aec_telln, "enabled", "disabled");
241904be5853SAndy Fiddaman
242004be5853SAndy Fiddaman /* NVMe 1.4 */
242104be5853SAndy Fiddaman nvme_print_bit(4, "ANA change notices",
2422*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
242304be5853SAndy Fiddaman aec.b.aec_ansacn, "enabled", "disabled");
242404be5853SAndy Fiddaman nvme_print_bit(4,
242504be5853SAndy Fiddaman "Predictable latency event aggr. LCNs",
2426*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
242704be5853SAndy Fiddaman aec.b.aec_plat, "enabled", "disabled");
242804be5853SAndy Fiddaman nvme_print_bit(4, "LBA status information notices",
2429*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
243004be5853SAndy Fiddaman aec.b.aec_lbasi, "enabled", "disabled");
243104be5853SAndy Fiddaman nvme_print_bit(4, "Endurance group event aggregate LCNs",
2432*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v4),
243304be5853SAndy Fiddaman aec.b.aec_egeal, "enabled", "disabled");
24343d9b1a2aSHans Rosenfeld }
24353d9b1a2aSHans Rosenfeld
24363d9b1a2aSHans Rosenfeld void
nvme_print_feat_auto_pst(uint32_t cdw0,void * buf,size_t bufsize,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2437*533affcbSRobert Mustacchi nvme_print_feat_auto_pst(uint32_t cdw0, void *buf, size_t bufsize,
2438*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
24393d9b1a2aSHans Rosenfeld {
24403d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
24413d9b1a2aSHans Rosenfeld
24423d9b1a2aSHans Rosenfeld nvme_auto_power_state_trans_t apst;
24433d9b1a2aSHans Rosenfeld nvme_auto_power_state_t *aps;
24443d9b1a2aSHans Rosenfeld int i;
24453d9b1a2aSHans Rosenfeld int cnt = bufsize / sizeof (nvme_auto_power_state_t);
24463d9b1a2aSHans Rosenfeld
24473d9b1a2aSHans Rosenfeld if (buf == NULL)
24483d9b1a2aSHans Rosenfeld return;
24493d9b1a2aSHans Rosenfeld
2450*533affcbSRobert Mustacchi apst.r = cdw0;
24513d9b1a2aSHans Rosenfeld aps = buf;
24523d9b1a2aSHans Rosenfeld
24533d9b1a2aSHans Rosenfeld nvme_print_bit(4, "Autonomous Power State Transition",
2454*533affcbSRobert Mustacchi nvme_vers_atleast(version, &nvme_vers_1v0),
24553d9b1a2aSHans Rosenfeld apst.b.apst_apste, "enabled", "disabled");
24563d9b1a2aSHans Rosenfeld for (i = 0; i != cnt; i++) {
24573d9b1a2aSHans Rosenfeld if (aps[i].apst_itps == 0 && aps[i].apst_itpt == 0)
24583d9b1a2aSHans Rosenfeld break;
24593d9b1a2aSHans Rosenfeld
24603d9b1a2aSHans Rosenfeld nvme_print(4, "Power State", i, NULL);
24613d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Idle Transition Power State",
24623d9b1a2aSHans Rosenfeld (uint16_t)aps[i].apst_itps, NULL, NULL);
24633d9b1a2aSHans Rosenfeld nvme_print_uint64(6, "Idle Time Prior to Transition",
24643d9b1a2aSHans Rosenfeld aps[i].apst_itpt, NULL, "ms");
24653d9b1a2aSHans Rosenfeld }
24663d9b1a2aSHans Rosenfeld }
24673d9b1a2aSHans Rosenfeld
24683d9b1a2aSHans Rosenfeld void
nvme_print_feat_progress(uint32_t cdw0,void * b,size_t s,const nvme_identify_ctrl_t * id,const nvme_version_t * version)2469*533affcbSRobert Mustacchi nvme_print_feat_progress(uint32_t cdw0, void *b, size_t s,
2470*533affcbSRobert Mustacchi const nvme_identify_ctrl_t *id, const nvme_version_t *version)
24713d9b1a2aSHans Rosenfeld {
24723d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(b));
24733d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(s));
24743d9b1a2aSHans Rosenfeld _NOTE(ARGUNUSED(id));
24753d9b1a2aSHans Rosenfeld nvme_software_progress_marker_t spm;
24763d9b1a2aSHans Rosenfeld
2477*533affcbSRobert Mustacchi spm.r = cdw0;
24783d9b1a2aSHans Rosenfeld nvme_print_uint64(4, "Pre-Boot Software Load Count",
24793d9b1a2aSHans Rosenfeld spm.b.spm_pbslc, NULL, NULL);
24803d9b1a2aSHans Rosenfeld }
2481cf840871SPaul Winder
2482*533affcbSRobert Mustacchi /*
2483*533affcbSRobert Mustacchi * This is designed to print out a large buffer as decipherable hexadecimal.
2484*533affcbSRobert Mustacchi * This is intended for log pages or command output where there is unknown
2485*533affcbSRobert Mustacchi * printing. For an inline hex buffer, see nvme_print_hexbuf(). Our expectation
2486*533affcbSRobert Mustacchi * here is that we have approximately 6 digits worth of address on the left then
2487*533affcbSRobert Mustacchi * we'll spell out each byte, followed by the translated form on the right. Each
2488*533affcbSRobert Mustacchi * of these groups is separated by pipes.
2489*533affcbSRobert Mustacchi */
2490*533affcbSRobert Mustacchi void
nvmeadm_dump_hex(const uint8_t * buf,size_t len)2491*533affcbSRobert Mustacchi nvmeadm_dump_hex(const uint8_t *buf, size_t len)
2492cf840871SPaul Winder {
2493*533affcbSRobert Mustacchi size_t off = 0;
2494*533affcbSRobert Mustacchi
2495*533affcbSRobert Mustacchi if (len == 0) {
2496*533affcbSRobert Mustacchi return;
2497cf840871SPaul Winder }
2498cf840871SPaul Winder
2499*533affcbSRobert Mustacchi /*
2500*533affcbSRobert Mustacchi * First we print the header.
2501*533affcbSRobert Mustacchi */
2502*533affcbSRobert Mustacchi (void) printf(" ");
2503*533affcbSRobert Mustacchi (void) printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
2504*533affcbSRobert Mustacchi (void) printf(" 0123456789abcdef\n");
2505*533affcbSRobert Mustacchi
2506*533affcbSRobert Mustacchi while (len > 0) {
2507*533affcbSRobert Mustacchi size_t nents = MIN(len, 16);
2508*533affcbSRobert Mustacchi len -= nents;
2509*533affcbSRobert Mustacchi
2510*533affcbSRobert Mustacchi (void) printf("0x%06x |", off);
2511*533affcbSRobert Mustacchi for (size_t i = 0; i < nents; i++) {
2512*533affcbSRobert Mustacchi (void) printf(" %02x", buf[i]);
2513*533affcbSRobert Mustacchi }
2514*533affcbSRobert Mustacchi
2515*533affcbSRobert Mustacchi for (size_t i = nents; i < 16; i++) {
2516*533affcbSRobert Mustacchi (void) printf(" ");
2517*533affcbSRobert Mustacchi }
2518*533affcbSRobert Mustacchi
2519*533affcbSRobert Mustacchi (void) printf(" | ");
2520*533affcbSRobert Mustacchi
2521*533affcbSRobert Mustacchi for (size_t i = 0; i < nents; i++) {
2522*533affcbSRobert Mustacchi if (isprint(buf[i])) {
2523*533affcbSRobert Mustacchi (void) printf("%c", buf[i]);
2524*533affcbSRobert Mustacchi } else {
2525*533affcbSRobert Mustacchi (void) putc('.', stdout);
2526*533affcbSRobert Mustacchi }
2527*533affcbSRobert Mustacchi }
2528*533affcbSRobert Mustacchi
2529*533affcbSRobert Mustacchi (void) putc('\n', stdout);
2530*533affcbSRobert Mustacchi buf += nents;
2531*533affcbSRobert Mustacchi off += nents;
2532*533affcbSRobert Mustacchi }
2533cf840871SPaul Winder }
2534