nvmecontrol.c revision 252659
1/*-
2 * Copyright (C) 2012-2013 Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/9/sbin/nvmecontrol/nvmecontrol.c 252659 2013-07-03 23:48:58Z jimharris $");
29
30#include <sys/param.h>
31#include <sys/ioccom.h>
32#include <sys/stat.h>
33
34#include <ctype.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <stdbool.h>
38#include <stddef.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <sysexits.h>
43#include <unistd.h>
44
45#include "nvmecontrol.h"
46
47static void
48usage(void)
49{
50	fprintf(stderr, "usage:\n");
51	fprintf(stderr, DEVLIST_USAGE);
52	fprintf(stderr, IDENTIFY_USAGE);
53	fprintf(stderr, RESET_USAGE);
54	fprintf(stderr, PERFTEST_USAGE);
55	exit(EX_USAGE);
56}
57
58void
59read_controller_data(int fd, struct nvme_controller_data *cdata)
60{
61	struct nvme_pt_command	pt;
62
63	memset(&pt, 0, sizeof(pt));
64	pt.cmd.opc = NVME_OPC_IDENTIFY;
65	pt.cmd.cdw10 = 1;
66	pt.buf = cdata;
67	pt.len = sizeof(*cdata);
68	pt.is_read = 1;
69
70	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
71		printf("Identify request failed. errno=%d (%s)\n",
72		    errno, strerror(errno));
73		exit(EX_IOERR);
74	}
75
76	if (nvme_completion_is_error(&pt.cpl)) {
77		printf("Passthrough command returned error.\n");
78		exit(EX_IOERR);
79	}
80}
81
82void
83read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata)
84{
85	struct nvme_pt_command	pt;
86
87	memset(&pt, 0, sizeof(pt));
88	pt.cmd.opc = NVME_OPC_IDENTIFY;
89	pt.cmd.nsid = nsid;
90	pt.buf = nsdata;
91	pt.len = sizeof(*nsdata);
92	pt.is_read = 1;
93
94	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) {
95		printf("Identify request failed. errno=%d (%s)\n",
96		    errno, strerror(errno));
97		exit(EX_IOERR);
98	}
99
100	if (nvme_completion_is_error(&pt.cpl)) {
101		printf("Passthrough command returned error.\n");
102		exit(EX_IOERR);
103	}
104}
105
106int
107open_dev(const char *str, int *fd, int show_error, int exit_on_error)
108{
109	struct stat	devstat;
110	char		full_path[64];
111
112	snprintf(full_path, sizeof(full_path), "/dev/%s", str);
113	if (stat(full_path, &devstat) != 0) {
114		if (show_error)
115			fprintf(stderr, "error\n");
116		if (exit_on_error)
117			exit(EX_NOINPUT);
118		else
119			return (EX_NOINPUT);
120	}
121
122	*fd = open(full_path, O_RDWR);
123	if (*fd < 0) {
124		if (show_error)
125			printf("Could not open %s. errno=%d (%s)\n", full_path,
126			    errno, strerror(errno));
127		if (exit_on_error)
128			exit(EX_NOPERM);
129		else
130			return (EX_NOPERM);
131	}
132
133	return (EX_OK);
134}
135
136static void
137reset_usage(void)
138{
139	fprintf(stderr, "usage:\n");
140	fprintf(stderr, RESET_USAGE);
141	exit(EX_USAGE);
142}
143
144static void
145reset_ctrlr(int argc, char *argv[])
146{
147	int	ch, fd;
148
149	while ((ch = getopt(argc, argv, "")) != -1) {
150		switch ((char)ch) {
151		default:
152			reset_usage();
153		}
154	}
155
156	open_dev(argv[optind], &fd, 1, 1);
157	if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) {
158		printf("Reset request to %s failed. errno=%d (%s)\n",
159		    argv[optind], errno, strerror(errno));
160		exit(EX_IOERR);
161	}
162
163	exit(EX_OK);
164}
165
166int
167main(int argc, char *argv[])
168{
169
170	if (argc < 2)
171		usage();
172
173	if (strcmp(argv[1], "devlist") == 0)
174		devlist(argc-1, &argv[1]);
175	else if (strcmp(argv[1], "identify") == 0)
176		identify(argc-1, &argv[1]);
177	else if (strcmp(argv[1], "perftest") == 0)
178		perftest(argc-1, &argv[1]);
179	else if (strcmp(argv[1], "reset") == 0)
180		reset_ctrlr(argc-1, &argv[1]);
181
182	usage();
183
184	return (0);
185}
186
187