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