source: rtems-libbsd/freebsd/sbin/nvmecontrol/identify.c @ e6acc15

5
Last change on this file since e6acc15 was e6acc15, checked in by Sebastian Huber <sebastian.huber@…>, on 09/20/19 at 05:57:01

NVMECONTROL(8): Port to RTEMS

Update #3821.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (C) 2012-2013 Intel Corporation
7 * All rights reserved.
8 * Copyright (C) 2018-2019 Alexander Motin <mav@FreeBSD.org>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifdef __rtems__
33#include <machine/rtems-bsd-program.h>
34#endif /* __rtems__ */
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include <sys/param.h>
39
40#include <ctype.h>
41#include <err.h>
42#include <fcntl.h>
43#include <stdbool.h>
44#include <stddef.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50#include "nvmecontrol.h"
51#include "nvmecontrol_ext.h"
52
53#define NONE 0xfffffffeu
54
55static struct options {
56        bool            hex;
57        bool            verbose;
58        const char      *dev;
59        uint32_t        nsid;
60} opt = {
61        .hex = false,
62        .verbose = false,
63        .dev = NULL,
64        .nsid = NONE,
65};
66
67void
68print_namespace(struct nvme_namespace_data *nsdata)
69{
70        char cbuf[UINT128_DIG + 1];
71        uint32_t        i;
72        uint32_t        lbaf, lbads, ms, rp;
73        uint8_t         thin_prov, ptype;
74        uint8_t         flbas_fmt, t;
75
76        thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) &
77                NVME_NS_DATA_NSFEAT_THIN_PROV_MASK;
78
79        flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
80                NVME_NS_DATA_FLBAS_FORMAT_MASK;
81
82        printf("Size:                        %lld blocks\n",
83            (long long)nsdata->nsze);
84        printf("Capacity:                    %lld blocks\n",
85            (long long)nsdata->ncap);
86        printf("Utilization:                 %lld blocks\n",
87            (long long)nsdata->nuse);
88        printf("Thin Provisioning:           %s\n",
89                thin_prov ? "Supported" : "Not Supported");
90        printf("Number of LBA Formats:       %d\n", nsdata->nlbaf+1);
91        printf("Current LBA Format:          LBA Format #%02d\n", flbas_fmt);
92        printf("Data Protection Caps:        %s%s%s%s%s%s\n",
93            (nsdata->dpc == 0) ? "Not Supported" : "",
94            ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_END_SHIFT) &
95             NVME_NS_DATA_DPC_MD_END_MASK) ? "Last Bytes, " : "",
96            ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_START_SHIFT) &
97             NVME_NS_DATA_DPC_MD_START_MASK) ? "First Bytes, " : "",
98            ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT3_SHIFT) &
99             NVME_NS_DATA_DPC_PIT3_MASK) ? "Type 3, " : "",
100            ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_SHIFT) &
101             NVME_NS_DATA_DPC_PIT2_MASK) ? "Type 2, " : "",
102            ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_MASK) &
103             NVME_NS_DATA_DPC_PIT1_MASK) ? "Type 1" : "");
104        printf("Data Protection Settings:    ");
105        ptype = (nsdata->dps >> NVME_NS_DATA_DPS_PIT_SHIFT) &
106            NVME_NS_DATA_DPS_PIT_MASK;
107        if (ptype) {
108                printf("Type %d, %s Bytes\n", ptype,
109                    ((nsdata->dps >> NVME_NS_DATA_DPS_MD_START_SHIFT) &
110                     NVME_NS_DATA_DPS_MD_START_MASK) ? "First" : "Last");
111        } else {
112                printf("Not Enabled\n");
113        }
114        printf("Multi-Path I/O Capabilities: %s%s\n",
115            (nsdata->nmic == 0) ? "Not Supported" : "",
116            ((nsdata->nmic >> NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) &
117             NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK) ? "May be shared" : "");
118        printf("Reservation Capabilities:    %s%s%s%s%s%s%s%s%s\n",
119            (nsdata->rescap == 0) ? "Not Supported" : "",
120            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_IEKEY13_SHIFT) &
121             NVME_NS_DATA_RESCAP_IEKEY13_MASK) ? "IEKEY13, " : "",
122            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_AR_SHIFT) &
123             NVME_NS_DATA_RESCAP_EX_AC_AR_MASK) ? "EX_AC_AR, " : "",
124            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_AR_SHIFT) &
125             NVME_NS_DATA_RESCAP_WR_EX_AR_MASK) ? "WR_EX_AR, " : "",
126            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_RO_SHIFT) &
127             NVME_NS_DATA_RESCAP_EX_AC_RO_MASK) ? "EX_AC_RO, " : "",
128            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_RO_SHIFT) &
129             NVME_NS_DATA_RESCAP_WR_EX_RO_MASK) ? "WR_EX_RO, " : "",
130            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_SHIFT) &
131             NVME_NS_DATA_RESCAP_EX_AC_MASK) ? "EX_AC, " : "",
132            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_SHIFT) &
133             NVME_NS_DATA_RESCAP_WR_EX_MASK) ? "WR_EX, " : "",
134            ((nsdata->rescap >> NVME_NS_DATA_RESCAP_PTPL_SHIFT) &
135             NVME_NS_DATA_RESCAP_PTPL_MASK) ? "PTPL" : "");
136        printf("Format Progress Indicator:   ");
137        if ((nsdata->fpi >> NVME_NS_DATA_FPI_SUPP_SHIFT) &
138            NVME_NS_DATA_FPI_SUPP_MASK) {
139                printf("%u%% remains\n",
140                    (nsdata->fpi >> NVME_NS_DATA_FPI_PERC_SHIFT) &
141                    NVME_NS_DATA_FPI_PERC_MASK);
142        } else
143                printf("Not Supported\n");
144        t = (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_READ_SHIFT) &
145            NVME_NS_DATA_DLFEAT_READ_MASK;
146        printf("Deallocate Logical Block:    Read %s%s%s\n",
147            (t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" :
148            (t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" :
149            (t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown",
150            (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_DWZ_SHIFT) &
151             NVME_NS_DATA_DLFEAT_DWZ_MASK ? ", Write Zero" : "",
152            (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_GCRC_SHIFT) &
153             NVME_NS_DATA_DLFEAT_GCRC_MASK ? ", Guard CRC" : "");
154        printf("Optimal I/O Boundary:        %u blocks\n", nsdata->noiob);
155        printf("NVM Capacity:                %s bytes\n",
156           uint128_to_str(to128(nsdata->nvmcap), cbuf, sizeof(cbuf)));
157        if ((nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_NPVALID_SHIFT) &
158            NVME_NS_DATA_NSFEAT_NPVALID_MASK) {
159                printf("Preferred Write Granularity: %u blocks",
160                    nsdata->npwg + 1);
161                printf("Preferred Write Alignment:   %u blocks",
162                    nsdata->npwa + 1);
163                printf("Preferred Deallocate Granul: %u blocks",
164                    nsdata->npdg + 1);
165                printf("Preferred Deallocate Align:  %u blocks",
166                    nsdata->npda + 1);
167                printf("Optimal Write Size:          %u blocks",
168                    nsdata->nows + 1);
169        }
170        printf("Globally Unique Identifier:  ");
171        for (i = 0; i < sizeof(nsdata->nguid); i++)
172                printf("%02x", nsdata->nguid[i]);
173        printf("\n");
174        printf("IEEE EUI64:                  ");
175        for (i = 0; i < sizeof(nsdata->eui64); i++)
176                printf("%02x", nsdata->eui64[i]);
177        printf("\n");
178        for (i = 0; i <= nsdata->nlbaf; i++) {
179                lbaf = nsdata->lbaf[i];
180                lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
181                        NVME_NS_DATA_LBAF_LBADS_MASK;
182                ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
183                        NVME_NS_DATA_LBAF_MS_MASK;
184                rp = (lbaf >> NVME_NS_DATA_LBAF_RP_SHIFT) &
185                        NVME_NS_DATA_LBAF_RP_MASK;
186                printf("LBA Format #%02d: Data Size: %5d  Metadata Size: %5d"
187                    "  Performance: %s\n",
188                    i, 1 << lbads, ms, (rp == 0) ? "Best" :
189                    (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded");
190        }
191}
192
193static void
194identify_ctrlr(int fd)
195{
196        struct nvme_controller_data     cdata;
197        int                             hexlength;
198
199        read_controller_data(fd, &cdata);
200        close(fd);
201
202        if (opt.hex) {
203                if (opt.verbose)
204                        hexlength = sizeof(struct nvme_controller_data);
205                else
206                        hexlength = offsetof(struct nvme_controller_data,
207                            reserved8);
208                print_hex(&cdata, hexlength);
209                exit(0);
210        }
211
212        nvme_print_controller(&cdata);
213        exit(0);
214}
215
216static void
217identify_ns(int fd, uint32_t nsid)
218{
219        struct nvme_namespace_data      nsdata;
220        int                             hexlength;
221
222        read_namespace_data(fd, nsid, &nsdata);
223        close(fd);
224
225        if (opt.hex) {
226                if (opt.verbose)
227                        hexlength = sizeof(struct nvme_namespace_data);
228                else
229                        hexlength = offsetof(struct nvme_namespace_data,
230                            reserved6);
231                print_hex(&nsdata, hexlength);
232                exit(0);
233        }
234
235        print_namespace(&nsdata);
236        exit(0);
237}
238
239static void
240identify(const struct cmd *f, int argc, char *argv[])
241{
242        char            *path;
243        int             fd;
244        uint32_t        nsid;
245
246        arg_parse(argc, argv, f);
247
248        open_dev(opt.dev, &fd, 1, 1);
249        get_nsid(fd, &path, &nsid);
250        if (nsid != 0) {
251                /*
252                 * We got namespace device, but we need to send IDENTIFY
253                 * commands to the controller, not the namespace, since it
254                 * is an admin cmd.  The namespace ID will be specified in
255                 * the IDENTIFY command itself.
256                 */
257                close(fd);
258                open_dev(path, &fd, 1, 1);
259        }
260        free(path);
261        if (opt.nsid != NONE)
262                nsid = opt.nsid;
263
264        if (nsid == 0)
265                identify_ctrlr(fd);
266        else
267                identify_ns(fd, nsid);
268}
269
270static const struct opts identify_opts[] = {
271#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
272        OPT("hex", 'x', arg_none, opt, hex,
273            "Print identiy information in hex"),
274        OPT("verbose", 'v', arg_none, opt, verbose,
275            "More verbosity: print entire identify table"),
276        OPT("nsid", 'n', arg_uint32, opt, nsid,
277            "Namespace ID to use if not in device name"),
278        { NULL, 0, arg_none, NULL, NULL }
279};
280#undef OPT
281
282static const struct args identify_args[] = {
283        { arg_string, &opt.dev, "controller-id|namespace-id" },
284        { arg_none, NULL, NULL },
285};
286
287static struct cmd identify_cmd = {
288        .name = "identify",
289        .fn = identify,
290        .descr = "Print summary of the IDENTIFY information",
291        .ctx_size = sizeof(opt),
292        .opts = identify_opts,
293        .args = identify_args,
294};
295
296CMD_COMMAND(identify_cmd);
Note: See TracBrowser for help on using the repository browser.