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 | #include <sys/cdefs.h> |
---|
33 | __FBSDID("$FreeBSD$"); |
---|
34 | |
---|
35 | #include <sys/param.h> |
---|
36 | |
---|
37 | #include <ctype.h> |
---|
38 | #include <err.h> |
---|
39 | #include <fcntl.h> |
---|
40 | #include <stddef.h> |
---|
41 | #include <stdio.h> |
---|
42 | #include <stdlib.h> |
---|
43 | #include <string.h> |
---|
44 | #include <unistd.h> |
---|
45 | |
---|
46 | #include "nvmecontrol.h" |
---|
47 | #include "nvmecontrol_ext.h" |
---|
48 | |
---|
49 | void |
---|
50 | nvme_print_controller(struct nvme_controller_data *cdata) |
---|
51 | { |
---|
52 | uint8_t str[128]; |
---|
53 | char cbuf[UINT128_DIG + 1]; |
---|
54 | uint16_t oncs, oacs; |
---|
55 | uint8_t compare, write_unc, dsm, t; |
---|
56 | uint8_t security, fmt, fw, nsmgmt; |
---|
57 | uint8_t fw_slot1_ro, fw_num_slots; |
---|
58 | uint8_t ns_smart; |
---|
59 | uint8_t sqes_max, sqes_min; |
---|
60 | uint8_t cqes_max, cqes_min; |
---|
61 | |
---|
62 | oncs = cdata->oncs; |
---|
63 | compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) & |
---|
64 | NVME_CTRLR_DATA_ONCS_COMPARE_MASK; |
---|
65 | write_unc = (oncs >> NVME_CTRLR_DATA_ONCS_WRITE_UNC_SHIFT) & |
---|
66 | NVME_CTRLR_DATA_ONCS_WRITE_UNC_MASK; |
---|
67 | dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) & |
---|
68 | NVME_CTRLR_DATA_ONCS_DSM_MASK; |
---|
69 | |
---|
70 | oacs = cdata->oacs; |
---|
71 | security = (oacs >> NVME_CTRLR_DATA_OACS_SECURITY_SHIFT) & |
---|
72 | NVME_CTRLR_DATA_OACS_SECURITY_MASK; |
---|
73 | fmt = (oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) & |
---|
74 | NVME_CTRLR_DATA_OACS_FORMAT_MASK; |
---|
75 | fw = (oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) & |
---|
76 | NVME_CTRLR_DATA_OACS_FIRMWARE_MASK; |
---|
77 | nsmgmt = (oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & |
---|
78 | NVME_CTRLR_DATA_OACS_NSMGMT_MASK; |
---|
79 | |
---|
80 | fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) & |
---|
81 | NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK; |
---|
82 | fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) & |
---|
83 | NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK; |
---|
84 | |
---|
85 | ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) & |
---|
86 | NVME_CTRLR_DATA_LPA_NS_SMART_MASK; |
---|
87 | |
---|
88 | sqes_min = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MIN_SHIFT) & |
---|
89 | NVME_CTRLR_DATA_SQES_MIN_MASK; |
---|
90 | sqes_max = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MAX_SHIFT) & |
---|
91 | NVME_CTRLR_DATA_SQES_MAX_MASK; |
---|
92 | |
---|
93 | cqes_min = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MIN_SHIFT) & |
---|
94 | NVME_CTRLR_DATA_CQES_MIN_MASK; |
---|
95 | cqes_max = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MAX_SHIFT) & |
---|
96 | NVME_CTRLR_DATA_CQES_MAX_MASK; |
---|
97 | |
---|
98 | printf("Controller Capabilities/Features\n"); |
---|
99 | printf("================================\n"); |
---|
100 | printf("Vendor ID: %04x\n", cdata->vid); |
---|
101 | printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); |
---|
102 | nvme_strvis(str, cdata->sn, sizeof(str), NVME_SERIAL_NUMBER_LENGTH); |
---|
103 | printf("Serial Number: %s\n", str); |
---|
104 | nvme_strvis(str, cdata->mn, sizeof(str), NVME_MODEL_NUMBER_LENGTH); |
---|
105 | printf("Model Number: %s\n", str); |
---|
106 | nvme_strvis(str, cdata->fr, sizeof(str), NVME_FIRMWARE_REVISION_LENGTH); |
---|
107 | printf("Firmware Version: %s\n", str); |
---|
108 | printf("Recommended Arb Burst: %d\n", cdata->rab); |
---|
109 | printf("IEEE OUI Identifier: %02x %02x %02x\n", |
---|
110 | cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); |
---|
111 | printf("Multi-Path I/O Capabilities: %s%s%s%s%s\n", |
---|
112 | (cdata->mic == 0) ? "Not Supported" : "", |
---|
113 | ((cdata->mic >> NVME_CTRLR_DATA_MIC_ANAR_SHIFT) & |
---|
114 | NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "Asymmetric, " : "", |
---|
115 | ((cdata->mic >> NVME_CTRLR_DATA_MIC_SRIOVVF_SHIFT) & |
---|
116 | NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "SR-IOV VF, " : "", |
---|
117 | ((cdata->mic >> NVME_CTRLR_DATA_MIC_MCTRLRS_SHIFT) & |
---|
118 | NVME_CTRLR_DATA_MIC_MCTRLRS_MASK) ? "Multiple controllers, " : "", |
---|
119 | ((cdata->mic >> NVME_CTRLR_DATA_MIC_MPORTS_SHIFT) & |
---|
120 | NVME_CTRLR_DATA_MIC_MPORTS_MASK) ? "Multiple ports" : ""); |
---|
121 | /* TODO: Use CAP.MPSMIN to determine true memory page size. */ |
---|
122 | printf("Max Data Transfer Size: "); |
---|
123 | if (cdata->mdts == 0) |
---|
124 | printf("Unlimited\n"); |
---|
125 | else |
---|
126 | printf("%ld bytes\n", PAGE_SIZE * (1L << cdata->mdts)); |
---|
127 | printf("Controller ID: 0x%04x\n", cdata->ctrlr_id); |
---|
128 | printf("Version: %d.%d.%d\n", |
---|
129 | (cdata->ver >> 16) & 0xffff, (cdata->ver >> 8) & 0xff, |
---|
130 | cdata->ver & 0xff); |
---|
131 | printf("\n"); |
---|
132 | |
---|
133 | printf("Admin Command Set Attributes\n"); |
---|
134 | printf("============================\n"); |
---|
135 | printf("Security Send/Receive: %s\n", |
---|
136 | security ? "Supported" : "Not Supported"); |
---|
137 | printf("Format NVM: %s\n", |
---|
138 | fmt ? "Supported" : "Not Supported"); |
---|
139 | printf("Firmware Activate/Download: %s\n", |
---|
140 | fw ? "Supported" : "Not Supported"); |
---|
141 | printf("Namespace Managment: %s\n", |
---|
142 | nsmgmt ? "Supported" : "Not Supported"); |
---|
143 | printf("Device Self-test: %sSupported\n", |
---|
144 | ((oacs >> NVME_CTRLR_DATA_OACS_SELFTEST_SHIFT) & |
---|
145 | NVME_CTRLR_DATA_OACS_SELFTEST_MASK) ? "" : "Not "); |
---|
146 | printf("Directives: %sSupported\n", |
---|
147 | ((oacs >> NVME_CTRLR_DATA_OACS_DIRECTIVES_SHIFT) & |
---|
148 | NVME_CTRLR_DATA_OACS_DIRECTIVES_MASK) ? "" : "Not "); |
---|
149 | printf("NVMe-MI Send/Receive: %sSupported\n", |
---|
150 | ((oacs >> NVME_CTRLR_DATA_OACS_NVMEMI_SHIFT) & |
---|
151 | NVME_CTRLR_DATA_OACS_NVMEMI_MASK) ? "" : "Not "); |
---|
152 | printf("Virtualization Management: %sSupported\n", |
---|
153 | ((oacs >> NVME_CTRLR_DATA_OACS_VM_SHIFT) & |
---|
154 | NVME_CTRLR_DATA_OACS_VM_MASK) ? "" : "Not "); |
---|
155 | printf("Doorbell Buffer Config: %sSupported\n", |
---|
156 | ((oacs >> NVME_CTRLR_DATA_OACS_DBBUFFER_SHIFT) & |
---|
157 | NVME_CTRLR_DATA_OACS_DBBUFFER_MASK) ? "" : "Not "); |
---|
158 | printf("Get LBA Status: %sSupported\n", |
---|
159 | ((oacs >> NVME_CTRLR_DATA_OACS_GETLBA_SHIFT) & |
---|
160 | NVME_CTRLR_DATA_OACS_GETLBA_MASK) ? "" : "Not "); |
---|
161 | printf("Sanitize: "); |
---|
162 | if (cdata->sanicap != 0) { |
---|
163 | printf("%s%s%s\n", |
---|
164 | ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) & |
---|
165 | NVME_CTRLR_DATA_SANICAP_CES_MASK) ? "crypto, " : "", |
---|
166 | ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) & |
---|
167 | NVME_CTRLR_DATA_SANICAP_BES_MASK) ? "block, " : "", |
---|
168 | ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) & |
---|
169 | NVME_CTRLR_DATA_SANICAP_OWS_MASK) ? "overwrite" : ""); |
---|
170 | } else { |
---|
171 | printf("Not Supported\n"); |
---|
172 | } |
---|
173 | printf("Abort Command Limit: %d\n", cdata->acl+1); |
---|
174 | printf("Async Event Request Limit: %d\n", cdata->aerl+1); |
---|
175 | printf("Number of Firmware Slots: "); |
---|
176 | if (fw != 0) |
---|
177 | printf("%d\n", fw_num_slots); |
---|
178 | else |
---|
179 | printf("N/A\n"); |
---|
180 | printf("Firmware Slot 1 Read-Only: "); |
---|
181 | if (fw != 0) |
---|
182 | printf("%s\n", fw_slot1_ro ? "Yes" : "No"); |
---|
183 | else |
---|
184 | printf("N/A\n"); |
---|
185 | printf("Per-Namespace SMART Log: %s\n", |
---|
186 | ns_smart ? "Yes" : "No"); |
---|
187 | printf("Error Log Page Entries: %d\n", cdata->elpe+1); |
---|
188 | printf("Number of Power States: %d\n", cdata->npss+1); |
---|
189 | if (cdata->ver >= 0x010200) { |
---|
190 | printf("Total NVM Capacity: %s bytes\n", |
---|
191 | uint128_to_str(to128(cdata->untncap.tnvmcap), |
---|
192 | cbuf, sizeof(cbuf))); |
---|
193 | printf("Unallocated NVM Capacity: %s bytes\n", |
---|
194 | uint128_to_str(to128(cdata->untncap.unvmcap), |
---|
195 | cbuf, sizeof(cbuf))); |
---|
196 | } |
---|
197 | printf("Host Buffer Preferred Size: %d bytes\n", cdata->hmpre); |
---|
198 | printf("Host Buffer Minimum Size: %d bytes\n", cdata->hmmin); |
---|
199 | |
---|
200 | printf("\n"); |
---|
201 | printf("NVM Command Set Attributes\n"); |
---|
202 | printf("==========================\n"); |
---|
203 | printf("Submission Queue Entry Size\n"); |
---|
204 | printf(" Max: %d\n", 1 << sqes_max); |
---|
205 | printf(" Min: %d\n", 1 << sqes_min); |
---|
206 | printf("Completion Queue Entry Size\n"); |
---|
207 | printf(" Max: %d\n", 1 << cqes_max); |
---|
208 | printf(" Min: %d\n", 1 << cqes_min); |
---|
209 | printf("Number of Namespaces: %d\n", cdata->nn); |
---|
210 | printf("Compare Command: %s\n", |
---|
211 | compare ? "Supported" : "Not Supported"); |
---|
212 | printf("Write Uncorrectable Command: %s\n", |
---|
213 | write_unc ? "Supported" : "Not Supported"); |
---|
214 | printf("Dataset Management Command: %s\n", |
---|
215 | dsm ? "Supported" : "Not Supported"); |
---|
216 | printf("Write Zeroes Command: %sSupported\n", |
---|
217 | ((oncs >> NVME_CTRLR_DATA_ONCS_WRZERO_SHIFT) & |
---|
218 | NVME_CTRLR_DATA_ONCS_WRZERO_MASK) ? "" : "Not "); |
---|
219 | printf("Save Features: %sSupported\n", |
---|
220 | ((oncs >> NVME_CTRLR_DATA_ONCS_SAVEFEAT_SHIFT) & |
---|
221 | NVME_CTRLR_DATA_ONCS_SAVEFEAT_MASK) ? "" : "Not "); |
---|
222 | printf("Reservations: %sSupported\n", |
---|
223 | ((oncs >> NVME_CTRLR_DATA_ONCS_RESERV_SHIFT) & |
---|
224 | NVME_CTRLR_DATA_ONCS_RESERV_MASK) ? "" : "Not "); |
---|
225 | printf("Timestamp feature: %sSupported\n", |
---|
226 | ((oncs >> NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT) & |
---|
227 | NVME_CTRLR_DATA_ONCS_TIMESTAMP_MASK) ? "" : "Not "); |
---|
228 | printf("Verify feature: %sSupported\n", |
---|
229 | ((oncs >> NVME_CTRLR_DATA_ONCS_VERIFY_SHIFT) & |
---|
230 | NVME_CTRLR_DATA_ONCS_VERIFY_MASK) ? "" : "Not "); |
---|
231 | printf("Fused Operation Support: %s%s\n", |
---|
232 | (cdata->fuses == 0) ? "Not Supported" : "", |
---|
233 | ((cdata->fuses >> NVME_CTRLR_DATA_FUSES_CNW_SHIFT) & |
---|
234 | NVME_CTRLR_DATA_FUSES_CNW_MASK) ? "Compare and Write" : ""); |
---|
235 | printf("Format NVM Attributes: %s%s Erase, %s Format\n", |
---|
236 | ((cdata->fna >> NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_SHIFT) & |
---|
237 | NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK) ? "Crypto Erase, " : "", |
---|
238 | ((cdata->fna >> NVME_CTRLR_DATA_FNA_ERASE_ALL_SHIFT) & |
---|
239 | NVME_CTRLR_DATA_FNA_ERASE_ALL_MASK) ? "All-NVM" : "Per-NS", |
---|
240 | ((cdata->fna >> NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT) & |
---|
241 | NVME_CTRLR_DATA_FNA_FORMAT_ALL_MASK) ? "All-NVM" : "Per-NS"); |
---|
242 | t = (cdata->vwc >> NVME_CTRLR_DATA_VWC_ALL_SHIFT) & |
---|
243 | NVME_CTRLR_DATA_VWC_ALL_MASK; |
---|
244 | printf("Volatile Write Cache: %s%s\n", |
---|
245 | ((cdata->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & |
---|
246 | NVME_CTRLR_DATA_VWC_PRESENT_MASK) ? "Present" : "Not Present", |
---|
247 | (t == NVME_CTRLR_DATA_VWC_ALL_NO) ? ", no flush all" : |
---|
248 | (t == NVME_CTRLR_DATA_VWC_ALL_YES) ? ", flush all" : ""); |
---|
249 | |
---|
250 | if (cdata->ver >= 0x010201) |
---|
251 | printf("\nNVM Subsystem Name: %.256s\n", cdata->subnqn); |
---|
252 | } |
---|