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