nvmecontrol.c revision 252670
1184251Smarcel/*- 2184251Smarcel * Copyright (C) 2012-2013 Intel Corporation 3184251Smarcel * All rights reserved. 4184251Smarcel * 5184251Smarcel * Redistribution and use in source and binary forms, with or without 6184251Smarcel * modification, are permitted provided that the following conditions 7184251Smarcel * are met: 8184251Smarcel * 1. Redistributions of source code must retain the above copyright 9184251Smarcel * notice, this list of conditions and the following disclaimer. 10184251Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11184251Smarcel * notice, this list of conditions and the following disclaimer in the 12184251Smarcel * documentation and/or other materials provided with the distribution. 13184251Smarcel * 14184251Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184251Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184251Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184251Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184251Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184251Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184251Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184251Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184251Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184251Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184251Smarcel * SUCH DAMAGE. 25184251Smarcel */ 26184251Smarcel 27184251Smarcel#include <sys/cdefs.h> 28184251Smarcel__FBSDID("$FreeBSD: stable/9/sbin/nvmecontrol/nvmecontrol.c 252670 2013-07-04 00:06:11Z jimharris $"); 29184251Smarcel 30184251Smarcel#include <sys/param.h> 31184251Smarcel#include <sys/ioccom.h> 32184251Smarcel#include <sys/stat.h> 33188156Ssam 34188156Ssam#include <ctype.h> 35184251Smarcel#include <errno.h> 36184251Smarcel#include <fcntl.h> 37184251Smarcel#include <stdbool.h> 38184251Smarcel#include <stddef.h> 39184251Smarcel#include <stdio.h> 40184251Smarcel#include <stdlib.h> 41184251Smarcel#include <string.h> 42184251Smarcel#include <sysexits.h> 43184251Smarcel#include <unistd.h> 44184251Smarcel 45184251Smarcel#include "nvmecontrol.h" 46184251Smarcel 47184251Smarceltypedef void (*nvme_fn_t)(int argc, char *argv[]); 48184251Smarcel 49184251Smarcelstatic struct nvme_function { 50184251Smarcel const char *name; 51184251Smarcel nvme_fn_t fn; 52184251Smarcel const char *usage; 53184251Smarcel} funcs[] = { 54189606Ssam {"devlist", devlist, DEVLIST_USAGE}, 55184251Smarcel {"identify", identify, IDENTIFY_USAGE}, 56184251Smarcel {"perftest", perftest, PERFTEST_USAGE}, 57184251Smarcel {"reset", reset, RESET_USAGE}, 58184251Smarcel {"logpage", logpage, LOGPAGE_USAGE}, 59184251Smarcel {NULL, NULL, NULL}, 60184251Smarcel}; 61184251Smarcel 62184251Smarcelstatic void 63184251Smarcelusage(void) 64184251Smarcel{ 65184251Smarcel struct nvme_function *f; 66184251Smarcel 67184251Smarcel f = funcs; 68184251Smarcel fprintf(stderr, "usage:\n"); 69184251Smarcel while (f->name != NULL) { 70184251Smarcel fprintf(stderr, "%s", f->usage); 71184251Smarcel f++; 72184251Smarcel } 73184251Smarcel exit(EX_USAGE); 74184251Smarcel} 75184251Smarcel 76184251Smarcelstatic void 77184251Smarcelprint_bytes(void *data, uint32_t length) 78184251Smarcel{ 79184251Smarcel uint32_t i, j; 80184251Smarcel uint8_t *p, *end; 81184251Smarcel 82184251Smarcel end = (uint8_t *)data + length; 83184251Smarcel 84184251Smarcel for (i = 0; i < length; i++) { 85184251Smarcel p = (uint8_t *)data + (i*16); 86184251Smarcel printf("%03x: ", i*16); 87184251Smarcel for (j = 0; j < 16 && p < end; j++) 88184251Smarcel printf("%02x ", *p++); 89184251Smarcel if (p >= end) 90184251Smarcel break; 91184251Smarcel printf("\n"); 92184251Smarcel } 93184251Smarcel printf("\n"); 94184251Smarcel} 95184251Smarcel 96184251Smarcelstatic void 97184251Smarcelprint_dwords(void *data, uint32_t length) 98184251Smarcel{ 99184251Smarcel uint32_t *p; 100184251Smarcel uint32_t i, j; 101184251Smarcel 102184251Smarcel p = (uint32_t *)data; 103184251Smarcel length /= sizeof(uint32_t); 104184251Smarcel 105184251Smarcel for (i = 0; i < length; i+=8) { 106184251Smarcel printf("%03x: ", i*4); 107184251Smarcel for (j = 0; j < 8; j++) 108184251Smarcel printf("%08x ", p[i+j]); 109184251Smarcel printf("\n"); 110184251Smarcel } 111184251Smarcel 112184251Smarcel printf("\n"); 113184251Smarcel} 114184251Smarcel 115184251Smarcelvoid 116184251Smarcelprint_hex(void *data, uint32_t length) 117184251Smarcel{ 118184251Smarcel if (length >= sizeof(uint32_t) || length % sizeof(uint32_t) == 0) 119184251Smarcel print_dwords(data, length); 120184251Smarcel else 121184251Smarcel print_bytes(data, length); 122184251Smarcel} 123184251Smarcel 124184251Smarcelvoid 125184251Smarcelread_controller_data(int fd, struct nvme_controller_data *cdata) 126184251Smarcel{ 127184251Smarcel struct nvme_pt_command pt; 128184251Smarcel 129184251Smarcel memset(&pt, 0, sizeof(pt)); 130184251Smarcel pt.cmd.opc = NVME_OPC_IDENTIFY; 131184251Smarcel pt.cmd.cdw10 = 1; 132184251Smarcel pt.buf = cdata; 133184251Smarcel pt.len = sizeof(*cdata); 134184251Smarcel pt.is_read = 1; 135184251Smarcel 136184251Smarcel if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { 137184251Smarcel printf("Identify request failed. errno=%d (%s)\n", 138184251Smarcel errno, strerror(errno)); 139184251Smarcel exit(EX_IOERR); 140184251Smarcel } 141184251Smarcel 142184251Smarcel if (nvme_completion_is_error(&pt.cpl)) { 143184251Smarcel printf("Passthrough command returned error.\n"); 144184251Smarcel exit(EX_IOERR); 145184251Smarcel } 146184251Smarcel} 147184251Smarcel 148184251Smarcelvoid 149184251Smarcelread_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) 150184251Smarcel{ 151184251Smarcel struct nvme_pt_command pt; 152184251Smarcel 153184251Smarcel memset(&pt, 0, sizeof(pt)); 154184251Smarcel pt.cmd.opc = NVME_OPC_IDENTIFY; 155188087Ssam pt.cmd.nsid = nsid; 156188087Ssam pt.buf = nsdata; 157188087Ssam pt.len = sizeof(*nsdata); 158188087Ssam pt.is_read = 1; 159188087Ssam 160188087Ssam if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { 161188087Ssam printf("Identify request failed. errno=%d (%s)\n", 162188087Ssam errno, strerror(errno)); 163188087Ssam exit(EX_IOERR); 164188087Ssam } 165184251Smarcel 166184251Smarcel if (nvme_completion_is_error(&pt.cpl)) { 167184251Smarcel printf("Passthrough command returned error.\n"); 168184251Smarcel exit(EX_IOERR); 169184251Smarcel } 170184251Smarcel} 171184251Smarcel 172184251Smarcelint 173184251Smarcelopen_dev(const char *str, int *fd, int show_error, int exit_on_error) 174184251Smarcel{ 175184251Smarcel struct stat devstat; 176184251Smarcel char full_path[64]; 177184251Smarcel 178184251Smarcel if (!strnstr(str, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) { 179184251Smarcel if (show_error) 180184251Smarcel fprintf(stderr, 181184251Smarcel "Controller/namespace IDs must begin with '%s'.\n", 182184251Smarcel NVME_CTRLR_PREFIX); 183184251Smarcel if (exit_on_error) 184184251Smarcel exit(EX_USAGE); 185184251Smarcel else 186184251Smarcel return (EX_USAGE); 187184251Smarcel } 188184251Smarcel 189184251Smarcel snprintf(full_path, sizeof(full_path), "/dev/%s", str); 190184251Smarcel if (stat(full_path, &devstat) != 0) { 191184251Smarcel if (show_error) 192184251Smarcel fprintf(stderr, "Could not stat %s. errno=%d (%s)\n", 193184251Smarcel full_path, errno, strerror(errno)); 194184251Smarcel if (exit_on_error) 195184251Smarcel exit(EX_NOINPUT); 196184251Smarcel else 197184251Smarcel return (EX_NOINPUT); 198184251Smarcel } 199184251Smarcel 200184251Smarcel *fd = open(full_path, O_RDWR); 201184251Smarcel if (*fd < 0) { 202184251Smarcel if (show_error) 203184251Smarcel fprintf(stderr, "Could not open %s. errno=%d (%s)\n", 204184251Smarcel full_path, errno, strerror(errno)); 205184251Smarcel if (exit_on_error) 206184251Smarcel exit(EX_NOPERM); 207184251Smarcel else 208184251Smarcel return (EX_NOPERM); 209184251Smarcel } 210184251Smarcel 211184251Smarcel return (EX_OK); 212184251Smarcel} 213184251Smarcel 214184251Smarcelint 215184251Smarcelmain(int argc, char *argv[]) 216184251Smarcel{ 217184251Smarcel struct nvme_function *f; 218184251Smarcel 219184251Smarcel if (argc < 2) 220184251Smarcel usage(); 221184251Smarcel 222184251Smarcel f = funcs; 223184251Smarcel while (f->name != NULL) { 224184251Smarcel if (strcmp(argv[1], f->name) == 0) 225184251Smarcel f->fn(argc-1, &argv[1]); 226184251Smarcel f++; 227184251Smarcel } 228184251Smarcel 229184251Smarcel usage(); 230184251Smarcel 231184251Smarcel return (0); 232184251Smarcel} 233184251Smarcel 234184251Smarcel