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 51 printf("Controller Capabilities/Features\n"); 52 printf("================================\n"); 53 printf("Vendor ID: %04x\n", cdata->vid); 54 printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); 55 nvme_strvis(str, cdata->sn, sizeof(str), NVME_SERIAL_NUMBER_LENGTH); 56 printf("Serial Number: %s\n", str); 57 nvme_strvis(str, cdata->mn, sizeof(str), NVME_MODEL_NUMBER_LENGTH); 58 printf("Model Number: %s\n", str); 59 nvme_strvis(str, cdata->fr, sizeof(str), NVME_FIRMWARE_REVISION_LENGTH); 60 printf("Firmware Version: %s\n", str); 61 printf("Recommended Arb Burst: %d\n", cdata->rab); 62 printf("IEEE OUI Identifier: %02x %02x %02x\n", 63 cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); 64 printf("Multi-Interface Cap: %02x\n", cdata->mic); 65 /* TODO: Use CAP.MPSMIN to determine true memory page size. */ 66 printf("Max Data Transfer Size: "); 67 if (cdata->mdts == 0) 68 printf("Unlimited\n"); 69 else 70 printf("%d\n", PAGE_SIZE * (1 << cdata->mdts)); 71 printf("Controller ID: 0x%02x\n", cdata->ctrlr_id); 72 printf("\n"); 73 74 printf("Admin Command Set Attributes\n"); 75 printf("============================\n"); 76 printf("Security Send/Receive: %s\n", 77 cdata->oacs.security ? "Supported" : "Not Supported"); 78 printf("Format NVM: %s\n", 79 cdata->oacs.format ? "Supported" : "Not Supported"); 80 printf("Firmware Activate/Download: %s\n", 81 cdata->oacs.firmware ? "Supported" : "Not Supported"); 82 printf("Namespace Managment: %s\n", 83 cdata->oacs.nsmgmt ? "Supported" : "Not Supported"); 84 printf("Abort Command Limit: %d\n", cdata->acl+1); 85 printf("Async Event Request Limit: %d\n", cdata->aerl+1); 86 printf("Number of Firmware Slots: "); 87 if (cdata->oacs.firmware != 0) 88 printf("%d\n", cdata->frmw.num_slots); 89 else 90 printf("N/A\n"); 91 printf("Firmware Slot 1 Read-Only: "); 92 if (cdata->oacs.firmware != 0) 93 printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No"); 94 else 95 printf("N/A\n"); 96 printf("Per-Namespace SMART Log: %s\n", 97 cdata->lpa.ns_smart ? "Yes" : "No"); 98 printf("Error Log Page Entries: %d\n", cdata->elpe+1); 99 printf("Number of Power States: %d\n", cdata->npss+1); 100 101 printf("\n"); 102 printf("NVM Command Set Attributes\n"); 103 printf("==========================\n"); 104 printf("Submission Queue Entry Size\n"); 105 printf(" Max: %d\n", 1 << cdata->sqes.max); 106 printf(" Min: %d\n", 1 << cdata->sqes.min); 107 printf("Completion Queue Entry Size\n"); 108 printf(" Max: %d\n", 1 << cdata->cqes.max); 109 printf(" Min: %d\n", 1 << cdata->cqes.min); 110 printf("Number of Namespaces: %d\n", cdata->nn); 111 printf("Compare Command: %s\n", 112 cdata->oncs.compare ? "Supported" : "Not Supported"); 113 printf("Write Uncorrectable Command: %s\n", 114 cdata->oncs.write_unc ? "Supported" : "Not Supported"); 115 printf("Dataset Management Command: %s\n", 116 cdata->oncs.dsm ? "Supported" : "Not Supported"); 117 printf("Volatile Write Cache: %s\n", 118 cdata->vwc.present ? "Present" : "Not Present"); 119 120 if (cdata->oacs.nsmgmt) { 121 printf("\n"); 122 printf("Namespace Drive Attributes\n"); 123 printf("==========================\n"); 124 printf("NVM total cap: %s\n", 125 uint128_to_str(to128(cdata->untncap.tnvmcap), cbuf, sizeof(cbuf))); 126 printf("NVM unallocated cap: %s\n", 127 uint128_to_str(to128(cdata->untncap.unvmcap), cbuf, sizeof(cbuf))); 128 } 129 } 130 131 static void 132 print_namespace(struct nvme_namespace_data *nsdata) 133 { 134 uint32_t i; 135 136 printf("Size (in LBAs): %lld (%lldM)\n", 137 (long long)nsdata->nsze, 138 (long long)nsdata->nsze / 1024 / 1024); 139 printf("Capacity (in LBAs): %lld (%lldM)\n", 140 (long long)nsdata->ncap, 141 (long long)nsdata->ncap / 1024 / 1024); 142 printf("Utilization (in LBAs): %lld (%lldM)\n", 143 (long long)nsdata->nuse, 144 (long long)nsdata->nuse / 1024 / 1024); 145 printf("Thin Provisioning: %s\n", 146 nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported"); 147 printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); 148 printf("Current LBA Format: LBA Format #%02d\n", 149 nsdata->flbas.format); 150 for (i = 0; i <= nsdata->nlbaf; i++) 151 printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n", 152 i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms); 153 } 154 155 static void 156 identify_usage(void) 157 { 158 fprintf(stderr, "usage:\n"); 159 fprintf(stderr, IDENTIFY_USAGE); 160 exit(1); 161 } 162 163 static void 164 identify_ctrlr(int argc, char *argv[]) 165 { 166 struct nvme_controller_data cdata; 167 int ch, fd, hexflag = 0, hexlength; 168 int verboseflag = 0; 169 170 while ((ch = getopt(argc, argv, "vx")) != -1) { 171 switch ((char)ch) { 172 case 'v': 173 verboseflag = 1; 174 break; 175 case 'x': 176 hexflag = 1; 177 break; 178 default: 179 identify_usage(); 180 } 181 } 182 183 /* Check that a controller was specified. */ 184 if (optind >= argc) 185 identify_usage(); 186 187 open_dev(argv[optind], &fd, 1, 1); 188 read_controller_data(fd, &cdata); 189 close(fd); 190 191 if (hexflag == 1) { 192 if (verboseflag == 1) 193 hexlength = sizeof(struct nvme_controller_data); 194 else 195 hexlength = offsetof(struct nvme_controller_data, 196 reserved5); 197 print_hex(&cdata, hexlength); 198 exit(0); 199 } 200 201 if (verboseflag == 1) { 202 fprintf(stderr, "-v not currently supported without -x\n"); 203 identify_usage(); 204 } 205 206 print_controller(&cdata); 207 exit(0); 208 } 209 210 static void 211 identify_ns(int argc, char *argv[]) 212 { 213 struct nvme_namespace_data nsdata; 214 char path[64]; 215 int ch, fd, hexflag = 0, hexlength, nsid; 216 int verboseflag = 0; 217 218 while ((ch = getopt(argc, argv, "vx")) != -1) { 219 switch ((char)ch) { 220 case 'v': 221 verboseflag = 1; 222 break; 223 case 'x': 224 hexflag = 1; 225 break; 226 default: 227 identify_usage(); 228 } 229 } 230 231 /* Check that a namespace was specified. */ 232 if (optind >= argc) 233 identify_usage(); 234 235 /* 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. 239 */ 240 open_dev(argv[optind], &fd, 1, 1); 241 close(fd); 242 243 /* 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. 248 */ 249 parse_ns_str(argv[optind], path, &nsid); 250 open_dev(path, &fd, 1, 1); 251 read_namespace_data(fd, nsid, &nsdata); 252 close(fd); 253 254 if (hexflag == 1) { 255 if (verboseflag == 1) 256 hexlength = sizeof(struct nvme_namespace_data); 257 else 258 hexlength = offsetof(struct nvme_namespace_data, 259 reserved6); 260 print_hex(&nsdata, hexlength); 261 exit(0); 262 } 263 264 if (verboseflag == 1) { 265 fprintf(stderr, "-v not currently supported without -x\n"); 266 identify_usage(); 267 } 268 269 print_namespace(&nsdata); 270 exit(0); 271 } 272 273 void 274 identify(int argc, char *argv[]) 275 { 276 char *target; 277 278 if (argc < 2) 279 identify_usage(); 280 281 while (getopt(argc, argv, "vx") != -1) ; 282 283 /* Check that a controller or namespace was specified. */ 284 if (optind >= argc) 285 identify_usage(); 286 287 target = argv[optind]; 288 289 optreset = 1; 290 optind = 1; 291 292 /* 293 * If device node contains "ns", we consider it a namespace, 294 * otherwise, consider it a controller. 295 */ 296 if (strstr(target, NVME_NS_PREFIX) == NULL) 297 identify_ctrlr(argc, argv); 298 else 299 identify_ns(argc, argv); 300 } 301