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