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 printf("Optimal I/O Boundary (LBAs): %u\n", nsdata->noiob);
129 printf("Globally Unique Identifier: ");
130 for (i = 0; i < sizeof(nsdata->nguid); i++)
131 printf("%02x", nsdata->nguid[i]);
133 printf("IEEE EUI64: ");
134 for (i = 0; i < sizeof(nsdata->eui64); i++)
135 printf("%02x", nsdata->eui64[i]);
137 for (i = 0; i <= nsdata->nlbaf; i++) {
138 lbaf = nsdata->lbaf[i];
139 lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
140 NVME_NS_DATA_LBAF_LBADS_MASK;
141 ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
142 NVME_NS_DATA_LBAF_MS_MASK;
143 rp = (lbaf >> NVME_NS_DATA_LBAF_RP_SHIFT) &
144 NVME_NS_DATA_LBAF_RP_MASK;
145 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d"
146 " Performance: %s\n",
147 i, 1 << lbads, ms, (rp == 0) ? "Best" :
148 (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded");
153 identify_ctrlr(struct nvme_function *nf, int argc, char *argv[])
155 struct nvme_controller_data cdata;
156 int ch, fd, hexflag = 0, hexlength;
159 while ((ch = getopt(argc, argv, "vx")) != -1) {
172 /* Check that a controller was specified. */
176 open_dev(argv[optind], &fd, 1, 1);
177 read_controller_data(fd, &cdata);
181 if (verboseflag == 1)
182 hexlength = sizeof(struct nvme_controller_data);
184 hexlength = offsetof(struct nvme_controller_data,
186 print_hex(&cdata, hexlength);
190 if (verboseflag == 1) {
191 fprintf(stderr, "-v not currently supported without -x\n");
195 nvme_print_controller(&cdata);
200 identify_ns(struct nvme_function *nf,int argc, char *argv[])
202 struct nvme_namespace_data nsdata;
204 int ch, fd, hexflag = 0, hexlength;
208 while ((ch = getopt(argc, argv, "vx")) != -1) {
221 /* Check that a namespace was specified. */
226 * Check if the specified device node exists before continuing.
227 * This is a cleaner check for cases where the correct controller
228 * is specified, but an invalid namespace on that controller.
230 open_dev(argv[optind], &fd, 1, 1);
234 * We send IDENTIFY commands to the controller, not the namespace,
235 * since it is an admin cmd. The namespace ID will be specified in
236 * the IDENTIFY command itself. So parse the namespace's device node
237 * string to get the controller substring and namespace ID.
239 parse_ns_str(argv[optind], path, &nsid);
240 open_dev(path, &fd, 1, 1);
241 read_namespace_data(fd, nsid, &nsdata);
245 if (verboseflag == 1)
246 hexlength = sizeof(struct nvme_namespace_data);
248 hexlength = offsetof(struct nvme_namespace_data,
250 print_hex(&nsdata, hexlength);
254 if (verboseflag == 1) {
255 fprintf(stderr, "-v not currently supported without -x\n");
259 print_namespace(&nsdata);
264 identify(struct nvme_function *nf, int argc, char *argv[])
271 while (getopt(argc, argv, "vx") != -1) ;
273 /* Check that a controller or namespace was specified. */
277 target = argv[optind];
283 * If device node contains "ns", we consider it a namespace,
284 * otherwise, consider it a controller.
286 if (strstr(target, NVME_NS_PREFIX) == NULL)
287 identify_ctrlr(nf, argc, argv);
289 identify_ns(nf, argc, argv);
292 NVME_COMMAND(top, identify, identify, IDENTIFY_USAGE);