2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2012-2013 Intel Corporation
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
43 #include "nvmecontrol.h"
44 #include "nvmecontrol_ext.h"
47 print_namespace(struct nvme_namespace_data *nsdata)
50 uint32_t lbaf, lbads, ms, rp;
51 uint8_t thin_prov, ptype;
54 thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) &
55 NVME_NS_DATA_NSFEAT_THIN_PROV_MASK;
57 flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
58 NVME_NS_DATA_FLBAS_FORMAT_MASK;
60 printf("Size (in LBAs): %lld (%lldM)\n",
61 (long long)nsdata->nsze,
62 (long long)nsdata->nsze / 1024 / 1024);
63 printf("Capacity (in LBAs): %lld (%lldM)\n",
64 (long long)nsdata->ncap,
65 (long long)nsdata->ncap / 1024 / 1024);
66 printf("Utilization (in LBAs): %lld (%lldM)\n",
67 (long long)nsdata->nuse,
68 (long long)nsdata->nuse / 1024 / 1024);
69 printf("Thin Provisioning: %s\n",
70 thin_prov ? "Supported" : "Not Supported");
71 printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1);
72 printf("Current LBA Format: LBA Format #%02d\n", flbas_fmt);
73 printf("Data Protection Caps: %s%s%s%s%s%s\n",
74 (nsdata->dpc == 0) ? "Not Supported" : "",
75 ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_END_SHIFT) &
76 NVME_NS_DATA_DPC_MD_END_MASK) ? "Last Bytes, " : "",
77 ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_START_SHIFT) &
78 NVME_NS_DATA_DPC_MD_START_MASK) ? "First Bytes, " : "",
79 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT3_SHIFT) &
80 NVME_NS_DATA_DPC_PIT3_MASK) ? "Type 3, " : "",
81 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_SHIFT) &
82 NVME_NS_DATA_DPC_PIT2_MASK) ? "Type 2, " : "",
83 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_MASK) &
84 NVME_NS_DATA_DPC_PIT1_MASK) ? "Type 1" : "");
85 printf("Data Protection Settings: ");
86 ptype = (nsdata->dps >> NVME_NS_DATA_DPS_PIT_SHIFT) &
87 NVME_NS_DATA_DPS_PIT_MASK;
89 printf("Type %d, %s Bytes\n", ptype,
90 ((nsdata->dps >> NVME_NS_DATA_DPS_MD_START_SHIFT) &
91 NVME_NS_DATA_DPS_MD_START_MASK) ? "First" : "Last");
93 printf("Not Enabled\n");
95 printf("Multi-Path I/O Capabilities: %s%s\n",
96 (nsdata->nmic == 0) ? "Not Supported" : "",
97 ((nsdata->nmic >> NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) &
98 NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK) ? "May be shared" : "");
99 printf("Reservation Capabilities: %s%s%s%s%s%s%s%s%s\n",
100 (nsdata->rescap == 0) ? "Not Supported" : "",
101 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_IEKEY13_SHIFT) &
102 NVME_NS_DATA_RESCAP_IEKEY13_MASK) ? "IEKEY13, " : "",
103 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_AR_SHIFT) &
104 NVME_NS_DATA_RESCAP_EX_AC_AR_MASK) ? "EX_AC_AR, " : "",
105 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_AR_SHIFT) &
106 NVME_NS_DATA_RESCAP_WR_EX_AR_MASK) ? "WR_EX_AR, " : "",
107 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_RO_SHIFT) &
108 NVME_NS_DATA_RESCAP_EX_AC_RO_MASK) ? "EX_AC_RO, " : "",
109 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_RO_SHIFT) &
110 NVME_NS_DATA_RESCAP_WR_EX_RO_MASK) ? "WR_EX_RO, " : "",
111 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_SHIFT) &
112 NVME_NS_DATA_RESCAP_EX_AC_MASK) ? "EX_AC, " : "",
113 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_SHIFT) &
114 NVME_NS_DATA_RESCAP_WR_EX_MASK) ? "WR_EX, " : "",
115 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_PTPL_SHIFT) &
116 NVME_NS_DATA_RESCAP_PTPL_MASK) ? "PTPL" : "");
117 printf("Format Progress Indicator: ");
118 if ((nsdata->fpi >> NVME_NS_DATA_FPI_SUPP_SHIFT) &
119 NVME_NS_DATA_FPI_SUPP_MASK) {
120 printf("%u%% remains\n",
121 (nsdata->fpi >> NVME_NS_DATA_FPI_PERC_SHIFT) &
122 NVME_NS_DATA_FPI_PERC_MASK);
124 printf("Not Supported\n");
125 t = (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_READ_SHIFT) &
126 NVME_NS_DATA_DLFEAT_READ_MASK;
127 printf("Deallocate Logical Block: Read %s%s%s\n",
128 (t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" :
129 (t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" :
130 (t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown",
131 (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_DWZ_SHIFT) &
132 NVME_NS_DATA_DLFEAT_DWZ_MASK ? ", Write Zero" : "",
133 (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_GCRC_SHIFT) &
134 NVME_NS_DATA_DLFEAT_GCRC_MASK ? ", Guard CRC" : "");
135 printf("Optimal I/O Boundary (LBAs): %u\n", nsdata->noiob);
136 printf("Globally Unique Identifier: ");
137 for (i = 0; i < sizeof(nsdata->nguid); i++)
138 printf("%02x", nsdata->nguid[i]);
140 printf("IEEE EUI64: ");
141 for (i = 0; i < sizeof(nsdata->eui64); i++)
142 printf("%02x", nsdata->eui64[i]);
144 for (i = 0; i <= nsdata->nlbaf; i++) {
145 lbaf = nsdata->lbaf[i];
146 lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
147 NVME_NS_DATA_LBAF_LBADS_MASK;
148 ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
149 NVME_NS_DATA_LBAF_MS_MASK;
150 rp = (lbaf >> NVME_NS_DATA_LBAF_RP_SHIFT) &
151 NVME_NS_DATA_LBAF_RP_MASK;
152 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d"
153 " Performance: %s\n",
154 i, 1 << lbads, ms, (rp == 0) ? "Best" :
155 (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded");
162 fprintf(stderr, "usage:\n");
163 fprintf(stderr, IDENTIFY_USAGE);
168 identify_ctrlr(int argc, char *argv[])
170 struct nvme_controller_data cdata;
171 int ch, fd, hexflag = 0, hexlength;
174 while ((ch = getopt(argc, argv, "vx")) != -1) {
187 /* Check that a controller was specified. */
191 open_dev(argv[optind], &fd, 1, 1);
192 read_controller_data(fd, &cdata);
196 if (verboseflag == 1)
197 hexlength = sizeof(struct nvme_controller_data);
199 hexlength = offsetof(struct nvme_controller_data,
201 print_hex(&cdata, hexlength);
205 if (verboseflag == 1) {
206 fprintf(stderr, "-v not currently supported without -x\n");
210 nvme_print_controller(&cdata);
215 identify_ns(int argc, char *argv[])
217 struct nvme_namespace_data nsdata;
219 int ch, fd, hexflag = 0, hexlength;
223 while ((ch = getopt(argc, argv, "vx")) != -1) {
236 /* Check that a namespace was specified. */
241 * Check if the specified device node exists before continuing.
242 * This is a cleaner check for cases where the correct controller
243 * is specified, but an invalid namespace on that controller.
245 open_dev(argv[optind], &fd, 1, 1);
249 * We send IDENTIFY commands to the controller, not the namespace,
250 * since it is an admin cmd. The namespace ID will be specified in
251 * the IDENTIFY command itself. So parse the namespace's device node
252 * string to get the controller substring and namespace ID.
254 parse_ns_str(argv[optind], path, &nsid);
255 open_dev(path, &fd, 1, 1);
256 read_namespace_data(fd, nsid, &nsdata);
260 if (verboseflag == 1)
261 hexlength = sizeof(struct nvme_namespace_data);
263 hexlength = offsetof(struct nvme_namespace_data,
265 print_hex(&nsdata, hexlength);
269 if (verboseflag == 1) {
270 fprintf(stderr, "-v not currently supported without -x\n");
274 print_namespace(&nsdata);
279 identify(int argc, char *argv[])
286 while (getopt(argc, argv, "vx") != -1) ;
288 /* Check that a controller or namespace was specified. */
292 target = argv[optind];
298 * If device node contains "ns", we consider it a namespace,
299 * otherwise, consider it a controller.
301 if (strstr(target, NVME_NS_PREFIX) == NULL)
302 identify_ctrlr(argc, argv);
304 identify_ns(argc, argv);