xref: /titanic_51/usr/src/cmd/nvmeadm/nvmeadm_dev.c (revision ecee5a1fb22b5ba5e3b9bf76dde2c12d7c15632a)
1*ecee5a1fSHans Rosenfeld /*
2*ecee5a1fSHans Rosenfeld  * This file and its contents are supplied under the terms of the
3*ecee5a1fSHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
4*ecee5a1fSHans Rosenfeld  * You may only use this file in accordance with the terms of version
5*ecee5a1fSHans Rosenfeld  * 1.0 of the CDDL.
6*ecee5a1fSHans Rosenfeld  *
7*ecee5a1fSHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
8*ecee5a1fSHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
9*ecee5a1fSHans Rosenfeld  * http://www.illumos.org/license/CDDL.
10*ecee5a1fSHans Rosenfeld  */
11*ecee5a1fSHans Rosenfeld 
12*ecee5a1fSHans Rosenfeld /*
13*ecee5a1fSHans Rosenfeld  * Copyright 2016 Nexenta Systems, Inc.
14*ecee5a1fSHans Rosenfeld  */
15*ecee5a1fSHans Rosenfeld 
16*ecee5a1fSHans Rosenfeld #include <sys/types.h>
17*ecee5a1fSHans Rosenfeld #include <sys/stat.h>
18*ecee5a1fSHans Rosenfeld #include <fcntl.h>
19*ecee5a1fSHans Rosenfeld #include <unistd.h>
20*ecee5a1fSHans Rosenfeld #include <stropts.h>
21*ecee5a1fSHans Rosenfeld #include <err.h>
22*ecee5a1fSHans Rosenfeld #include <libdevinfo.h>
23*ecee5a1fSHans Rosenfeld #include <sys/nvme.h>
24*ecee5a1fSHans Rosenfeld #include <assert.h>
25*ecee5a1fSHans Rosenfeld 
26*ecee5a1fSHans Rosenfeld #include "nvmeadm.h"
27*ecee5a1fSHans Rosenfeld 
28*ecee5a1fSHans Rosenfeld 
29*ecee5a1fSHans Rosenfeld static boolean_t
30*ecee5a1fSHans Rosenfeld nvme_ioctl(int fd, int ioc, size_t *bufsize, void **buf, uint64_t arg,
31*ecee5a1fSHans Rosenfeld     uint64_t *res)
32*ecee5a1fSHans Rosenfeld {
33*ecee5a1fSHans Rosenfeld 	nvme_ioctl_t nioc = { 0 };
34*ecee5a1fSHans Rosenfeld 
35*ecee5a1fSHans Rosenfeld 	if (buf != NULL)
36*ecee5a1fSHans Rosenfeld 		*buf = NULL;
37*ecee5a1fSHans Rosenfeld 
38*ecee5a1fSHans Rosenfeld 	if (res != NULL)
39*ecee5a1fSHans Rosenfeld 		*res = ~0ULL;
40*ecee5a1fSHans Rosenfeld 
41*ecee5a1fSHans Rosenfeld 	if (bufsize != NULL && *bufsize != 0) {
42*ecee5a1fSHans Rosenfeld 		assert(buf != NULL);
43*ecee5a1fSHans Rosenfeld 
44*ecee5a1fSHans Rosenfeld 		if ((nioc.n_buf = (uintptr_t)calloc(*bufsize, 1)) == NULL)
45*ecee5a1fSHans Rosenfeld 			err(-1, "nvme_ioctl()");
46*ecee5a1fSHans Rosenfeld 
47*ecee5a1fSHans Rosenfeld 		nioc.n_len = *bufsize;
48*ecee5a1fSHans Rosenfeld 	}
49*ecee5a1fSHans Rosenfeld 
50*ecee5a1fSHans Rosenfeld 	nioc.n_arg = arg;
51*ecee5a1fSHans Rosenfeld 
52*ecee5a1fSHans Rosenfeld 	if (ioctl(fd, ioc, &nioc) != 0) {
53*ecee5a1fSHans Rosenfeld 		if (debug)
54*ecee5a1fSHans Rosenfeld 			warn("nvme_ioctl()");
55*ecee5a1fSHans Rosenfeld 		if (nioc.n_buf != 0)
56*ecee5a1fSHans Rosenfeld 			free((void *)nioc.n_buf);
57*ecee5a1fSHans Rosenfeld 
58*ecee5a1fSHans Rosenfeld 		return (B_FALSE);
59*ecee5a1fSHans Rosenfeld 	}
60*ecee5a1fSHans Rosenfeld 
61*ecee5a1fSHans Rosenfeld 	if (res != NULL)
62*ecee5a1fSHans Rosenfeld 		*res = nioc.n_arg;
63*ecee5a1fSHans Rosenfeld 
64*ecee5a1fSHans Rosenfeld 	if (bufsize != NULL)
65*ecee5a1fSHans Rosenfeld 		*bufsize = nioc.n_len;
66*ecee5a1fSHans Rosenfeld 
67*ecee5a1fSHans Rosenfeld 	if (buf != NULL)
68*ecee5a1fSHans Rosenfeld 		*buf = (void *)nioc.n_buf;
69*ecee5a1fSHans Rosenfeld 
70*ecee5a1fSHans Rosenfeld 	return (B_TRUE);
71*ecee5a1fSHans Rosenfeld }
72*ecee5a1fSHans Rosenfeld 
73*ecee5a1fSHans Rosenfeld nvme_capabilities_t *
74*ecee5a1fSHans Rosenfeld nvme_capabilities(int fd)
75*ecee5a1fSHans Rosenfeld {
76*ecee5a1fSHans Rosenfeld 	void *cap = NULL;
77*ecee5a1fSHans Rosenfeld 	size_t bufsize = sizeof (nvme_capabilities_t);
78*ecee5a1fSHans Rosenfeld 
79*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_CAPABILITIES, &bufsize, &cap, 0, NULL);
80*ecee5a1fSHans Rosenfeld 
81*ecee5a1fSHans Rosenfeld 	return (cap);
82*ecee5a1fSHans Rosenfeld }
83*ecee5a1fSHans Rosenfeld 
84*ecee5a1fSHans Rosenfeld nvme_version_t *
85*ecee5a1fSHans Rosenfeld nvme_version(int fd)
86*ecee5a1fSHans Rosenfeld {
87*ecee5a1fSHans Rosenfeld 	void *vs = NULL;
88*ecee5a1fSHans Rosenfeld 	size_t bufsize = sizeof (nvme_version_t);
89*ecee5a1fSHans Rosenfeld 
90*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_VERSION, &bufsize, &vs, 0, NULL);
91*ecee5a1fSHans Rosenfeld 
92*ecee5a1fSHans Rosenfeld 	return (vs);
93*ecee5a1fSHans Rosenfeld }
94*ecee5a1fSHans Rosenfeld 
95*ecee5a1fSHans Rosenfeld nvme_identify_ctrl_t *
96*ecee5a1fSHans Rosenfeld nvme_identify_ctrl(int fd)
97*ecee5a1fSHans Rosenfeld {
98*ecee5a1fSHans Rosenfeld 	void *idctl = NULL;
99*ecee5a1fSHans Rosenfeld 	size_t bufsize = NVME_IDENTIFY_BUFSIZE;
100*ecee5a1fSHans Rosenfeld 
101*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_IDENTIFY_CTRL, &bufsize, &idctl, 0,
102*ecee5a1fSHans Rosenfeld 	    NULL);
103*ecee5a1fSHans Rosenfeld 
104*ecee5a1fSHans Rosenfeld 	return (idctl);
105*ecee5a1fSHans Rosenfeld }
106*ecee5a1fSHans Rosenfeld 
107*ecee5a1fSHans Rosenfeld nvme_identify_nsid_t *
108*ecee5a1fSHans Rosenfeld nvme_identify_nsid(int fd)
109*ecee5a1fSHans Rosenfeld {
110*ecee5a1fSHans Rosenfeld 	void *idns = NULL;
111*ecee5a1fSHans Rosenfeld 	size_t bufsize = NVME_IDENTIFY_BUFSIZE;
112*ecee5a1fSHans Rosenfeld 
113*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_IDENTIFY_NSID, &bufsize, &idns, 0, NULL);
114*ecee5a1fSHans Rosenfeld 
115*ecee5a1fSHans Rosenfeld 	return (idns);
116*ecee5a1fSHans Rosenfeld }
117*ecee5a1fSHans Rosenfeld 
118*ecee5a1fSHans Rosenfeld void *
119*ecee5a1fSHans Rosenfeld nvme_get_logpage(int fd, uint8_t logpage, size_t *bufsize)
120*ecee5a1fSHans Rosenfeld {
121*ecee5a1fSHans Rosenfeld 	void *buf = NULL;
122*ecee5a1fSHans Rosenfeld 
123*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_GET_LOGPAGE, bufsize, &buf, logpage,
124*ecee5a1fSHans Rosenfeld 	    NULL);
125*ecee5a1fSHans Rosenfeld 
126*ecee5a1fSHans Rosenfeld 	return (buf);
127*ecee5a1fSHans Rosenfeld }
128*ecee5a1fSHans Rosenfeld 
129*ecee5a1fSHans Rosenfeld boolean_t
130*ecee5a1fSHans Rosenfeld nvme_get_feature(int fd, uint8_t feature, uint32_t arg, uint64_t *res,
131*ecee5a1fSHans Rosenfeld     size_t *bufsize, void **buf)
132*ecee5a1fSHans Rosenfeld {
133*ecee5a1fSHans Rosenfeld 	return (nvme_ioctl(fd, NVME_IOC_GET_FEATURES, bufsize, buf,
134*ecee5a1fSHans Rosenfeld 	    (uint64_t)feature << 32 | arg, res));
135*ecee5a1fSHans Rosenfeld }
136*ecee5a1fSHans Rosenfeld 
137*ecee5a1fSHans Rosenfeld int
138*ecee5a1fSHans Rosenfeld nvme_intr_cnt(int fd)
139*ecee5a1fSHans Rosenfeld {
140*ecee5a1fSHans Rosenfeld 	uint64_t res = 0;
141*ecee5a1fSHans Rosenfeld 
142*ecee5a1fSHans Rosenfeld 	(void) nvme_ioctl(fd, NVME_IOC_INTR_CNT, NULL, NULL, 0, &res);
143*ecee5a1fSHans Rosenfeld 	return ((int)res);
144*ecee5a1fSHans Rosenfeld }
145*ecee5a1fSHans Rosenfeld 
146*ecee5a1fSHans Rosenfeld boolean_t
147*ecee5a1fSHans Rosenfeld nvme_format_nvm(int fd, uint8_t lbaf, uint8_t ses)
148*ecee5a1fSHans Rosenfeld {
149*ecee5a1fSHans Rosenfeld 	nvme_format_nvm_t frmt = { 0 };
150*ecee5a1fSHans Rosenfeld 
151*ecee5a1fSHans Rosenfeld 	frmt.b.fm_lbaf = lbaf & 0xf;
152*ecee5a1fSHans Rosenfeld 	frmt.b.fm_ses = ses & 0x7;
153*ecee5a1fSHans Rosenfeld 
154*ecee5a1fSHans Rosenfeld 	return (nvme_ioctl(fd, NVME_IOC_FORMAT, NULL, NULL, frmt.r, NULL));
155*ecee5a1fSHans Rosenfeld }
156*ecee5a1fSHans Rosenfeld 
157*ecee5a1fSHans Rosenfeld boolean_t
158*ecee5a1fSHans Rosenfeld nvme_detach(int fd)
159*ecee5a1fSHans Rosenfeld {
160*ecee5a1fSHans Rosenfeld 	return (nvme_ioctl(fd, NVME_IOC_DETACH, NULL, NULL, 0, NULL));
161*ecee5a1fSHans Rosenfeld }
162*ecee5a1fSHans Rosenfeld 
163*ecee5a1fSHans Rosenfeld boolean_t
164*ecee5a1fSHans Rosenfeld nvme_attach(int fd)
165*ecee5a1fSHans Rosenfeld {
166*ecee5a1fSHans Rosenfeld 	return (nvme_ioctl(fd, NVME_IOC_ATTACH, NULL, NULL, 0, NULL));
167*ecee5a1fSHans Rosenfeld }
168*ecee5a1fSHans Rosenfeld 
169*ecee5a1fSHans Rosenfeld int
170*ecee5a1fSHans Rosenfeld nvme_open(di_minor_t minor)
171*ecee5a1fSHans Rosenfeld {
172*ecee5a1fSHans Rosenfeld 	char *devpath, *path;
173*ecee5a1fSHans Rosenfeld 	int fd;
174*ecee5a1fSHans Rosenfeld 
175*ecee5a1fSHans Rosenfeld 	if ((devpath = di_devfs_minor_path(minor)) == NULL)
176*ecee5a1fSHans Rosenfeld 		err(-1, "nvme_open()");
177*ecee5a1fSHans Rosenfeld 
178*ecee5a1fSHans Rosenfeld 	if (asprintf(&path, "/devices%s", devpath) < 0) {
179*ecee5a1fSHans Rosenfeld 		di_devfs_path_free(devpath);
180*ecee5a1fSHans Rosenfeld 		err(-1, "nvme_open()");
181*ecee5a1fSHans Rosenfeld 	}
182*ecee5a1fSHans Rosenfeld 
183*ecee5a1fSHans Rosenfeld 	di_devfs_path_free(devpath);
184*ecee5a1fSHans Rosenfeld 
185*ecee5a1fSHans Rosenfeld 	fd = open(path, O_RDWR);
186*ecee5a1fSHans Rosenfeld 	free(path);
187*ecee5a1fSHans Rosenfeld 
188*ecee5a1fSHans Rosenfeld 	if (fd < 0) {
189*ecee5a1fSHans Rosenfeld 		if (debug)
190*ecee5a1fSHans Rosenfeld 			warn("nvme_open(%s)", path);
191*ecee5a1fSHans Rosenfeld 		return (-1);
192*ecee5a1fSHans Rosenfeld 	}
193*ecee5a1fSHans Rosenfeld 
194*ecee5a1fSHans Rosenfeld 	return (fd);
195*ecee5a1fSHans Rosenfeld }
196*ecee5a1fSHans Rosenfeld 
197*ecee5a1fSHans Rosenfeld void
198*ecee5a1fSHans Rosenfeld nvme_close(int fd)
199*ecee5a1fSHans Rosenfeld {
200*ecee5a1fSHans Rosenfeld 	(void) close(fd);
201*ecee5a1fSHans Rosenfeld }
202