1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2012-2013 Intel Corporation 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 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 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <stddef.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "nvmecontrol.h" 44 45 static void 46 print_controller(struct nvme_controller_data *cdata) 47 { 48 uint8_t str[128]; 49 char cbuf[UINT128_DIG + 1]; 50 uint16_t oncs, oacs; 51 uint8_t compare, write_unc, dsm, vwc_present; 52 uint8_t security, fmt, fw, nsmgmt; 53 uint8_t fw_slot1_ro, fw_num_slots; 54 uint8_t ns_smart; 55 uint8_t sqes_max, sqes_min; 56 uint8_t cqes_max, cqes_min; 57 58 oncs = cdata->oncs; 59 compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) & 60 NVME_CTRLR_DATA_ONCS_COMPARE_MASK; 61 write_unc = (oncs >> NVME_CTRLR_DATA_ONCS_WRITE_UNC_SHIFT) & 62 NVME_CTRLR_DATA_ONCS_WRITE_UNC_MASK; 63 dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) & 64 NVME_CTRLR_DATA_ONCS_DSM_MASK; 65 vwc_present = (cdata->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & 66 NVME_CTRLR_DATA_VWC_PRESENT_MASK; 67 68 oacs = cdata->oacs; 69 security = (oacs >> NVME_CTRLR_DATA_OACS_SECURITY_SHIFT) & 70 NVME_CTRLR_DATA_OACS_SECURITY_MASK; 71 fmt = (oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) & 72 NVME_CTRLR_DATA_OACS_FORMAT_MASK; 73 fw = (oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) & 74 NVME_CTRLR_DATA_OACS_FIRMWARE_MASK; 75 nsmgmt = (oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 76 NVME_CTRLR_DATA_OACS_NSMGMT_MASK; 77 78 fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) & 79 NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK; 80 fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) & 81 NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK; 82 83 ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) & 84 NVME_CTRLR_DATA_LPA_NS_SMART_MASK; 85 86 sqes_min = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MIN_SHIFT) & 87 NVME_CTRLR_DATA_SQES_MIN_MASK; 88 sqes_max = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MAX_SHIFT) & 89 NVME_CTRLR_DATA_SQES_MAX_MASK; 90 91 cqes_min = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MIN_SHIFT) & 92 NVME_CTRLR_DATA_CQES_MIN_MASK; 93 cqes_max = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MAX_SHIFT) & 94 NVME_CTRLR_DATA_CQES_MAX_MASK; 95 96 printf("Controller Capabilities/Features\n"); 97 printf("================================\n"); 98 printf("Vendor ID: %04x\n", cdata->vid); 99 printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); 100 nvme_strvis(str, cdata->sn, sizeof(str), NVME_SERIAL_NUMBER_LENGTH); 101 printf("Serial Number: %s\n", str); 102 nvme_strvis(str, cdata->mn, sizeof(str), NVME_MODEL_NUMBER_LENGTH); 103 printf("Model Number: %s\n", str); 104 nvme_strvis(str, cdata->fr, sizeof(str), NVME_FIRMWARE_REVISION_LENGTH); 105 printf("Firmware Version: %s\n", str); 106 printf("Recommended Arb Burst: %d\n", cdata->rab); 107 printf("IEEE OUI Identifier: %02x %02x %02x\n", 108 cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); 109 printf("Multi-Interface Cap: %02x\n", cdata->mic); 110 /* TODO: Use CAP.MPSMIN to determine true memory page size. */ 111 printf("Max Data Transfer Size: "); 112 if (cdata->mdts == 0) 113 printf("Unlimited\n"); 114 else 115 printf("%d\n", PAGE_SIZE * (1 << cdata->mdts)); 116 printf("Controller ID: 0x%02x\n", cdata->ctrlr_id); 117 printf("\n"); 118 119 printf("Admin Command Set Attributes\n"); 120 printf("============================\n"); 121 printf("Security Send/Receive: %s\n", 122 security ? "Supported" : "Not Supported"); 123 printf("Format NVM: %s\n", 124 fmt ? "Supported" : "Not Supported"); 125 printf("Firmware Activate/Download: %s\n", 126 fw ? "Supported" : "Not Supported"); 127 printf("Namespace Managment: %s\n", 128 nsmgmt ? "Supported" : "Not Supported"); 129 printf("Abort Command Limit: %d\n", cdata->acl+1); 130 printf("Async Event Request Limit: %d\n", cdata->aerl+1); 131 printf("Number of Firmware Slots: "); 132 if (fw != 0) 133 printf("%d\n", fw_num_slots); 134 else 135 printf("N/A\n"); 136 printf("Firmware Slot 1 Read-Only: "); 137 if (fw != 0) 138 printf("%s\n", fw_slot1_ro ? "Yes" : "No"); 139 else 140 printf("N/A\n"); 141 printf("Per-Namespace SMART Log: %s\n", 142 ns_smart ? "Yes" : "No"); 143 printf("Error Log Page Entries: %d\n", cdata->elpe+1); 144 printf("Number of Power States: %d\n", cdata->npss+1); 145 146 printf("\n"); 147 printf("NVM Command Set Attributes\n"); 148 printf("==========================\n"); 149 printf("Submission Queue Entry Size\n"); 150 printf(" Max: %d\n", 1 << sqes_max); 151 printf(" Min: %d\n", 1 << sqes_min); 152 printf("Completion Queue Entry Size\n"); 153 printf(" Max: %d\n", 1 << cqes_max); 154 printf(" Min: %d\n", 1 << cqes_min); 155 printf("Number of Namespaces: %d\n", cdata->nn); 156 printf("Compare Command: %s\n", 157 compare ? "Supported" : "Not Supported"); 158 printf("Write Uncorrectable Command: %s\n", 159 write_unc ? "Supported" : "Not Supported"); 160 printf("Dataset Management Command: %s\n", 161 dsm ? "Supported" : "Not Supported"); 162 printf("Volatile Write Cache: %s\n", 163 vwc_present ? "Present" : "Not Present"); 164 165 if (nsmgmt) { 166 printf("\n"); 167 printf("Namespace Drive Attributes\n"); 168 printf("==========================\n"); 169 printf("NVM total cap: %s\n", 170 uint128_to_str(to128(cdata->untncap.tnvmcap), cbuf, sizeof(cbuf))); 171 printf("NVM unallocated cap: %s\n", 172 uint128_to_str(to128(cdata->untncap.unvmcap), cbuf, sizeof(cbuf))); 173 } 174 } 175 176 static void 177 print_namespace(struct nvme_namespace_data *nsdata) 178 { 179 uint32_t i; 180 uint32_t lbaf, lbads, ms; 181 uint8_t thin_prov; 182 uint8_t flbas_fmt; 183 184 thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) & 185 NVME_NS_DATA_NSFEAT_THIN_PROV_MASK; 186 187 flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) & 188 NVME_NS_DATA_FLBAS_FORMAT_MASK; 189 190 printf("Size (in LBAs): %lld (%lldM)\n", 191 (long long)nsdata->nsze, 192 (long long)nsdata->nsze / 1024 / 1024); 193 printf("Capacity (in LBAs): %lld (%lldM)\n", 194 (long long)nsdata->ncap, 195 (long long)nsdata->ncap / 1024 / 1024); 196 printf("Utilization (in LBAs): %lld (%lldM)\n", 197 (long long)nsdata->nuse, 198 (long long)nsdata->nuse / 1024 / 1024); 199 printf("Thin Provisioning: %s\n", 200 thin_prov ? "Supported" : "Not Supported"); 201 printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); 202 printf("Current LBA Format: LBA Format #%02d\n", flbas_fmt); 203 for (i = 0; i <= nsdata->nlbaf; i++) { 204 lbaf = nsdata->lbaf[i]; 205 lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) & 206 NVME_NS_DATA_LBAF_LBADS_MASK; 207 ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) & 208 NVME_NS_DATA_LBAF_MS_MASK; 209 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n", 210 i, 1 << lbads, ms); 211 } 212 } 213 214 static void 215 identify_usage(void) 216 { 217 fprintf(stderr, "usage:\n"); 218 fprintf(stderr, IDENTIFY_USAGE); 219 exit(1); 220 } 221 222 static void 223 identify_ctrlr(int argc, char *argv[]) 224 { 225 struct nvme_controller_data cdata; 226 int ch, fd, hexflag = 0, hexlength; 227 int verboseflag = 0; 228 229 while ((ch = getopt(argc, argv, "vx")) != -1) { 230 switch ((char)ch) { 231 case 'v': 232 verboseflag = 1; 233 break; 234 case 'x': 235 hexflag = 1; 236 break; 237 default: 238 identify_usage(); 239 } 240 } 241 242 /* Check that a controller was specified. */ 243 if (optind >= argc) 244 identify_usage(); 245 246 open_dev(argv[optind], &fd, 1, 1); 247 read_controller_data(fd, &cdata); 248 close(fd); 249 250 if (hexflag == 1) { 251 if (verboseflag == 1) 252 hexlength = sizeof(struct nvme_controller_data); 253 else 254 hexlength = offsetof(struct nvme_controller_data, 255 reserved5); 256 print_hex(&cdata, hexlength); 257 exit(0); 258 } 259 260 if (verboseflag == 1) { 261 fprintf(stderr, "-v not currently supported without -x\n"); 262 identify_usage(); 263 } 264 265 print_controller(&cdata); 266 exit(0); 267 } 268 269 static void 270 identify_ns(int argc, char *argv[]) 271 { 272 struct nvme_namespace_data nsdata; 273 char path[64]; 274 int ch, fd, hexflag = 0, hexlength, nsid; 275 int verboseflag = 0; 276 277 while ((ch = getopt(argc, argv, "vx")) != -1) { 278 switch ((char)ch) { 279 case 'v': 280 verboseflag = 1; 281 break; 282 case 'x': 283 hexflag = 1; 284 break; 285 default: 286 identify_usage(); 287 } 288 } 289 290 /* Check that a namespace was specified. */ 291 if (optind >= argc) 292 identify_usage(); 293 294 /* 295 * Check if the specified device node exists before continuing. 296 * This is a cleaner check for cases where the correct controller 297 * is specified, but an invalid namespace on that controller. 298 */ 299 open_dev(argv[optind], &fd, 1, 1); 300 close(fd); 301 302 /* 303 * We send IDENTIFY commands to the controller, not the namespace, 304 * since it is an admin cmd. The namespace ID will be specified in 305 * the IDENTIFY command itself. So parse the namespace's device node 306 * string to get the controller substring and namespace ID. 307 */ 308 parse_ns_str(argv[optind], path, &nsid); 309 open_dev(path, &fd, 1, 1); 310 read_namespace_data(fd, nsid, &nsdata); 311 close(fd); 312 313 if (hexflag == 1) { 314 if (verboseflag == 1) 315 hexlength = sizeof(struct nvme_namespace_data); 316 else 317 hexlength = offsetof(struct nvme_namespace_data, 318 reserved6); 319 print_hex(&nsdata, hexlength); 320 exit(0); 321 } 322 323 if (verboseflag == 1) { 324 fprintf(stderr, "-v not currently supported without -x\n"); 325 identify_usage(); 326 } 327 328 print_namespace(&nsdata); 329 exit(0); 330 } 331 332 void 333 identify(int argc, char *argv[]) 334 { 335 char *target; 336 337 if (argc < 2) 338 identify_usage(); 339 340 while (getopt(argc, argv, "vx") != -1) ; 341 342 /* Check that a controller or namespace was specified. */ 343 if (optind >= argc) 344 identify_usage(); 345 346 target = argv[optind]; 347 348 optreset = 1; 349 optind = 1; 350 351 /* 352 * If device node contains "ns", we consider it a namespace, 353 * otherwise, consider it a controller. 354 */ 355 if (strstr(target, NVME_NS_PREFIX) == NULL) 356 identify_ctrlr(argc, argv); 357 else 358 identify_ns(argc, argv); 359 } 360