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"
46 #define IDENTIFY_USAGE \
47 "identify [-x [-v]] <controller id|namespace id>\n"
50 print_namespace(struct nvme_namespace_data *nsdata)
53 uint32_t lbaf, lbads, ms, rp;
54 uint8_t thin_prov, ptype;
57 thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) &
58 NVME_NS_DATA_NSFEAT_THIN_PROV_MASK;
60 flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
61 NVME_NS_DATA_FLBAS_FORMAT_MASK;
63 printf("Size (in LBAs): %lld (%lldM)\n",
64 (long long)nsdata->nsze,
65 (long long)nsdata->nsze / 1024 / 1024);
66 printf("Capacity (in LBAs): %lld (%lldM)\n",
67 (long long)nsdata->ncap,
68 (long long)nsdata->ncap / 1024 / 1024);
69 printf("Utilization (in LBAs): %lld (%lldM)\n",
70 (long long)nsdata->nuse,
71 (long long)nsdata->nuse / 1024 / 1024);
72 printf("Thin Provisioning: %s\n",
73 thin_prov ? "Supported" : "Not Supported");
74 printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1);
75 printf("Current LBA Format: LBA Format #%02d\n", flbas_fmt);
76 printf("Data Protection Caps: %s%s%s%s%s%s\n",
77 (nsdata->dpc == 0) ? "Not Supported" : "",
78 ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_END_SHIFT) &
79 NVME_NS_DATA_DPC_MD_END_MASK) ? "Last Bytes, " : "",
80 ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_START_SHIFT) &
81 NVME_NS_DATA_DPC_MD_START_MASK) ? "First Bytes, " : "",
82 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT3_SHIFT) &
83 NVME_NS_DATA_DPC_PIT3_MASK) ? "Type 3, " : "",
84 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_SHIFT) &
85 NVME_NS_DATA_DPC_PIT2_MASK) ? "Type 2, " : "",
86 ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_MASK) &
87 NVME_NS_DATA_DPC_PIT1_MASK) ? "Type 1" : "");
88 printf("Data Protection Settings: ");
89 ptype = (nsdata->dps >> NVME_NS_DATA_DPS_PIT_SHIFT) &
90 NVME_NS_DATA_DPS_PIT_MASK;
92 printf("Type %d, %s Bytes\n", ptype,
93 ((nsdata->dps >> NVME_NS_DATA_DPS_MD_START_SHIFT) &
94 NVME_NS_DATA_DPS_MD_START_MASK) ? "First" : "Last");
96 printf("Not Enabled\n");
98 printf("Multi-Path I/O Capabilities: %s%s\n",
99 (nsdata->nmic == 0) ? "Not Supported" : "",
100 ((nsdata->nmic >> NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) &
101 NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK) ? "May be shared" : "");
102 printf("Reservation Capabilities: %s%s%s%s%s%s%s%s%s\n",
103 (nsdata->rescap == 0) ? "Not Supported" : "",
104 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_IEKEY13_SHIFT) &
105 NVME_NS_DATA_RESCAP_IEKEY13_MASK) ? "IEKEY13, " : "",
106 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_AR_SHIFT) &
107 NVME_NS_DATA_RESCAP_EX_AC_AR_MASK) ? "EX_AC_AR, " : "",
108 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_AR_SHIFT) &
109 NVME_NS_DATA_RESCAP_WR_EX_AR_MASK) ? "WR_EX_AR, " : "",
110 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_RO_SHIFT) &
111 NVME_NS_DATA_RESCAP_EX_AC_RO_MASK) ? "EX_AC_RO, " : "",
112 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_RO_SHIFT) &
113 NVME_NS_DATA_RESCAP_WR_EX_RO_MASK) ? "WR_EX_RO, " : "",
114 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_SHIFT) &
115 NVME_NS_DATA_RESCAP_EX_AC_MASK) ? "EX_AC, " : "",
116 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_SHIFT) &
117 NVME_NS_DATA_RESCAP_WR_EX_MASK) ? "WR_EX, " : "",
118 ((nsdata->rescap >> NVME_NS_DATA_RESCAP_PTPL_SHIFT) &
119 NVME_NS_DATA_RESCAP_PTPL_MASK) ? "PTPL" : "");
120 printf("Format Progress Indicator: ");
121 if ((nsdata->fpi >> NVME_NS_DATA_FPI_SUPP_SHIFT) &
122 NVME_NS_DATA_FPI_SUPP_MASK) {
123 printf("%u%% remains\n",
124 (nsdata->fpi >> NVME_NS_DATA_FPI_PERC_SHIFT) &
125 NVME_NS_DATA_FPI_PERC_MASK);
127 printf("Not Supported\n");
128 t = (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_READ_SHIFT) &
129 NVME_NS_DATA_DLFEAT_READ_MASK;
130 printf("Deallocate Logical Block: Read %s%s%s\n",
131 (t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" :
132 (t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" :
133 (t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown",
134 (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_DWZ_SHIFT) &
135 NVME_NS_DATA_DLFEAT_DWZ_MASK ? ", Write Zero" : "",
136 (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_GCRC_SHIFT) &
137 NVME_NS_DATA_DLFEAT_GCRC_MASK ? ", Guard CRC" : "");
138 printf("Optimal I/O Boundary (LBAs): %u\n", nsdata->noiob);
139 printf("Globally Unique Identifier: ");
140 for (i = 0; i < sizeof(nsdata->nguid); i++)
141 printf("%02x", nsdata->nguid[i]);
143 printf("IEEE EUI64: ");
144 for (i = 0; i < sizeof(nsdata->eui64); i++)
145 printf("%02x", nsdata->eui64[i]);
147 for (i = 0; i <= nsdata->nlbaf; i++) {
148 lbaf = nsdata->lbaf[i];
149 lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
150 NVME_NS_DATA_LBAF_LBADS_MASK;
151 ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
152 NVME_NS_DATA_LBAF_MS_MASK;
153 rp = (lbaf >> NVME_NS_DATA_LBAF_RP_SHIFT) &
154 NVME_NS_DATA_LBAF_RP_MASK;
155 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d"
156 " Performance: %s\n",
157 i, 1 << lbads, ms, (rp == 0) ? "Best" :
158 (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded");
163 identify_ctrlr(const struct nvme_function *nf, int argc, char *argv[])
165 struct nvme_controller_data cdata;
166 int ch, fd, hexflag = 0, hexlength;
169 while ((ch = getopt(argc, argv, "vx")) != -1) {
182 /* Check that a controller was specified. */
186 open_dev(argv[optind], &fd, 1, 1);
187 read_controller_data(fd, &cdata);
191 if (verboseflag == 1)
192 hexlength = sizeof(struct nvme_controller_data);
194 hexlength = offsetof(struct nvme_controller_data,
196 print_hex(&cdata, hexlength);
200 if (verboseflag == 1) {
201 fprintf(stderr, "-v not currently supported without -x\n");
205 nvme_print_controller(&cdata);
210 identify_ns(const struct nvme_function *nf,int argc, char *argv[])
212 struct nvme_namespace_data nsdata;
214 int ch, fd, hexflag = 0, hexlength;
218 while ((ch = getopt(argc, argv, "vx")) != -1) {
231 /* Check that a namespace was specified. */
236 * Check if the specified device node exists before continuing.
237 * This is a cleaner check for cases where the correct controller
238 * is specified, but an invalid namespace on that controller.
240 open_dev(argv[optind], &fd, 1, 1);
244 * We send IDENTIFY commands to the controller, not the namespace,
245 * since it is an admin cmd. The namespace ID will be specified in
246 * the IDENTIFY command itself. So parse the namespace's device node
247 * string to get the controller substring and namespace ID.
249 parse_ns_str(argv[optind], path, &nsid);
250 open_dev(path, &fd, 1, 1);
251 read_namespace_data(fd, nsid, &nsdata);
255 if (verboseflag == 1)
256 hexlength = sizeof(struct nvme_namespace_data);
258 hexlength = offsetof(struct nvme_namespace_data,
260 print_hex(&nsdata, hexlength);
264 if (verboseflag == 1) {
265 fprintf(stderr, "-v not currently supported without -x\n");
269 print_namespace(&nsdata);
274 identify(const struct nvme_function *nf, int argc, char *argv[])
281 while (getopt(argc, argv, "vx") != -1) ;
283 /* Check that a controller or namespace was specified. */
287 target = argv[optind];
293 * If device node contains "ns", we consider it a namespace,
294 * otherwise, consider it a controller.
296 if (strstr(target, NVME_NS_PREFIX) == NULL)
297 identify_ctrlr(nf, argc, argv);
299 identify_ns(nf, argc, argv);
302 NVME_COMMAND(top, identify, identify, IDENTIFY_USAGE);