1/*	$NetBSD: nvmeio.h,v 1.4 2021/11/10 17:19:30 msaitoh Exp $	*/
2
3/*-
4 * Copyright (C) 2012-2013 Intel Corporation
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/nvme/nvme.h 329824 2018-02-22 13:32:31Z wma $
29 */
30
31#ifndef __NVMEIO_H__
32#define __NVMEIO_H__
33
34#include <sys/endian.h>
35#include <sys/ioccom.h>
36#include <dev/ic/nvmereg.h>
37
38#define	NVME_PASSTHROUGH_CMD		_IOWR('n', 0, struct nvme_pt_command)
39
40#define	nvme_completion_is_error(cpl)					\
41	((NVME_CQE_SC((cpl)->flags) != NVME_CQE_SC_SUCCESS)   		\
42	    || (NVME_CQE_SCT((cpl)->flags) != NVME_CQE_SCT_GENERIC))
43
44struct nvme_pt_command {
45
46	/*
47	 * cmd is used to specify a passthrough command to a controller or
48	 *  namespace.
49	 *
50	 * The following fields from cmd may be specified by the caller:
51	 *	* opcode
52	 *	* nsid (namespace id) - for admin commands only
53	 *	* cdw10-cdw15
54	 *
55	 * Remaining fields must be set to 0 by the caller.
56	 */
57	struct nvme_sqe		cmd;
58
59	/*
60	 * cpl returns completion status for the passthrough command
61	 *  specified by cmd.
62	 *
63	 * The following fields will be filled out by the driver, for
64	 *  consumption by the caller:
65	 *	* cdw0
66	 *	* flags (except for phase)
67	 *
68	 * Remaining fields will be set to 0 by the driver.
69	 */
70	struct nvme_cqe		cpl;
71
72	/* buf is the data buffer associated with this passthrough command. */
73	void			*buf;
74
75	/*
76	 * len is the length of the data buffer associated with this
77	 *  passthrough command.
78	 */
79	uint32_t		len;
80
81	/*
82	 * is_read = 1 if the passthrough command will read data into the
83	 *  supplied buffer from the controller.
84	 *
85	 * is_read = 0 if the passthrough command will write data from the
86	 *  supplied buffer to the controller.
87	 */
88	uint32_t		is_read;
89
90	/*
91	 * timeout (unit: ms)
92	 *
93	 * 0: use default timeout value
94	 */
95	uint32_t		timeout;
96};
97
98/* Endianness conversion functions for NVMe structs */
99static __inline void
100nvme_le128toh(uint64_t v[2])
101{
102#if _BYTE_ORDER != _LITTLE_ENDIAN
103	uint64_t t;
104
105	t = le64toh(v[0]);
106	v[0] = le64toh(v[1]);
107	v[1] = t;
108#endif
109}
110
111static __inline void
112nvme_namespace_format_swapbytes(struct nvm_namespace_format *format)
113{
114
115#if _BYTE_ORDER != _LITTLE_ENDIAN
116	format->ms = le16toh(format->ms);
117#endif
118}
119
120static __inline void
121nvme_identify_namespace_swapbytes(struct nvm_identify_namespace *identify)
122{
123#if _BYTE_ORDER != _LITTLE_ENDIAN
124	u_int i;
125
126	identify->nsze = le64toh(identify->nsze);
127	identify->ncap = le64toh(identify->ncap);
128	identify->nuse = le64toh(identify->nuse);
129	identify->nawun = le16toh(identify->nawun);
130	identify->nawupf = le16toh(identify->nawupf);
131	identify->nacwu = le16toh(identify->nacwu);
132	identify->nabsn = le16toh(identify->nabsn);
133	identify->nabo = le16toh(identify->nabo);
134	identify->nabspf = le16toh(identify->nabspf);
135	identify->noiob = le16toh(identify->noiob);
136	for (i = 0; i < __arraycount(identify->lbaf); i++)
137		nvme_namespace_format_swapbytes(&identify->lbaf[i]);
138#endif
139}
140
141static __inline void
142nvme_identify_psd_swapbytes(struct nvm_identify_psd *psd)
143{
144
145#if _BYTE_ORDER != _LITTLE_ENDIAN
146	psd->mp = le16toh(psd->mp);
147	psd->enlat = le32toh(psd->enlat);
148	psd->exlat = le32toh(psd->exlat);
149	psd->idlp = le16toh(psd->idlp);
150	psd->actp = le16toh(psd->actp);
151	psd->ap = le16toh(psd->ap);
152#endif
153}
154
155static __inline void
156nvme_identify_controller_swapbytes(struct nvm_identify_controller *identify)
157{
158#if _BYTE_ORDER != _LITTLE_ENDIAN
159	u_int i;
160
161	identify->vid = le16toh(identify->vid);
162	identify->ssvid = le16toh(identify->ssvid);
163	identify->cntlid = le16toh(identify->cntlid);
164	identify->ver = le32toh(identify->ver);
165	identify->rtd3r = le32toh(identify->rtd3r);
166	identify->rtd3e = le32toh(identify->rtd3e);
167	identify->oaes = le32toh(identify->oaes);
168	identify->ctrattr = le32toh(identify->ctrattr);
169	identify->oacs = le16toh(identify->oacs);
170	identify->wctemp = le16toh(identify->wctemp);
171	identify->cctemp = le16toh(identify->cctemp);
172	identify->mtfa = le16toh(identify->mtfa);
173	identify->hmpre = le32toh(identify->hmpre);
174	identify->hmmin = le32toh(identify->hmmin);
175	nvme_le128toh(identify->untncap.tnvmcap);
176	nvme_le128toh(identify->untncap.unvmcap);
177	identify->rpmbs = le32toh(identify->rpmbs);
178	identify->edstt = le16toh(identify->edstt);
179	identify->kas = le16toh(identify->kas);
180	identify->hctma = le16toh(identify->hctma);
181	identify->mntmt = le16toh(identify->mntmt);
182	identify->mxtmt = le16toh(identify->mxtmt);
183	identify->sanicap = le32toh(identify->sanicap);
184	identify->maxcmd = le16toh(identify->maxcmd);
185	identify->nn = le32toh(identify->nn);
186	identify->oncs = le16toh(identify->oncs);
187	identify->fuses = le16toh(identify->fuses);
188	identify->awun = le16toh(identify->awun);
189	identify->awupf = le16toh(identify->awupf);
190	identify->acwu = le16toh(identify->acwu);
191	identify->sgls = le32toh(identify->sgls);
192	for (i = 0; i < __arraycount(identify->psd); i++)
193		nvme_identify_psd_swapbytes(&identify->psd[i]);
194#endif
195}
196
197#endif /* __NVMEIO_H__ */
198