xref: /openbsd-src/sys/dev/ic/nvmereg.h (revision 3800fc3581d8812fd1c522b2a75e85fb3d9ce5db)
1*3800fc35Sjmatthew /*	$OpenBSD: nvmereg.h,v 1.16 2024/09/13 09:57:34 jmatthew Exp $ */
2282c0692Sdlg 
3282c0692Sdlg /*
4282c0692Sdlg  * Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
5282c0692Sdlg  *
6282c0692Sdlg  * Permission to use, copy, modify, and distribute this software for any
7282c0692Sdlg  * purpose with or without fee is hereby granted, provided that the above
8282c0692Sdlg  * copyright notice and this permission notice appear in all copies.
9282c0692Sdlg  *
10282c0692Sdlg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11282c0692Sdlg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12282c0692Sdlg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13282c0692Sdlg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14282c0692Sdlg  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15282c0692Sdlg  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16282c0692Sdlg  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17282c0692Sdlg  */
18282c0692Sdlg 
19282c0692Sdlg #define NVME_CAP	0x0000	/* Controller Capabilities */
20282c0692Sdlg #define  NVME_CAP_MPSMAX(_r)	(12 + (((_r) >> 52) & 0xf)) /* shift */
21282c0692Sdlg #define  NVME_CAP_MPSMIN(_r)	(12 + (((_r) >> 48) & 0xf)) /* shift */
22282c0692Sdlg #define  NVME_CAP_CSS(_r)	(((_r) >> 37) & 0x7f)
23282c0692Sdlg #define  NVME_CAP_CSS_NVM	(1 << 0)
24282c0692Sdlg #define  NVME_CAP_NSSRS(_r)	ISSET((_r), (1ULL << 36))
25282c0692Sdlg #define  NVME_CAP_DSTRD(_r)	(1 << (2 + (((_r) >> 32) & 0xf))) /* bytes */
26282c0692Sdlg #define  NVME_CAP_TO(_r)	(500 * (((_r) >> 24) & 0xff)) /* ms */
27282c0692Sdlg #define  NVME_CAP_AMS(_r)	(((_r) >> 17) & 0x3)
28282c0692Sdlg #define  NVME_CAP_AMS_WRR	(1 << 0)
29282c0692Sdlg #define  NVME_CAP_AMS_VENDOR	(1 << 1)
30282c0692Sdlg #define  NVME_CAP_CQR(_r)	ISSET((_r), (1 << 16))
3184a80625Sdlg #define  NVME_CAP_MQES(_r)	(((_r) & 0xffff) + 1)
32282c0692Sdlg #define NVME_CAP_LO	0x0000
33282c0692Sdlg #define NVME_CAP_HI	0x0004
34282c0692Sdlg #define NVME_VS		0x0008	/* Version */
35a4fcfefeSmpi #define  NVME_VS_MJR(_r)	(((_r) & 0xffff0000) >> 16)
36a4fcfefeSmpi #define  NVME_VS_MNR(_r)	(((_r) & 0x0000ff00) >> 8)
37282c0692Sdlg #define NVME_INTMS	0x000c	/* Interrupt Mask Set */
38282c0692Sdlg #define NVME_INTMC	0x0010	/* Interrupt Mask Clear */
39282c0692Sdlg #define NVME_CC		0x0014	/* Controller Configuration */
40282c0692Sdlg #define  NVME_CC_IOCQES(_v)	(((_v) & 0xf) << 20)
41282c0692Sdlg #define  NVME_CC_IOCQES_MASK	NVME_CC_IOCQES(0xf)
42282c0692Sdlg #define  NVME_CC_IOCQES_R(_v)	(((_v) >> 20) & 0xf)
43282c0692Sdlg #define  NVME_CC_IOSQES(_v)	(((_v) & 0xf) << 16)
44282c0692Sdlg #define  NVME_CC_IOSQES_MASK	NVME_CC_IOSQES(0xf)
45282c0692Sdlg #define  NVME_CC_IOSQES_R(_v)	(((_v) >> 16) & 0xf)
46282c0692Sdlg #define  NVME_CC_SHN(_v)	(((_v) & 0x3) << 14)
47282c0692Sdlg #define  NVME_CC_SHN_MASK	NVME_CC_SHN(0x3)
48282c0692Sdlg #define  NVME_CC_SHN_R(_v)	(((_v) >> 15) & 0x3)
49282c0692Sdlg #define  NVME_CC_SHN_NONE	0
50282c0692Sdlg #define  NVME_CC_SHN_NORMAL	1
51282c0692Sdlg #define  NVME_CC_SHN_ABRUPT	2
52282c0692Sdlg #define  NVME_CC_AMS(_v)	(((_v) & 0x7) << 11)
53282c0692Sdlg #define  NVME_CC_AMS_MASK	NVME_CC_AMS(0x7)
54282c0692Sdlg #define  NVME_CC_AMS_R(_v)	(((_v) >> 11) & 0xf)
55282c0692Sdlg #define  NVME_CC_AMS_RR		0 /* round-robin */
56282c0692Sdlg #define  NVME_CC_AMS_WRR_U	1 /* weighted round-robin w/ urgent */
57282c0692Sdlg #define  NVME_CC_AMS_VENDOR	7 /* vendor */
58282c0692Sdlg #define  NVME_CC_MPS(_v)	((((_v) - 12) & 0xf) << 7)
59282c0692Sdlg #define  NVME_CC_MPS_MASK	(0xf << 7)
60282c0692Sdlg #define  NVME_CC_MPS_R(_v)	(12 + (((_v) >> 7) & 0xf))
61282c0692Sdlg #define  NVME_CC_CSS(_v)	(((_v) & 0x7) << 4)
62282c0692Sdlg #define  NVME_CC_CSS_MASK	NVME_CC_CSS(0x7)
63282c0692Sdlg #define  NVME_CC_CSS_R(_v)	(((_v) >> 4) & 0x7)
64282c0692Sdlg #define  NVME_CC_CSS_NVM	0
65282c0692Sdlg #define  NVME_CC_EN		(1 << 0)
66282c0692Sdlg #define NVME_CSTS	0x001c	/* Controller Status */
675313ab17Sdlg #define  NVME_CSTS_SHST_MASK	(0x3 << 2)
685313ab17Sdlg #define  NVME_CSTS_SHST_NONE	(0x0 << 2) /* normal operation */
695313ab17Sdlg #define  NVME_CSTS_SHST_WAIT	(0x1 << 2) /* shutdown processing occurring */
705313ab17Sdlg #define  NVME_CSTS_SHST_DONE	(0x2 << 2) /* shutdown processing complete */
71282c0692Sdlg #define  NVME_CSTS_CFS		(1 << 1)
72282c0692Sdlg #define  NVME_CSTS_RDY		(1 << 0)
73282c0692Sdlg #define NVME_NSSR	0x0020	/* NVM Subsystem Reset (Optional) */
74282c0692Sdlg #define NVME_AQA	0x0024	/* Admin Queue Attributes */
75282c0692Sdlg 				/* Admin Completion Queue Size */
76282c0692Sdlg #define  NVME_AQA_ACQS(_v)	(((_v) - 1) << 16)
77282c0692Sdlg 				/* Admin Submission Queue Size */
78282c0692Sdlg #define  NVME_AQA_ASQS(_v)	(((_v) - 1) << 0)
79282c0692Sdlg #define NVME_ASQ	0x0028	/* Admin Submission Queue Base Address */
80282c0692Sdlg #define NVME_ACQ	0x0030	/* Admin Completion Queue Base Address */
81282c0692Sdlg 
82282c0692Sdlg #define NVME_ADMIN_Q		0
83282c0692Sdlg /* Submission Queue Tail Doorbell */
84282c0692Sdlg #define NVME_SQTDBL(_q, _s)	(0x1000 + (2 * (_q) + 0) * (_s))
85448b3c09Sdlg /* Completion Queue Head Doorbell */
86448b3c09Sdlg #define NVME_CQHDBL(_q, _s)	(0x1000 + (2 * (_q) + 1) * (_s))
87282c0692Sdlg 
88282c0692Sdlg struct nvme_sge {
89282c0692Sdlg 	u_int8_t	id;
90282c0692Sdlg 	u_int8_t	_reserved[15];
91282c0692Sdlg } __packed __aligned(8);
92282c0692Sdlg 
93282c0692Sdlg struct nvme_sge_data {
94282c0692Sdlg 	u_int8_t	id;
95282c0692Sdlg 	u_int8_t	_reserved[3];
96282c0692Sdlg 
97282c0692Sdlg 	u_int32_t	length;
98282c0692Sdlg 
99282c0692Sdlg 	u_int64_t	address;
100282c0692Sdlg } __packed __aligned(8);
101282c0692Sdlg 
102282c0692Sdlg struct nvme_sge_bit_bucket {
103282c0692Sdlg 	u_int8_t	id;
104282c0692Sdlg 	u_int8_t	_reserved[3];
105282c0692Sdlg 
106282c0692Sdlg 	u_int32_t	length;
107282c0692Sdlg 
108282c0692Sdlg 	u_int64_t	address;
109282c0692Sdlg } __packed __aligned(8);
110282c0692Sdlg 
111282c0692Sdlg struct nvme_sqe {
112282c0692Sdlg 	u_int8_t	opcode;
113282c0692Sdlg 	u_int8_t	flags;
114282c0692Sdlg 	u_int16_t	cid;
115282c0692Sdlg 
116282c0692Sdlg 	u_int32_t	nsid;
117282c0692Sdlg 
118282c0692Sdlg 	u_int8_t	_reserved[8];
119282c0692Sdlg 
120282c0692Sdlg 	u_int64_t	mptr;
121282c0692Sdlg 
122282c0692Sdlg 	union {
123282c0692Sdlg 		u_int64_t	prp[2];
124282c0692Sdlg 		struct nvme_sge	sge;
125282c0692Sdlg 	} __packed	entry;
126282c0692Sdlg 
127282c0692Sdlg 	u_int32_t	cdw10;
128282c0692Sdlg 	u_int32_t	cdw11;
129282c0692Sdlg 	u_int32_t	cdw12;
130282c0692Sdlg 	u_int32_t	cdw13;
131282c0692Sdlg 	u_int32_t	cdw14;
132282c0692Sdlg 	u_int32_t	cdw15;
133282c0692Sdlg } __packed __aligned(8);
1341b7032ebSdlg 
1353e780090Sdlg struct nvme_sqe_q {
1363e780090Sdlg 	u_int8_t	opcode;
1373e780090Sdlg 	u_int8_t	flags;
1383e780090Sdlg 	u_int16_t	cid;
1393e780090Sdlg 
1403e780090Sdlg 	u_int8_t	_reserved1[20];
1413e780090Sdlg 
1423e780090Sdlg 	u_int64_t	prp1;
1433e780090Sdlg 
1443e780090Sdlg 	u_int8_t	_reserved2[8];
1453e780090Sdlg 
1463e780090Sdlg 	u_int16_t	qid;
1473e780090Sdlg 	u_int16_t	qsize;
1483e780090Sdlg 
1493e780090Sdlg 	u_int8_t	qflags;
1503e780090Sdlg #define NVM_SQE_SQ_QPRIO_URG	(0x0 << 1)
1513e780090Sdlg #define NVM_SQE_SQ_QPRIO_HI	(0x1 << 1)
1523e780090Sdlg #define NVM_SQE_SQ_QPRIO_MED	(0x2 << 1)
1533e780090Sdlg #define NVM_SQE_SQ_QPRIO_LOW	(0x3 << 1)
1545313ab17Sdlg #define NVM_SQE_CQ_IEN		(1 << 1)
1553e780090Sdlg #define NVM_SQE_Q_PC		(1 << 0)
1563e780090Sdlg 	u_int8_t	_reserved3;
1573e780090Sdlg 	u_int16_t	cqid; /* XXX interrupt vector for cq */
1583e780090Sdlg 
1593e780090Sdlg 	u_int8_t	_reserved4[16];
1603e780090Sdlg } __packed __aligned(8);
1613e780090Sdlg 
1623e780090Sdlg struct nvme_sqe_io {
1633e780090Sdlg 	u_int8_t	opcode;
1643e780090Sdlg 	u_int8_t	flags;
1653e780090Sdlg 	u_int16_t	cid;
1663e780090Sdlg 
1673e780090Sdlg 	u_int32_t	nsid;
1683e780090Sdlg 
1693e780090Sdlg 	u_int8_t	_reserved[8];
1703e780090Sdlg 
1713e780090Sdlg 	u_int64_t	mptr;
1723e780090Sdlg 
1733e780090Sdlg 	union {
1743e780090Sdlg 		u_int64_t	prp[2];
1753e780090Sdlg 		struct nvme_sge	sge;
1763e780090Sdlg 	} __packed	entry;
1773e780090Sdlg 
1783e780090Sdlg 	u_int64_t	slba;	/* Starting LBA */
1793e780090Sdlg 
1803e780090Sdlg 	u_int16_t	nlb;	/* Number of Logical Blocks */
1813e780090Sdlg 	u_int16_t	ioflags;
1823e780090Sdlg 
1833e780090Sdlg 	u_int8_t	dsm;	/* Dataset Management */
1843e780090Sdlg 	u_int8_t	_reserved2[3];
1853e780090Sdlg 
1863e780090Sdlg 	u_int32_t	eilbrt;	/* Expected Initial Logical Block
1873e780090Sdlg 				   Reference Tag */
1883e780090Sdlg 
1893e780090Sdlg 	u_int16_t	elbat;	/* Expected Logical Block
1903e780090Sdlg 				   Application Tag */
1913e780090Sdlg 	u_int16_t	elbatm;	/* Expected Logical Block
1923e780090Sdlg 				   Application Tag Mask */
1933e780090Sdlg } __packed __aligned(8);
1943e780090Sdlg 
195448b3c09Sdlg struct nvme_cqe {
196448b3c09Sdlg 	u_int32_t	cdw0;
197448b3c09Sdlg 
198448b3c09Sdlg 	u_int32_t	_reserved;
199448b3c09Sdlg 
200448b3c09Sdlg 	u_int16_t	sqhd; /* SQ Head Pointer */
201448b3c09Sdlg 	u_int16_t	sqid; /* SQ Identifier */
202448b3c09Sdlg 
203448b3c09Sdlg 	u_int16_t	cid; /* Command Identifier */
204448b3c09Sdlg 	u_int16_t	flags;
205448b3c09Sdlg #define NVME_CQE_DNR		(1 << 15)
206448b3c09Sdlg #define NVME_CQE_M		(1 << 14)
207b798bbb2Skrw #define NVME_CQE_SCT(_f)	((_f) & (0x07 << 9))
208b798bbb2Skrw #define  NVME_CQE_SCT_GENERIC		(0x00 << 9)
209b798bbb2Skrw #define  NVME_CQE_SCT_COMMAND		(0x01 << 9)
210b798bbb2Skrw #define  NVME_CQE_SCT_MEDIAERR		(0x02 << 9)
211b798bbb2Skrw #define  NVME_CQE_SCT_VENDOR		(0x07 << 9)
212b798bbb2Skrw #define NVME_CQE_SC(_f)		((_f) & (0xff << 1))
2139f81ea3bSdlg #define  NVME_CQE_SC_SUCCESS		(0x00 << 1)
2149f81ea3bSdlg #define  NVME_CQE_SC_INVALID_OPCODE	(0x01 << 1)
2159f81ea3bSdlg #define  NVME_CQE_SC_INVALID_FIELD	(0x02 << 1)
2169f81ea3bSdlg #define  NVME_CQE_SC_CID_CONFLICT	(0x03 << 1)
2179f81ea3bSdlg #define  NVME_CQE_SC_DATA_XFER_ERR	(0x04 << 1)
2189f81ea3bSdlg #define  NVME_CQE_SC_ABRT_BY_NO_PWR	(0x05 << 1)
2199f81ea3bSdlg #define  NVME_CQE_SC_INTERNAL_DEV_ERR	(0x06 << 1)
2209f81ea3bSdlg #define  NVME_CQE_SC_CMD_ABRT_REQD	(0x07 << 1)
2219f81ea3bSdlg #define  NVME_CQE_SC_CMD_ABDR_SQ_DEL	(0x08 << 1)
2229f81ea3bSdlg #define  NVME_CQE_SC_CMD_ABDR_FUSE_ERR	(0x09 << 1)
2239f81ea3bSdlg #define  NVME_CQE_SC_CMD_ABDR_FUSE_MISS	(0x0a << 1)
2249f81ea3bSdlg #define  NVME_CQE_SC_INVALID_NS		(0x0b << 1)
2259f81ea3bSdlg #define  NVME_CQE_SC_CMD_SEQ_ERR	(0x0c << 1)
2269f81ea3bSdlg #define  NVME_CQE_SC_INVALID_LAST_SGL	(0x0d << 1)
2279f81ea3bSdlg #define  NVME_CQE_SC_INVALID_NUM_SGL	(0x0e << 1)
2289f81ea3bSdlg #define  NVME_CQE_SC_DATA_SGL_LEN	(0x0f << 1)
2299f81ea3bSdlg #define  NVME_CQE_SC_MDATA_SGL_LEN	(0x10 << 1)
2309f81ea3bSdlg #define  NVME_CQE_SC_SGL_TYPE_INVALID	(0x11 << 1)
2319f81ea3bSdlg #define  NVME_CQE_SC_LBA_RANGE		(0x80 << 1)
2329f81ea3bSdlg #define  NVME_CQE_SC_CAP_EXCEEDED	(0x81 << 1)
2339f81ea3bSdlg #define  NVME_CQE_NS_NOT_RDY		(0x82 << 1)
2349f81ea3bSdlg #define  NVME_CQE_RSV_CONFLICT		(0x83 << 1)
235448b3c09Sdlg #define NVME_CQE_PHASE		(1 << 0)
236448b3c09Sdlg } __packed __aligned(8);
237448b3c09Sdlg 
238448b3c09Sdlg #define NVM_ADMIN_DEL_IOSQ	0x00 /* Delete I/O Submission Queue */
239448b3c09Sdlg #define NVM_ADMIN_ADD_IOSQ	0x01 /* Create I/O Submission Queue */
240448b3c09Sdlg #define NVM_ADMIN_GET_LOG_PG	0x02 /* Get Log Page */
241448b3c09Sdlg #define NVM_ADMIN_DEL_IOCQ	0x04 /* Delete I/O Completion Queue */
242448b3c09Sdlg #define NVM_ADMIN_ADD_IOCQ	0x05 /* Create I/O Completion Queue */
243448b3c09Sdlg #define NVM_ADMIN_IDENTIFY	0x06 /* Identify */
244448b3c09Sdlg #define NVM_ADMIN_ABORT		0x08 /* Abort */
245448b3c09Sdlg #define NVM_ADMIN_SET_FEATURES	0x09 /* Set Features */
246448b3c09Sdlg #define NVM_ADMIN_GET_FEATURES	0x0a /* Get Features */
247448b3c09Sdlg #define NVM_ADMIN_ASYNC_EV_REQ	0x0c /* Asynchronous Event Request */
248448b3c09Sdlg #define NVM_ADMIN_FW_ACTIVATE	0x10 /* Firmware Activate */
249448b3c09Sdlg #define NVM_ADMIN_FW_DOWNLOAD	0x11 /* Firmware Image Download */
2504e9514d6Skrw #define NVM_ADMIN_SELFTEST	0x14 /* Start self test */
251448b3c09Sdlg 
252d01f48b5Sdlg #define NVM_CMD_FLUSH		0x00 /* Flush */
253d01f48b5Sdlg #define NVM_CMD_WRITE		0x01 /* Write */
254d01f48b5Sdlg #define NVM_CMD_READ		0x02 /* Read */
255d01f48b5Sdlg #define NVM_CMD_WR_UNCOR	0x04 /* Write Uncorrectable */
256d01f48b5Sdlg #define NVM_CMD_COMPARE		0x05 /* Compare */
257d01f48b5Sdlg #define NVM_CMD_DSM		0x09 /* Dataset Management */
258d01f48b5Sdlg 
259448b3c09Sdlg /* Power State Descriptor Data */
260448b3c09Sdlg struct nvm_identify_psd {
261448b3c09Sdlg 	u_int16_t	mp;		/* Max Power */
262448b3c09Sdlg 	u_int16_t	flags;
263448b3c09Sdlg 
264448b3c09Sdlg 	u_int32_t	enlat;		/* Entry Latency */
265448b3c09Sdlg 
266448b3c09Sdlg 	u_int32_t	exlat;		/* Exit Latency */
267448b3c09Sdlg 
268448b3c09Sdlg 	u_int8_t	rrt;		/* Relative Read Throughput */
269448b3c09Sdlg 	u_int8_t	rrl;		/* Relative Read Latency */
270448b3c09Sdlg 	u_int8_t	rwt;		/* Relative Write Throughput */
271448b3c09Sdlg 	u_int8_t	rwl;		/* Relative Write Latency */
272448b3c09Sdlg 
273448b3c09Sdlg 	u_int8_t	_reserved[16];
274448b3c09Sdlg } __packed __aligned(8);
275448b3c09Sdlg 
276448b3c09Sdlg struct nvm_identify_controller {
277448b3c09Sdlg 	/* Controller Capabilities and Features */
278448b3c09Sdlg 
279448b3c09Sdlg 	u_int16_t	vid;		/* PCI Vendor ID */
280448b3c09Sdlg 	u_int16_t	ssvid;		/* PCI Subsystem Vendor ID */
281448b3c09Sdlg 
282448b3c09Sdlg 	u_int8_t	sn[20];		/* Serial Number */
283448b3c09Sdlg 	u_int8_t	mn[40];		/* Model Number */
2849f81ea3bSdlg 	u_int8_t	fr[8];		/* Firmware Revision */
285448b3c09Sdlg 
286448b3c09Sdlg 	u_int8_t	rab;		/* Recommended Arbitration Burst */
287448b3c09Sdlg 	u_int8_t	ieee[3];	/* IEEE OUI Identifier */
288448b3c09Sdlg 
289448b3c09Sdlg 	u_int8_t	cmic;		/* Controller Multi-Path I/O and
290448b3c09Sdlg 					   Namespace Sharing Capabilities */
291448b3c09Sdlg 	u_int8_t	mdts;		/* Maximum Data Transfer Size */
292448b3c09Sdlg 	u_int16_t	cntlid;		/* Controller ID */
293448b3c09Sdlg 
2947f4636ceSkrw 	u_int8_t	_reserved1[16];
2957f4636ceSkrw 	u_int32_t	ctratt;
2967f4636ceSkrw #define NVM_ID_CTRL_CTRATT_FMT			"\020" \
2977f4636ceSkrw 	"\016DELEG" "\017DEVNVM" "\020ELBAS" "\005ENDURGRPS" \
2987f4636ceSkrw 	"\014FIXCAPMGMT" "\001HOSTID" "\013MDS" "\002NOPSPM" \
2997f4636ceSkrw 	"\010NSGRAN" "\003NVMSETS" "\006PREDLATENCY" "\004READRCVRY" \
3007f4636ceSkrw 	"\011SQASSOC" "\007TBKAS" "\012UUIDLIST" "\015VARCAPMGMT"
3017f4636ceSkrw 
3027f4636ceSkrw 	u_int8_t	_reserved9[156];
303448b3c09Sdlg 
304448b3c09Sdlg 	/* Admin Command Set Attributes & Optional Controller Capabilities */
305448b3c09Sdlg 
306448b3c09Sdlg 	u_int16_t	oacs;		/* Optional Admin Command Support */
3077f4636ceSkrw #define NVM_ID_CTRL_OACS_FMT			"\020" \
3087f4636ceSkrw 	"\013CAFL" "\011DBBC" "\006DIREC" "\005DST" "\012GLBAS" \
3097f4636ceSkrw 	"\002FORMAT" "\003FWCD" "\007MISR" "\004NSMGMT" "\001SECSR" \
3107f4636ceSkrw 	"\010VM"
3117f4636ceSkrw 
312448b3c09Sdlg 	u_int8_t	acl;		/* Abort Command Limit */
313448b3c09Sdlg 	u_int8_t	aerl;		/* Asynchronous Event Request Limit */
314448b3c09Sdlg 
315448b3c09Sdlg 	u_int8_t	frmw;		/* Firmware Updates */
316448b3c09Sdlg 	u_int8_t	lpa;		/* Log Page Attributes */
3177f4636ceSkrw #define NVM_ID_CTRL_LPA_PE		(1 << 4)
318448b3c09Sdlg 	u_int8_t	elpe;		/* Error Log Page Entries */
319448b3c09Sdlg 	u_int8_t	npss;		/* Number of Power States Support */
320448b3c09Sdlg 
321448b3c09Sdlg 	u_int8_t	avscc;		/* Admin Vendor Specific Command
322448b3c09Sdlg 					   Configuration */
323448b3c09Sdlg 	u_int8_t	apsta;		/* Autonomous Power State Transition
324448b3c09Sdlg 					   Attributes */
325448b3c09Sdlg 
3267f4636ceSkrw 	u_int8_t	_reserved2[62];
3277f4636ceSkrw 	u_int32_t	sanicap;
3287f4636ceSkrw #define NVM_ID_CTRL_SANICAP_FMT			"\020" \
3297f4636ceSkrw 	"\002BlockErase" "\001CryptoErase" "\003Overwrite"
3307f4636ceSkrw 	u_int8_t	_reserved10[180];
331448b3c09Sdlg 
332448b3c09Sdlg 	/* NVM Command Set Attributes */
333448b3c09Sdlg 
334448b3c09Sdlg 	u_int8_t	sqes;		/* Submission Queue Entry Size */
335448b3c09Sdlg 	u_int8_t	cqes;		/* Completion Queue Entry Size */
336448b3c09Sdlg 	u_int8_t	_reserved3[2];
337448b3c09Sdlg 
338448b3c09Sdlg 	u_int32_t	nn;		/* Number of Namespaces */
339448b3c09Sdlg 
340448b3c09Sdlg 	u_int16_t	oncs;		/* Optional NVM Command Support */
3417f4636ceSkrw #define NVM_ID_CTRL_ONCS_FMT			"\020" \
3427f4636ceSkrw 	"\006RSV" "\001SCMP" "\011SCPY" "\003SDMGMT" "\005SF" \
3437f4636ceSkrw 	"\010SV" "\002SWU" "\004SWZ" "\007TS"
3447f4636ceSkrw 
345448b3c09Sdlg 	u_int16_t	fuses;		/* Fused Operation Support */
346448b3c09Sdlg 
347448b3c09Sdlg 	u_int8_t	fna;		/* Format NVM Attributes */
3487f4636ceSkrw #define NVM_ID_CTRL_FNA_CRYPTOFORMAT		(1 << 2)
349448b3c09Sdlg 	u_int8_t	vwc;		/* Volatile Write Cache */
3507f4636ceSkrw #define NVM_ID_CTRL_VWC_PRESENT			(1 << 0)
351448b3c09Sdlg 	u_int16_t	awun;		/* Atomic Write Unit Normal */
352448b3c09Sdlg 
353448b3c09Sdlg 	u_int16_t	awupf;		/* Atomic Write Unit Power Fail */
354448b3c09Sdlg 	u_int8_t	nvscc;		/* NVM Vendor Specific Command */
355448b3c09Sdlg 	u_int8_t	_reserved4[1];
356448b3c09Sdlg 
357448b3c09Sdlg 	u_int16_t	acwu;		/* Atomic Compare & Write Unit */
358448b3c09Sdlg 	u_int8_t	_reserved5[2];
359448b3c09Sdlg 
360448b3c09Sdlg 	u_int32_t	sgls;		/* SGL Support */
361448b3c09Sdlg 
362448b3c09Sdlg 	u_int8_t	_reserved6[164];
363448b3c09Sdlg 
364448b3c09Sdlg 	/* I/O Command Set Attributes */
365448b3c09Sdlg 
366448b3c09Sdlg 	u_int8_t	_reserved7[1344];
367448b3c09Sdlg 
368448b3c09Sdlg 	/* Power State Descriptors */
369448b3c09Sdlg 
370448b3c09Sdlg 	struct nvm_identify_psd psd[32]; /* Power State Descriptors */
371448b3c09Sdlg 
372448b3c09Sdlg 	/* Vendor Specific */
373448b3c09Sdlg 
374448b3c09Sdlg 	u_int8_t	_reserved8[1024];
375448b3c09Sdlg } __packed __aligned(8);
3765dc507c5Sdlg 
3775dc507c5Sdlg struct nvm_namespace_format {
3785dc507c5Sdlg 	u_int16_t	ms;		/* Metadata Size */
3795dc507c5Sdlg 	u_int8_t	lbads;		/* LBA Data Size */
3805dc507c5Sdlg 	u_int8_t	rp;		/* Relative Performance */
3815dc507c5Sdlg } __packed __aligned(4);
3825dc507c5Sdlg 
3835dc507c5Sdlg struct nvm_identify_namespace {
3845dc507c5Sdlg 	u_int64_t	nsze;		/* Namespace Size */
3855dc507c5Sdlg 
3865dc507c5Sdlg 	u_int64_t	ncap;		/* Namespace Capacity */
3875dc507c5Sdlg 
3885dc507c5Sdlg 	u_int64_t	nuse;		/* Namespace Utilization */
3895dc507c5Sdlg 
3905dc507c5Sdlg 	u_int8_t	nsfeat;		/* Namespace Features */
391daef0c50Skrw #define	NVME_ID_NS_NSFEAT_THIN_PROV	(1 << 0)
3927f4636ceSkrw #define NVME_ID_NS_NSFEAT_FMT		"\020" \
3937f4636ceSkrw 	"\002NSABP" "\005OPTPERF" "\001THIN_PROV" "\004UIDREUSE" "\003DAE"
3947f4636ceSkrw 
3955dc507c5Sdlg 	u_int8_t	nlbaf;		/* Number of LBA Formats */
3965dc507c5Sdlg 	u_int8_t	flbas;		/* Formatted LBA Size */
3975dc507c5Sdlg #define NVME_ID_NS_FLBAS(_f)		((_f) & 0x0f)
3985dc507c5Sdlg #define NVME_ID_NS_FLBAS_MD		0x10
3995dc507c5Sdlg 	u_int8_t	mc;		/* Metadata Capabilities */
4007f4636ceSkrw 
4015dc507c5Sdlg 	u_int8_t	dpc;		/* End-to-end Data Protection
4025dc507c5Sdlg 					   Capabilities */
4035313ab17Sdlg 	u_int8_t	dps;		/* End-to-end Data Protection Type Settings */
4047f4636ceSkrw #define NVME_ID_NS_DPS_PIP		(1 << 3)
4057f4636ceSkrw #define NVME_ID_NS_DPS_TYPE(_f)		((_f) & 0x7)
4065dc507c5Sdlg 
4077f4636ceSkrw 	u_int8_t	_reserved1[74];
4087f4636ceSkrw 	uint8_t		nguid[16];
4097f4636ceSkrw 	uint8_t		eui64[8];	/* BIG-endian */
4105dc507c5Sdlg 
4115dc507c5Sdlg 	struct nvm_namespace_format
4125dc507c5Sdlg 			lbaf[16];	/* LBA Format Support */
4135dc507c5Sdlg 
4145dc507c5Sdlg 	u_int8_t	_reserved2[192];
4155dc507c5Sdlg 
4165dc507c5Sdlg 	u_int8_t	vs[3712];
4175dc507c5Sdlg } __packed __aligned(8);
418*3800fc35Sjmatthew 
419*3800fc35Sjmatthew #define NVM_LOG_PAGE_SMART_HEALTH	0x02
420*3800fc35Sjmatthew struct nvm_smart_health {
421*3800fc35Sjmatthew 	u_int8_t	critical_warning;
422*3800fc35Sjmatthew #define NVM_HEALTH_CW_SPARE		(1 << 0)
423*3800fc35Sjmatthew #define NVM_HEALTH_CW_TEMP		(1 << 1)
424*3800fc35Sjmatthew #define NVM_HEALTH_CW_MEDIA		(1 << 2)
425*3800fc35Sjmatthew #define NVM_HEALTH_CW_READONLY		(1 << 3)
426*3800fc35Sjmatthew #define NVM_HEALTH_CW_VOLATILE		(1 << 4)
427*3800fc35Sjmatthew #define NVM_HEALTH_CW_PMR		(1 << 5)
428*3800fc35Sjmatthew 	u_int16_t	temperature;
429*3800fc35Sjmatthew 	u_int8_t	avail_spare;
430*3800fc35Sjmatthew 	u_int8_t	avail_spare_threshold;
431*3800fc35Sjmatthew 	u_int8_t	percent_used;
432*3800fc35Sjmatthew 	u_int8_t	end_grp_summary;	/* 1.4+ */
433*3800fc35Sjmatthew 
434*3800fc35Sjmatthew 	u_int8_t	_reserved1[25];
435*3800fc35Sjmatthew 
436*3800fc35Sjmatthew 	u_int64_t	data_units_read[2];
437*3800fc35Sjmatthew 	u_int64_t	data_units_written[2];
438*3800fc35Sjmatthew 	u_int64_t	host_read_commands[2];
439*3800fc35Sjmatthew 	u_int64_t	host_write_commands[2];
440*3800fc35Sjmatthew 	u_int64_t	busy_time[2];
441*3800fc35Sjmatthew 	u_int64_t	power_cycles[2];
442*3800fc35Sjmatthew 	u_int64_t	power_on_hours[2];
443*3800fc35Sjmatthew 	u_int64_t	unsafe_shutdowns[2];
444*3800fc35Sjmatthew 	u_int64_t	integrity_errors[2];
445*3800fc35Sjmatthew 	u_int64_t	error_log_entries[2];
446*3800fc35Sjmatthew 	u_int32_t	warn_temp_time;		/* 1.2+ */
447*3800fc35Sjmatthew 	u_int32_t	crit_temp_time;		/* 1.2+ */
448*3800fc35Sjmatthew 	u_int16_t	temp_sensors[8];	/* 1.2+ */
449*3800fc35Sjmatthew 	u_int32_t	therm_mgmt_count_1;	/* 1.3+ */
450*3800fc35Sjmatthew 	u_int32_t	therm_mgmt_count_2;	/* 1.3+ */
451*3800fc35Sjmatthew 	u_int32_t	therm_mgmt_time_1;	/* 1.3+ */
452*3800fc35Sjmatthew 	u_int32_t	therm_mgmt_time_2;	/* 1.3+ */
453*3800fc35Sjmatthew 
454*3800fc35Sjmatthew 	u_int8_t	_reserved2[280];
455*3800fc35Sjmatthew } __packed __aligned(8);
456