xref: /illumos-gate/usr/src/lib/libnvme/common/libnvme_impl.h (revision 564eeb7d65973f1d64a5390ff477b689707e9daf)
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 2026 Oxide Computer Company
14  */
15 
16 #ifndef _LIBNVME_IMPL_H
17 #define	_LIBNVME_IMPL_H
18 
19 /*
20  * Implementation structures and related for libnvme.
21  */
22 
23 #include <libnvme.h>
24 #include <libdevinfo.h>
25 #include <stdbool.h>
26 #include <nvme_common.h>
27 #include <synch.h>
28 #include <sys/nvme/ocp.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /*
35  * Maximum size of an internal error message.
36  */
37 #define	NVME_ERR_LEN	1024
38 
39 typedef struct nvme_err_data {
40 	nvme_err_t ne_err;
41 	int32_t ne_syserr;
42 	char ne_errmsg[NVME_ERR_LEN];
43 	size_t ne_errlen;
44 	uint32_t ne_ctrl_sct;
45 	uint32_t ne_ctrl_sc;
46 } nvme_err_data_t;
47 
48 struct nvme {
49 	nvme_err_data_t nh_err;
50 	di_node_t nh_devinfo;
51 };
52 
53 struct nvme_ctrl_disc {
54 	di_node_t ncd_devi;
55 	di_minor_t ncd_minor;
56 };
57 
58 struct nvme_ctrl_iter {
59 	nvme_t *ni_nvme;
60 	bool ni_done;
61 	di_node_t ni_cur;
62 	nvme_ctrl_disc_t ni_disc;
63 };
64 
65 typedef enum {
66 	/*
67 	 * This indicates that we have attempted to fill in the NVMe 2.0
68 	 * supported logs page information and therefore can use it as part of
69 	 * log page discovery. This is filled in lazily on a handle and will
70 	 * persist as long as a handle does. If the log page is not supported or
71 	 * an error occurred then the VALID flag will be set, but the
72 	 * nc_sup_logs member will be set to NULL to indicate that we don't have
73 	 * the information.
74 	 *
75 	 * When the log page is supported, but something has gone wrong, we will
76 	 * set the FAILED flag to indicate that. Presuming it wasn't a memory
77 	 * failure, then we try to save a copy of the resulting nvme_err_data_t.
78 	 * This information isn't exposed outside of the library, but is kept on
79 	 * the handle to aid debugging.
80 	 */
81 	NVME_CTRL_F_SUP_LOGS_VALID	= 1 << 0,
82 	NVME_CTRL_F_SUP_LOGS_FAILED	= 1 << 1
83 } nvme_ctrl_flags_t;
84 
85 struct nvme_ctrl {
86 	nvme_t *nc_nvme;
87 	nvme_err_data_t nc_err;
88 	di_node_t nc_devi;
89 	di_minor_t nc_minor;
90 	char *nc_devi_path;
91 	int32_t nc_inst;
92 	int nc_fd;
93 	nvme_version_t nc_vers;
94 	nvme_identify_ctrl_t nc_info;
95 	const struct nvme_vsd *nc_vsd;
96 	nvme_ctrl_flags_t nc_flags;
97 	nvme_suplog_log_t *nc_sup_logs;
98 	nvme_err_data_t *nc_sup_logs_err;
99 };
100 
101 struct nvme_ns_disc {
102 	uint32_t nnd_nsid;
103 	nvme_ns_disc_level_t nnd_level;
104 	nvme_ns_disc_flags_t nnd_flags;
105 	uint8_t nnd_eui64[8];
106 	uint8_t nnd_nguid[16];
107 };
108 
109 struct nvme_ns_iter {
110 	nvme_ctrl_t *nni_ctrl;
111 	nvme_ns_disc_level_t nni_level;
112 	bool nni_err;
113 	bool nni_done;
114 	size_t nni_cur_idx;
115 	nvme_ns_disc_t nni_disc;
116 };
117 
118 struct nvme_ns {
119 	nvme_ctrl_t *nn_ctrl;
120 	uint32_t nn_nsid;
121 };
122 
123 struct nvme_nvm_lba_fmt {
124 	uint32_t nnlf_id;
125 	uint32_t nnlf_ms;
126 	uint64_t nnlf_lbasz;
127 	uint32_t nnlf_rel;
128 };
129 
130 struct nvme_ctrl_info {
131 	nvme_info_err_t nci_err;
132 	int32_t nci_syserr;
133 	char nci_errmsg[NVME_ERR_LEN];
134 	size_t nci_errlen;
135 	/*
136 	 * The NVMe strings are generally ASCII strings that have trailing
137 	 * spaces on them ala SCSI. We transform that into a C style string
138 	 * without trailing padding. The +1 assumes we need to add a terminator.
139 	 */
140 	char nci_serial[NVME_SERIAL_SZ + 1];
141 	char nci_model[NVME_MODEL_SZ + 1];
142 	char nci_fwrev[NVME_FWVER_SZ + 1];
143 	bool nci_lbaf_valid[NVME_MAX_LBAF];
144 	nvme_nvm_lba_fmt_t nci_lbaf[NVME_MAX_LBAF];
145 	/*
146 	 * Only information below here should be persisted. That is, the above
147 	 * information is meant to be specific to the library.
148 	 */
149 	nvme_version_t nci_vers;
150 	int32_t nci_inst;
151 	char nci_dev_path[PATH_MAX];
152 	nvme_identify_ctrl_t nci_info;
153 	nvme_identify_nsid_t nci_ns;
154 	nvme_ctrl_transport_t nci_tport;
155 	uint16_t nci_vid;
156 	uint16_t nci_did;
157 	uint16_t nci_subvid;
158 	uint16_t nci_subsys;
159 	uint8_t nci_rev;
160 	uint32_t nci_mps_min;
161 	uint32_t nci_mps_max;
162 	uint32_t nci_nintrs;
163 };
164 
165 /*
166  * Internal nvlist_t keys for control information.
167  */
168 #define	NVME_NVL_CI_VERS	"version"
169 #define	NVME_NVL_CI_VERS_0	0
170 #define	NVME_NVL_CI_INST	"inst"
171 #define	NVME_NVL_CI_MAJOR	"nvme-major-version"
172 #define	NVME_NVL_CI_MINOR	"nvme-minor-version"
173 #define	NVME_NVL_CI_DEV_PATH	"dev-path"
174 #define	NVME_NVL_CI_ID_CTRL	"identify-controller"
175 #define	NVME_NVL_CI_ID_NS	"identify-namespace"
176 #define	NVME_NVL_CI_TPORT	"transport"
177 #define	NVME_NVL_CI_PCI_VID	"pci-vendor-id"
178 #define	NVME_NVL_CI_PCI_DID	"pci-device-id"
179 #define	NVME_NVL_CI_PCI_SUBVID	"pci-subsystem-vendor-id"
180 #define	NVME_NVL_CI_PCI_SUBSYS	"pci-subsystem-id"
181 #define	NVME_NVL_CI_PCI_REV	"pci-revision-id"
182 #define	NVME_NVL_CI_PCI_MPSMIN	"pci-memory-page-size-min"
183 #define	NVME_NVL_CI_PCI_MPSMAX	"pci-memory-page-size-max"
184 #define	NVME_NVL_CI_PCI_NINTRS	"pci-num-interrupts"
185 
186 struct nvme_ns_info {
187 	nvme_info_err_t nni_err;
188 	int32_t nni_syserr;
189 	char nni_errmsg[NVME_ERR_LEN];
190 	size_t nni_errlen;
191 	uint32_t nni_nsid;
192 	nvme_version_t nni_vers;
193 	nvme_ns_disc_level_t nni_level;
194 	nvme_ioctl_ns_info_t nni_info;
195 	bool nni_lbaf_valid[NVME_MAX_LBAF];
196 	nvme_nvm_lba_fmt_t nni_lbaf[NVME_MAX_LBAF];
197 };
198 
199 typedef enum {
200 	NVME_LOG_REQ_F_RAE		= 1 << 0,
201 	NVME_LOG_REQ_F_BCAST_NS_OK	= 1 << 1
202 } nvme_log_req_flags_t;
203 
204 struct nvme_log_req {
205 	nvme_ctrl_t *nlr_ctrl;
206 	uint32_t nlr_need;
207 	uint32_t nlr_allow;
208 	nvme_csi_t nlr_csi;
209 	uint32_t nlr_lid;
210 	uint32_t nlr_lsp;
211 	uint32_t nlr_lsi;
212 	uint32_t nlr_nsid;
213 	nvme_log_req_flags_t nlr_flags;
214 	void *nlr_output;
215 	size_t nlr_output_len;
216 	uint64_t nlr_offset;
217 };
218 
219 /*
220  * This structure is used internally to describe information about a given log
221  * page.
222  */
223 typedef enum {
224 	/*
225 	 * This indicates that the log page is actually implemented.
226 	 */
227 	NVME_LOG_DISC_F_IMPL		= 1 << 0
228 } nvme_log_disc_flags_t;
229 
230 struct nvme_log_disc {
231 	const char		*nld_short;
232 	const char		*nld_desc;
233 	const char *const	*nld_aliases;
234 	size_t			nld_naliases;
235 	uint32_t		nld_lid;
236 	nvme_csi_t		nld_csi;
237 	nvme_log_disc_kind_t	nld_kind;
238 	nvme_log_disc_source_t	nld_srcs;
239 	nvme_log_disc_fields_t	nld_fields;
240 	nvme_log_disc_scope_t	nld_scope;
241 	nvme_log_disc_flags_t	nld_flags;
242 	nvme_log_size_kind_t	nld_size_kind;
243 	uint64_t		nld_alloc_len;
244 	nvme_log_page_var_len_f	nld_var_func;
245 };
246 
247 struct nvme_log_iter {
248 	nvme_ctrl_t *nli_ctrl;
249 	nvme_log_disc_scope_t nli_scope;
250 	bool nli_std_done;
251 	bool nli_vs_done;
252 	size_t nli_cur_idx;
253 	nvme_log_disc_t nli_nld;
254 };
255 
256 /*
257  * Feature discovery and iteration.
258  */
259 struct nvme_feat_disc {
260 	const char *nfd_short;
261 	const char *nfd_spec;
262 	uint32_t nfd_fid;
263 	nvme_feat_kind_t nfd_kind;
264 	nvme_feat_scope_t nfd_scope;
265 	nvme_feat_flags_t nfd_flags;
266 	nvme_feat_csi_t nfd_csi;
267 	nvme_get_feat_fields_t nfd_in_get;
268 	nvme_set_feat_fields_t nfd_in_set;
269 	nvme_feat_output_t nfd_out_get;
270 	nvme_feat_output_t nfd_out_set;
271 	nvme_disc_impact_t nfd_impact;
272 	uint64_t nfd_len;
273 	nvme_feat_impl_t nfd_impl;
274 };
275 
276 struct nvme_feat_iter {
277 	nvme_ctrl_t *nfi_ctrl;
278 	nvme_feat_scope_t nfi_scope;
279 	bool nfi_std_done;
280 	bool nfi_vs_done;
281 	size_t nfi_cur_idx;
282 	nvme_feat_disc_t nfi_disc;
283 };
284 
285 struct nvme_get_feat_req {
286 	nvme_ctrl_t *gfr_ctrl;
287 	uint32_t gfr_need;
288 	uint32_t gfr_allow;
289 	nvme_feat_flags_t gfr_flags;
290 	uint32_t gfr_fid;
291 	uint32_t gfr_sel;
292 	uint32_t gfr_nsid;
293 	uint32_t gfr_cdw11;
294 	void *gfr_buf;
295 	size_t gfr_len;
296 	uint64_t gfr_targ_len;
297 	/*
298 	 * The following are set on exec.
299 	 */
300 	bool gfr_results_valid;
301 	uint32_t gfr_cdw0;
302 };
303 
304 struct nvme_set_feat_req {
305 	nvme_ctrl_t *sfr_ctrl;
306 	uint32_t sfr_need;
307 	uint32_t sfr_allow;
308 	nvme_feat_flags_t sfr_flags;
309 	uint32_t sfr_fid;
310 	uint32_t sfr_save;
311 	uint32_t sfr_cdw11;
312 	uint32_t sfr_cdw12;
313 	uint32_t sfr_cdw13;
314 	uint32_t sfr_cdw15;
315 	const void *sfr_buf;
316 	size_t sfr_len;
317 	uint64_t sfr_targ_len;
318 	uint32_t sfr_nsid;
319 	uint32_t sfr_impact;
320 	/*
321 	 * The following are set on exec.
322 	 */
323 	bool sfr_results_valid;
324 	uint32_t sfr_cdw0;
325 };
326 
327 /*
328  * Identify command request
329  */
330 struct nvme_id_req {
331 	nvme_ctrl_t *nir_ctrl;
332 	const nvme_identify_info_t *nir_info;
333 	nvme_identify_req_field_t nir_need;
334 	nvme_identify_req_field_t nir_allow;
335 	uint32_t nir_nsid;
336 	uint32_t nir_ctrlid;
337 	void *nir_buf;
338 };
339 
340 /*
341  * Vendor unique command support.
342  */
343 struct nvme_vuc_disc {
344 	const char *nvd_short;
345 	const char *nvd_desc;
346 	uint8_t nvd_opc;
347 	nvme_disc_impact_t nvd_impact;
348 	nvme_vuc_disc_io_t nvd_dt;
349 	nvme_vuc_disc_lock_t nvd_lock;
350 };
351 
352 struct nvme_vuc_iter {
353 	nvme_ctrl_t *nvi_ctrl;
354 	size_t nvi_cur_idx;
355 };
356 
357 struct nvme_vuc_req {
358 	nvme_ctrl_t *nvr_ctrl;
359 	uint32_t nvr_need;
360 	uint32_t nvr_opcode;
361 	uint32_t nvr_timeout;
362 	uint32_t nvr_nsid;
363 	uint32_t nvr_cdw12;
364 	uint32_t nvr_cdw13;
365 	uint32_t nvr_cdw14;
366 	uint32_t nvr_cdw15;
367 	uint32_t nvr_impact;
368 	size_t nvr_outlen;
369 	size_t nvr_inlen;
370 	void *nvr_output;
371 	const void *nvr_input;
372 	/*
373 	 * The following values are set on exec.
374 	 */
375 	bool nvr_results_valid;
376 	uint32_t nvr_cdw0;
377 };
378 
379 /*
380  * If we ever support updating the boot partition ID, our expectation is that we
381  * end up doing that through other library interfaces even if it uses the same
382  * underlying ioctl. That ultimately will keep things simpler from a consumer
383  * perspective.
384  */
385 struct nvme_fw_commit_req {
386 	nvme_ctrl_t *fwc_ctrl;
387 	uint32_t fwc_need;
388 	uint32_t fwc_slot;
389 	uint32_t fwc_action;
390 };
391 
392 /*
393  * Format request data.
394  */
395 struct nvme_format_req {
396 	nvme_ctrl_t *nfr_ctrl;
397 	uint32_t nfr_need;
398 	bool nfr_ns;
399 	uint32_t nfr_lbaf;
400 	uint32_t nfr_ses;
401 	uint32_t nfr_nsid;
402 };
403 
404 /*
405  * Namespace Attach request.
406  */
407 struct nvme_ns_attach_req {
408 	nvme_ctrl_t *nar_ctrl;
409 	uint32_t nar_need;
410 	uint32_t nar_nsid;
411 	uint32_t nar_sel;
412 };
413 
414 /*
415  * Namespace Delete request.
416  */
417 struct nvme_ns_delete_req {
418 	nvme_ctrl_t *ndr_ctrl;
419 	uint32_t ndr_need;
420 	uint32_t ndr_nsid;
421 };
422 
423 /*
424  * Namespace Create request.
425  */
426 struct nvme_ns_create_req {
427 	nvme_ctrl_t *ncr_ctrl;
428 	nvme_csi_t ncr_csi;
429 	uint32_t ncr_need;
430 	uint32_t ncr_allow;
431 	uint64_t ncr_nsze;
432 	uint64_t ncr_ncap;
433 	uint32_t ncr_flbas;
434 	uint32_t ncr_nmic;
435 	/*
436 	 * The following are set on exec.
437 	 */
438 	bool ncr_results_valid;
439 	uint32_t ncr_nsid;
440 };
441 
442 /*
443  * WDC e6 request. This was made an opaque request style structure to try to
444  * safeguard us against future changes where something like the optional mode
445  * byte was required (right now it's just always zero).
446  */
447 struct nvme_wdc_e6_req {
448 	uint32_t wer_need;
449 	nvme_vuc_req_t *wer_vuc;
450 };
451 
452 /*
453  * OCP Error injection request.
454  */
455 struct nvme_ocp_errinj_req {
456 	uint32_t oer_need;
457 	uint32_t oer_allow;
458 	ocp_vuf_errinj_t oer_err[OCP_ERRINJ_MAX_INJECT + 1];
459 	nvme_set_feat_req_t *oer_feat;
460 };
461 
462 /*
463  * Common interfaces for operation success and failure. There are currently
464  * errors that can exist on four different objects in the library and there is
465  * one success() and error() function for each of them. See the theory statement
466  * section on errors in libnvme.c for more information. Note, all namespace and
467  * request structures set errors on the controller.
468  *
469  * The controller has an extra error path that is used for converting ioctls to
470  * semantic errors. It takes care of translating the different kinds of kernel
471  * errors to the library's errors. Our goal is to never programmatically leak
472  * the kernel ioctls and their error codes as they do not promise stability
473  * unlike our aspirations. It also doesn't allow for variable arguments and only
474  * takes a single description.
475  */
476 extern bool nvme_error(nvme_t *, nvme_err_t, int32_t, const char *,
477     ...)  __PRINTFLIKE(4);
478 extern bool nvme_success(nvme_t *);
479 
480 extern bool nvme_ctrl_error(nvme_ctrl_t *, nvme_err_t, int32_t, const char *,
481     ...)  __PRINTFLIKE(4);
482 extern bool nvme_ioctl_error(nvme_ctrl_t *, const nvme_ioctl_common_t *,
483     const char *);
484 extern bool nvme_ioctl_syserror(nvme_ctrl_t *, int, const char *);
485 extern bool nvme_ctrl_success(nvme_ctrl_t *);
486 
487 extern bool nvme_info_error(nvme_ctrl_info_t *, nvme_info_err_t, int32_t,
488     const char *, ...)  __PRINTFLIKE(4);
489 extern bool nvme_info_success(nvme_ctrl_info_t *);
490 
491 extern bool nvme_ns_info_error(nvme_ns_info_t *, nvme_info_err_t, int32_t,
492     const char *, ...)  __PRINTFLIKE(4);
493 extern bool nvme_ns_info_success(nvme_ns_info_t *);
494 
495 /*
496  * Common functions for preserving and restoring error data. This comes up when
497  * utilizing callback functions for discovery where we call libnvme functions.
498  */
499 extern void nvme_err_save(const nvme_t *, nvme_err_data_t *);
500 extern void nvme_err_set(nvme_t *, const nvme_err_data_t *);
501 extern void nvme_ctrl_err_save(const nvme_ctrl_t *, nvme_err_data_t *);
502 extern void nvme_ctrl_err_set(nvme_ctrl_t *, const nvme_err_data_t *);
503 
504 /*
505  * Common functions for issuing ioctls to a controller.
506  */
507 extern bool nvme_ioc_ctrl_info(nvme_ctrl_t *, nvme_ioctl_ctrl_info_t *);
508 extern bool nvme_ioc_ns_info(nvme_ctrl_t *, uint32_t, nvme_ioctl_ns_info_t *);
509 
510 /*
511  * Common validation template functions.
512  */
513 extern bool nvme_field_miss_err(nvme_ctrl_t *, const nvme_field_info_t *,
514     size_t, nvme_err_t, const char *, uint32_t);
515 
516 typedef struct {
517 	const nvme_field_info_t *chk_fields;
518 	size_t chk_index;
519 	nvme_err_t chk_field_range;
520 	nvme_err_t chk_field_unsup;
521 	nvme_err_t chk_field_unuse;
522 } nvme_field_check_t;
523 
524 extern bool nvme_field_check_one(nvme_ctrl_t *, uint64_t, const char *,
525     const nvme_field_check_t *, uint32_t allow);
526 extern bool nvme_field_valid_impact(nvme_ctrl_t *, nvme_disc_impact_t,
527     nvme_err_t);
528 
529 /*
530  * Misc. functions.
531  */
532 extern const char *nvme_tporttostr(nvme_ctrl_transport_t);
533 extern nvme_ns_disc_level_t nvme_ns_state_to_disc_level(nvme_ns_state_t);
534 extern const char *nvme_nsleveltostr(nvme_ns_disc_level_t);
535 
536 /*
537  * Version related information and functions. There are statically declared
538  * version structures in the library for use for internal comparisons. Note, we
539  * have attempted to avoid a general comparison function in the internal API so
540  * that way it's always clear what we're comparing to a version and can't
541  * reverse things.
542  */
543 extern const nvme_version_t nvme_vers_1v0;
544 extern const nvme_version_t nvme_vers_1v1;
545 extern const nvme_version_t nvme_vers_1v2;
546 extern const nvme_version_t nvme_vers_1v3;
547 extern const nvme_version_t nvme_vers_1v4;
548 extern const nvme_version_t nvme_vers_2v0;
549 
550 extern bool nvme_vers_ctrl_atleast(const nvme_ctrl_t *, const nvme_version_t *);
551 extern bool nvme_vers_ctrl_info_atleast(const nvme_ctrl_info_t *,
552     const nvme_version_t *);
553 extern bool nvme_vers_ns_info_atleast(const nvme_ns_info_t *,
554     const nvme_version_t *);
555 
556 /*
557  * Vendor-specific information.
558  */
559 typedef struct nvme_vsd_ident {
560 	const char *nvdi_human;
561 	bool nvdi_subsys;
562 	uint16_t nvdi_vid;
563 	uint16_t nvdi_did;
564 	uint16_t nvdi_svid;
565 	uint16_t nvdi_sdid;
566 } nvme_vsd_ident_t;
567 
568 typedef struct nvme_vsd {
569 	const nvme_vsd_ident_t *nvd_ident;
570 	size_t nvd_nident;
571 	const nvme_log_page_info_t *const *nvd_logs;
572 	size_t nvd_nlogs;
573 	const nvme_vuc_disc_t *nvd_vuc;
574 	size_t nvd_nvuc;
575 	const nvme_feat_info_t *const *nvd_feats;
576 	size_t nvd_nfeats;
577 } nvme_vsd_t;
578 
579 extern const nvme_log_page_info_t ocp_log_smart;
580 extern const nvme_log_page_info_t ocp_log_errrec;
581 extern const nvme_log_page_info_t ocp_log_fwact;
582 extern const nvme_log_page_info_t ocp_log_lat;
583 extern const nvme_log_page_info_t ocp_log_devcap;
584 extern const nvme_log_page_info_t ocp_log_unsup;
585 extern const nvme_log_page_info_t ocp_log_hwcomp;
586 extern const nvme_log_page_info_t ocp_log_telstr;
587 
588 extern const nvme_feat_info_t ocp_feat_errinj;
589 extern const nvme_feat_info_t ocp_feat_plpfail;
590 extern const nvme_feat_info_t ocp_feat_plphealth;
591 
592 extern const nvme_vsd_t wdc_sn840;
593 extern const nvme_vsd_t wdc_sn65x;
594 extern const nvme_vsd_t sandisk_sn861;
595 extern const nvme_vsd_t micron_7300;
596 extern const nvme_vsd_t micron_74x0;
597 extern const nvme_vsd_t micron_x500;
598 extern const nvme_vsd_t micron_7600;
599 extern const nvme_vsd_t micron_9550;
600 extern const nvme_vsd_t intel_p5510;
601 extern const nvme_vsd_t solidigm_p5x20;
602 extern const nvme_vsd_t solidigm_ps10x0;
603 extern const nvme_vsd_t kioxia_cd8;
604 extern const nvme_vsd_t phison_x200;
605 extern const nvme_vsd_t samsung_pm9d3a;
606 
607 extern void nvme_vendor_map_ctrl(nvme_ctrl_t *);
608 extern bool nvme_vendor_vuc_supported(nvme_ctrl_t *, const char *);
609 extern bool nvme_vendor_feature_supported(nvme_ctrl_t *, const char *);
610 
611 /*
612  * Internal formatting functions that probably could be external.
613  */
614 #define	NVME_NGUID_NAMELEN	33
615 #define	NVME_EUI64_NAMELEN	17
616 
617 extern int nvme_format_nguid(const uint8_t [16], char *, size_t);
618 extern int nvme_format_eui64(const uint8_t [8], char *, size_t);
619 
620 #ifdef __cplusplus
621 }
622 #endif
623 
624 #endif /* _LIBNVME_IMPL_H */
625