xref: /illumos-gate/usr/src/uts/common/io/nvme/nvme_reg.h (revision 533affcb)
13c9168faSHans Rosenfeld /*
23c9168faSHans Rosenfeld  * This file and its contents are supplied under the terms of the
33c9168faSHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
43c9168faSHans Rosenfeld  * You may only use this file in accordance with the terms of version
53c9168faSHans Rosenfeld  * 1.0 of the CDDL.
63c9168faSHans Rosenfeld  *
73c9168faSHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
83c9168faSHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
93c9168faSHans Rosenfeld  * http://www.illumos.org/license/CDDL.
103c9168faSHans Rosenfeld  */
113c9168faSHans Rosenfeld 
123c9168faSHans Rosenfeld /*
132ba19bafSJason King  * Copyright 2020 Joyent, Inc.
14153f3212SHans Rosenfeld  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
1504be5853SAndy Fiddaman  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
16*533affcbSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
173c9168faSHans Rosenfeld  */
183c9168faSHans Rosenfeld 
193c9168faSHans Rosenfeld /*
203c9168faSHans Rosenfeld  * NVMe hardware interface
213c9168faSHans Rosenfeld  */
223c9168faSHans Rosenfeld 
233c9168faSHans Rosenfeld #ifndef _NVME_REG_H
243c9168faSHans Rosenfeld #define	_NVME_REG_H
253c9168faSHans Rosenfeld 
263d9b1a2aSHans Rosenfeld #include <sys/nvme.h>
273d9b1a2aSHans Rosenfeld 
283c9168faSHans Rosenfeld #pragma pack(1)
293c9168faSHans Rosenfeld 
303c9168faSHans Rosenfeld #ifdef __cplusplus
313c9168faSHans Rosenfeld extern "C" {
323c9168faSHans Rosenfeld #endif
333c9168faSHans Rosenfeld 
343c9168faSHans Rosenfeld 
353c9168faSHans Rosenfeld /*
363c9168faSHans Rosenfeld  * NVMe constants
373c9168faSHans Rosenfeld  */
383c9168faSHans Rosenfeld #define	NVME_MAX_ADMIN_QUEUE_LEN	4096
393c9168faSHans Rosenfeld 
403c9168faSHans Rosenfeld /*
413c9168faSHans Rosenfeld  * NVMe registers and register fields
423c9168faSHans Rosenfeld  */
433c9168faSHans Rosenfeld #define	NVME_REG_CAP	0x0		/* Controller Capabilities */
443c9168faSHans Rosenfeld #define	NVME_REG_VS	0x8		/* Version */
453c9168faSHans Rosenfeld #define	NVME_REG_INTMS	0xc		/* Interrupt Mask Set */
463c9168faSHans Rosenfeld #define	NVME_REG_INTMC	0x10		/* Interrupt Mask Clear */
473c9168faSHans Rosenfeld #define	NVME_REG_CC	0x14		/* Controller Configuration */
483c9168faSHans Rosenfeld #define	NVME_REG_CSTS	0x1c		/* Controller Status */
493c9168faSHans Rosenfeld #define	NVME_REG_NSSR	0x20		/* NVM Subsystem Reset */
503c9168faSHans Rosenfeld #define	NVME_REG_AQA	0x24		/* Admin Queue Attributes */
513c9168faSHans Rosenfeld #define	NVME_REG_ASQ	0x28		/* Admin Submission Queue */
523c9168faSHans Rosenfeld #define	NVME_REG_ACQ	0x30		/* Admin Completion Qeueu */
5348d370f1SRobert Mustacchi #define	NVME_REG_CMBLOC	0x38		/* Controller Memory Buffer Location */
5448d370f1SRobert Mustacchi #define	NVME_REG_CMBSZ	0x3C		/* Controller Memory Buffer Size */
5548d370f1SRobert Mustacchi #define	NVME_REG_BPINFO	0x40		/* Boot Partition Information */
5648d370f1SRobert Mustacchi #define	NVME_REG_BPRSEL	0x44		/* Boot Partition Read Select */
5748d370f1SRobert Mustacchi #define	NVME_REG_BPMBL	0x48		/* Boot Partition Memory Buffer Loc */
583c9168faSHans Rosenfeld #define	NVME_REG_SQTDBL(nvme, n) \
593c9168faSHans Rosenfeld 	(0x1000 + ((2 * (n)) * nvme->n_doorbell_stride))
603c9168faSHans Rosenfeld #define	NVME_REG_CQHDBL(nvme, n) \
613c9168faSHans Rosenfeld 	(0x1000 + ((2 * (n) + 1) * nvme->n_doorbell_stride))
623c9168faSHans Rosenfeld 
633c9168faSHans Rosenfeld #define	 NVME_CAP_CSS_NVM	1	/* NVM Command Set */
643c9168faSHans Rosenfeld #define	 NVME_CAP_AMS_WRR	1	/* Weighted Round-Robin */
653c9168faSHans Rosenfeld 
663c9168faSHans Rosenfeld /* CAP -- Controller Capabilities */
673c9168faSHans Rosenfeld typedef union {
683c9168faSHans Rosenfeld 	struct {
693c9168faSHans Rosenfeld 		uint16_t cap_mqes;	/* Maximum Queue Entries Supported */
703c9168faSHans Rosenfeld 		uint8_t cap_cqr:1;	/* Contiguous Queues Required */
713c9168faSHans Rosenfeld 		uint8_t cap_ams:2;	/* Arbitration Mechanisms Supported */
723c9168faSHans Rosenfeld 		uint8_t cap_rsvd1:5;
733c9168faSHans Rosenfeld 		uint8_t cap_to;		/* Timeout */
743c9168faSHans Rosenfeld 		uint16_t cap_dstrd:4;	/* Doorbell Stride */
753c9168faSHans Rosenfeld 		uint16_t cap_nssrs:1;	/* NVM Subsystem Reset Supported */
763c9168faSHans Rosenfeld 		uint16_t cap_css:8;	/* Command Sets Supported */
7748d370f1SRobert Mustacchi 		uint16_t cap_rsvd2:2;
7848d370f1SRobert Mustacchi 		uint8_t cap_bps:1;	/* Boot Partition Support */
793c9168faSHans Rosenfeld 		uint8_t cap_mpsmin:4;	/* Memory Page Size Minimum */
803c9168faSHans Rosenfeld 		uint8_t cap_mpsmax:4;	/* Memory Page Size Maximum */
813c9168faSHans Rosenfeld 		uint8_t cap_rsvd3;
823c9168faSHans Rosenfeld 	} b;
833c9168faSHans Rosenfeld 	uint64_t r;
843c9168faSHans Rosenfeld } nvme_reg_cap_t;
853c9168faSHans Rosenfeld 
863c9168faSHans Rosenfeld /* VS -- Version */
873c9168faSHans Rosenfeld typedef union {
883c9168faSHans Rosenfeld 	struct {
893c9168faSHans Rosenfeld 		uint8_t vs_rsvd;
903c9168faSHans Rosenfeld 		uint8_t vs_mnr;		/* Minor Version Number */
913c9168faSHans Rosenfeld 		uint16_t vs_mjr;	/* Major Version Number */
923c9168faSHans Rosenfeld 	} b;
933c9168faSHans Rosenfeld 	uint32_t r;
943c9168faSHans Rosenfeld } nvme_reg_vs_t;
953c9168faSHans Rosenfeld 
963c9168faSHans Rosenfeld /* CC -- Controller Configuration */
973c9168faSHans Rosenfeld #define	NVME_CC_SHN_NORMAL	1	/* Normal Shutdown Notification */
983c9168faSHans Rosenfeld #define	NVME_CC_SHN_ABRUPT	2	/* Abrupt Shutdown Notification */
993c9168faSHans Rosenfeld 
1003c9168faSHans Rosenfeld typedef union {
1013c9168faSHans Rosenfeld 	struct {
1023c9168faSHans Rosenfeld 		uint16_t cc_en:1;	/* Enable */
1033c9168faSHans Rosenfeld 		uint16_t cc_rsvd1:3;
1043c9168faSHans Rosenfeld 		uint16_t cc_css:3;	/* I/O Command Set Selected */
1053c9168faSHans Rosenfeld 		uint16_t cc_mps:4;	/* Memory Page Size */
1063c9168faSHans Rosenfeld 		uint16_t cc_ams:3;	/* Arbitration Mechanism Selected */
1073c9168faSHans Rosenfeld 		uint16_t cc_shn:2;	/* Shutdown Notification */
1083c9168faSHans Rosenfeld 		uint8_t cc_iosqes:4;	/* I/O Submission Queue Entry Size */
1093c9168faSHans Rosenfeld 		uint8_t cc_iocqes:4;	/* I/O Completion Queue Entry Size */
1103c9168faSHans Rosenfeld 		uint8_t cc_rsvd2;
1113c9168faSHans Rosenfeld 	} b;
1123c9168faSHans Rosenfeld 	uint32_t r;
1133c9168faSHans Rosenfeld } nvme_reg_cc_t;
1143c9168faSHans Rosenfeld 
1153c9168faSHans Rosenfeld /* CSTS -- Controller Status */
1163c9168faSHans Rosenfeld #define	NVME_CSTS_SHN_OCCURING	1	/* Shutdown Processing Occuring */
1173c9168faSHans Rosenfeld #define	NVME_CSTS_SHN_COMPLETE	2	/* Shutdown Processing Complete */
1183c9168faSHans Rosenfeld 
1193c9168faSHans Rosenfeld typedef union {
1203c9168faSHans Rosenfeld 	struct {
1213c9168faSHans Rosenfeld 		uint32_t csts_rdy:1;	/* Ready */
1223c9168faSHans Rosenfeld 		uint32_t csts_cfs:1;	/* Controller Fatal Status */
1233c9168faSHans Rosenfeld 		uint32_t csts_shst:2;	/* Shutdown Status */
1243c9168faSHans Rosenfeld 		uint32_t csts_nssro:1;	/* NVM Subsystem Reset Occured */
12548d370f1SRobert Mustacchi 		uint32_t csts_pp:1;	/* Processing Paused */
12648d370f1SRobert Mustacchi 		uint32_t csts_rsvd:26;
1273c9168faSHans Rosenfeld 	} b;
1283c9168faSHans Rosenfeld 	uint32_t r;
1293c9168faSHans Rosenfeld } nvme_reg_csts_t;
1303c9168faSHans Rosenfeld 
1313c9168faSHans Rosenfeld /* NSSR -- NVM Subsystem Reset */
1323c9168faSHans Rosenfeld #define	NVME_NSSR_NSSRC	0x4e564d65	/* NSSR magic value */
1333c9168faSHans Rosenfeld typedef uint32_t nvme_reg_nssr_t;
1343c9168faSHans Rosenfeld 
1353c9168faSHans Rosenfeld /* AQA -- Admin Queue Attributes */
1363c9168faSHans Rosenfeld typedef union {
1373c9168faSHans Rosenfeld 	struct {
1383c9168faSHans Rosenfeld 		uint16_t aqa_asqs:12;	/* Admin Submission Queue Size */
1393c9168faSHans Rosenfeld 		uint16_t aqa_rsvd1:4;
1403c9168faSHans Rosenfeld 		uint16_t aqa_acqs:12;	/* Admin Completion Queue Size */
1413c9168faSHans Rosenfeld 		uint16_t aqa_rsvd2:4;
1423c9168faSHans Rosenfeld 	} b;
1433c9168faSHans Rosenfeld 	uint32_t r;
1443c9168faSHans Rosenfeld } nvme_reg_aqa_t;
1453c9168faSHans Rosenfeld 
1463c9168faSHans Rosenfeld /*
1473c9168faSHans Rosenfeld  * The spec specifies the lower 12 bits of ASQ and ACQ as reserved, which is
1483c9168faSHans Rosenfeld  * probably a specification bug. The full 64bit regs are used as base address,
1493c9168faSHans Rosenfeld  * and the lower bits must be zero to ensure alignment on the page size
1503c9168faSHans Rosenfeld  * specified in CC.MPS.
1513c9168faSHans Rosenfeld  */
1523c9168faSHans Rosenfeld /* ASQ -- Admin Submission Queue Base Address */
1533c9168faSHans Rosenfeld typedef uint64_t nvme_reg_asq_t;	/* Admin Submission Queue Base */
1543c9168faSHans Rosenfeld 
1553c9168faSHans Rosenfeld /* ACQ -- Admin Completion Queue Base Address */
1563c9168faSHans Rosenfeld typedef uint64_t nvme_reg_acq_t;	/* Admin Completion Queue Base */
1573c9168faSHans Rosenfeld 
15848d370f1SRobert Mustacchi /* CMBLOC - Controller Memory Buffer Location */
15948d370f1SRobert Mustacchi typedef union {
16048d370f1SRobert Mustacchi 	struct {
16148d370f1SRobert Mustacchi 		uint32_t cmbloc_bir:3;		/* Base Indicator Register */
16248d370f1SRobert Mustacchi 		uint32_t cmbloc_rsvd:9;
16348d370f1SRobert Mustacchi 		uint32_t cmbloc_ofst:20;	/* Offset */
16448d370f1SRobert Mustacchi 	} b;
16548d370f1SRobert Mustacchi 	uint32_t r;
16648d370f1SRobert Mustacchi } nvme_reg_cmbloc_t;
16748d370f1SRobert Mustacchi 
16848d370f1SRobert Mustacchi /* CMBSZ - Controller Memory Buffer Size */
16948d370f1SRobert Mustacchi typedef union {
17048d370f1SRobert Mustacchi 	struct {
17148d370f1SRobert Mustacchi 		uint32_t cmbsz_sqs:1;	/* Submission Queue Support */
17248d370f1SRobert Mustacchi 		uint32_t cmbsz_cqs:1;	/* Completion Queue Support */
17348d370f1SRobert Mustacchi 		uint32_t cmbsz_lists:1;	/* PRP SGL List Support */
17448d370f1SRobert Mustacchi 		uint32_t cmbsz_rds:1;	/* Read Data Support */
17548d370f1SRobert Mustacchi 		uint32_t cmbsz_wds:1;	/* Write Data Support */
17648d370f1SRobert Mustacchi 		uint32_t cmbsz_rsvd:3;
17748d370f1SRobert Mustacchi 		uint32_t cmbsz_szu:4;	/* Size Units */
17848d370f1SRobert Mustacchi 		uint32_t cmbsz_sz:20;	/* Size */
17948d370f1SRobert Mustacchi 	} b;
18048d370f1SRobert Mustacchi 	uint32_t r;
18148d370f1SRobert Mustacchi } nvme_reg_cmbsz_t;
18248d370f1SRobert Mustacchi 
18348d370f1SRobert Mustacchi /* BPINFO - Boot Partition Information */
18448d370f1SRobert Mustacchi typedef union {
18548d370f1SRobert Mustacchi 	struct {
18648d370f1SRobert Mustacchi 		uint32_t bpinfo_bpsz:15;	/* Boot Partition Size */
18748d370f1SRobert Mustacchi 		uint32_t bpinfo_rsvd:9;
18848d370f1SRobert Mustacchi 		uint32_t bpinfo_brs:2;		/* Boot Read Status */
18948d370f1SRobert Mustacchi 		uint32_t bpinfo_rsvd2:5;
19048d370f1SRobert Mustacchi 		uint32_t bpinfo_abpid:1;	/* Active Boot Partition ID */
19148d370f1SRobert Mustacchi 	} b;
19248d370f1SRobert Mustacchi 	uint32_t r;
19348d370f1SRobert Mustacchi } nvme_reg_bpinfo_t;
19448d370f1SRobert Mustacchi 
19548d370f1SRobert Mustacchi /* BPRSEL - Boot Partition Read Select */
19648d370f1SRobert Mustacchi typedef union {
19748d370f1SRobert Mustacchi 	struct {
19848d370f1SRobert Mustacchi 		uint32_t bprsel_bprsz:10;	/* Boot Partition Read Size */
19948d370f1SRobert Mustacchi 		uint32_t bprsel_bprof:20;	/* Boot Partition Read Offset */
20048d370f1SRobert Mustacchi 		uint32_t bprsel_rsvd:1;
20148d370f1SRobert Mustacchi 		uint32_t bprsel_bpid:1;		/* Boot Partition Identifier */
20248d370f1SRobert Mustacchi 	} b;
20348d370f1SRobert Mustacchi 	uint32_t r;
20448d370f1SRobert Mustacchi } nvme_reg_bprsel_t;
20548d370f1SRobert Mustacchi 
20648d370f1SRobert Mustacchi /* BPMBL - Boot Partition Memory Location Buffer Location */
20748d370f1SRobert Mustacchi typedef uint64_t nvme_reg_bpbml_t;	/* Memory Buffer Base Address */
20848d370f1SRobert Mustacchi 
2093c9168faSHans Rosenfeld /* SQyTDBL -- Submission Queue y Tail Doorbell */
2103c9168faSHans Rosenfeld typedef union {
2113c9168faSHans Rosenfeld 	struct {
2123c9168faSHans Rosenfeld 		uint16_t sqtdbl_sqt;	/* Submission Queue Tail */
2133c9168faSHans Rosenfeld 		uint16_t sqtdbl_rsvd;
2143c9168faSHans Rosenfeld 	} b;
2153c9168faSHans Rosenfeld 	uint32_t r;
2163c9168faSHans Rosenfeld } nvme_reg_sqtdbl_t;
2173c9168faSHans Rosenfeld 
2183c9168faSHans Rosenfeld /* CQyHDBL -- Completion Queue y Head Doorbell */
2193c9168faSHans Rosenfeld typedef union {
2203c9168faSHans Rosenfeld 	struct {
2213c9168faSHans Rosenfeld 		uint16_t cqhdbl_cqh;	/* Completion Queue Head */
2223c9168faSHans Rosenfeld 		uint16_t cqhdbl_rsvd;
2233c9168faSHans Rosenfeld 	} b;
2243c9168faSHans Rosenfeld 	uint32_t r;
2253c9168faSHans Rosenfeld } nvme_reg_cqhdbl_t;
2263c9168faSHans Rosenfeld 
2273c9168faSHans Rosenfeld /*
2283c9168faSHans Rosenfeld  * NVMe submission queue entries
2293c9168faSHans Rosenfeld  */
2303c9168faSHans Rosenfeld 
2313c9168faSHans Rosenfeld /* NVMe scatter/gather list descriptor */
2323c9168faSHans Rosenfeld typedef struct {
2333c9168faSHans Rosenfeld 	uint64_t sgl_addr;		/* Address */
2343c9168faSHans Rosenfeld 	uint32_t sgl_len;		/* Length */
2353c9168faSHans Rosenfeld 	uint8_t sgl_rsvd[3];
2363c9168faSHans Rosenfeld 	uint8_t sgl_zero:4;
2373c9168faSHans Rosenfeld 	uint8_t sgl_type:4;		/* SGL descriptor type */
2383c9168faSHans Rosenfeld } nvme_sgl_t;
2393c9168faSHans Rosenfeld 
2403c9168faSHans Rosenfeld /* NVMe SGL descriptor type */
2413c9168faSHans Rosenfeld #define	NVME_SGL_DATA_BLOCK	0
2423c9168faSHans Rosenfeld #define	NVME_SGL_BIT_BUCKET	1
2433c9168faSHans Rosenfeld #define	NVME_SGL_SEGMENT	2
2443c9168faSHans Rosenfeld #define	NVME_SGL_LAST_SEGMENT	3
2453c9168faSHans Rosenfeld #define	NVME_SGL_VENDOR		0xf
2463c9168faSHans Rosenfeld 
2473c9168faSHans Rosenfeld /* NVMe submission queue entry */
2483c9168faSHans Rosenfeld typedef struct {
2493c9168faSHans Rosenfeld 	uint8_t sqe_opc;		/* Opcode */
2503c9168faSHans Rosenfeld 	uint8_t sqe_fuse:2;		/* Fused Operation */
2513c9168faSHans Rosenfeld 	uint8_t sqe_rsvd:5;
2523c9168faSHans Rosenfeld 	uint8_t sqe_psdt:1;		/* PRP or SGL for Data Transfer */
2533c9168faSHans Rosenfeld 	uint16_t sqe_cid;		/* Command Identifier */
2543c9168faSHans Rosenfeld 	uint32_t sqe_nsid;		/* Namespace Identifier */
2553c9168faSHans Rosenfeld 	uint64_t sqe_rsvd1;
2563c9168faSHans Rosenfeld 	union {
2573c9168faSHans Rosenfeld 		uint64_t m_ptr;		/* Metadata Pointer */
2583c9168faSHans Rosenfeld 		uint64_t m_sglp;	/* Metadata SGL Segment Pointer */
2593c9168faSHans Rosenfeld 	} sqe_m;
2603c9168faSHans Rosenfeld 	union {
2613c9168faSHans Rosenfeld 		uint64_t d_prp[2];	/* Physical Page Region Entries 1 & 2 */
2623c9168faSHans Rosenfeld 		nvme_sgl_t d_sgl;	/* SGL Entry 1 */
2633c9168faSHans Rosenfeld 	} sqe_dptr;			/* Data Pointer */
2643c9168faSHans Rosenfeld 	uint32_t sqe_cdw10;		/* Number of Dwords in Data Transfer */
2653c9168faSHans Rosenfeld 	uint32_t sqe_cdw11;		/* Number of Dwords in Metadata Xfer */
2663c9168faSHans Rosenfeld 	uint32_t sqe_cdw12;
2673c9168faSHans Rosenfeld 	uint32_t sqe_cdw13;
2683c9168faSHans Rosenfeld 	uint32_t sqe_cdw14;
2693c9168faSHans Rosenfeld 	uint32_t sqe_cdw15;
2703c9168faSHans Rosenfeld } nvme_sqe_t;
2713c9168faSHans Rosenfeld 
2723c9168faSHans Rosenfeld /* NVMe admin command opcodes */
2733c9168faSHans Rosenfeld #define	NVME_OPC_DELETE_SQUEUE	0x0
2743c9168faSHans Rosenfeld #define	NVME_OPC_CREATE_SQUEUE	0x1
2753c9168faSHans Rosenfeld #define	NVME_OPC_GET_LOG_PAGE	0x2
2763c9168faSHans Rosenfeld #define	NVME_OPC_DELETE_CQUEUE	0x4
2773c9168faSHans Rosenfeld #define	NVME_OPC_CREATE_CQUEUE	0x5
2783c9168faSHans Rosenfeld #define	NVME_OPC_IDENTIFY	0x6
2793c9168faSHans Rosenfeld #define	NVME_OPC_ABORT		0x8
2803c9168faSHans Rosenfeld #define	NVME_OPC_SET_FEATURES	0x9
2813c9168faSHans Rosenfeld #define	NVME_OPC_GET_FEATURES	0xa
2823c9168faSHans Rosenfeld #define	NVME_OPC_ASYNC_EVENT	0xc
28348d370f1SRobert Mustacchi #define	NVME_OPC_NS_MGMT	0xd	/* 1.2 */
2843c9168faSHans Rosenfeld #define	NVME_OPC_FW_ACTIVATE	0x10
2853c9168faSHans Rosenfeld #define	NVME_OPC_FW_IMAGE_LOAD	0x11
28648d370f1SRobert Mustacchi #define	NVME_OPC_SELF_TEST	0x14	/* 1.3 */
28748d370f1SRobert Mustacchi #define	NVME_OPC_NS_ATTACH	0x15	/* 1.2 */
28848d370f1SRobert Mustacchi #define	NVME_OPC_KEEP_ALIVE	0x18	/* 1.3 */
28948d370f1SRobert Mustacchi #define	NVME_OPC_DIRECTIVE_SEND	0x19	/* 1.3 */
29048d370f1SRobert Mustacchi #define	NVME_OPC_DIRECTIVE_RECV	0x1A	/* 1.3 */
29148d370f1SRobert Mustacchi #define	NVME_OPC_VIRT_MGMT	0x1C	/* 1.3 */
29248d370f1SRobert Mustacchi #define	NVME_OPC_NVMEMI_SEND	0x1D	/* 1.3 */
29348d370f1SRobert Mustacchi #define	NVME_OPC_NVMEMI_RECV	0x1E	/* 1.3 */
29448d370f1SRobert Mustacchi #define	NVME_OPC_DB_CONFIG	0x7C	/* 1.3 */
2953c9168faSHans Rosenfeld 
2963c9168faSHans Rosenfeld /* NVMe NVM command set specific admin command opcodes */
2973c9168faSHans Rosenfeld #define	NVME_OPC_NVM_FORMAT	0x80
2983c9168faSHans Rosenfeld #define	NVME_OPC_NVM_SEC_SEND	0x81
2993c9168faSHans Rosenfeld #define	NVME_OPC_NVM_SEC_RECV	0x82
3003c9168faSHans Rosenfeld 
3013c9168faSHans Rosenfeld /* NVMe NVM command opcodes */
3023c9168faSHans Rosenfeld #define	NVME_OPC_NVM_FLUSH	0x0
3033c9168faSHans Rosenfeld #define	NVME_OPC_NVM_WRITE	0x1
3043c9168faSHans Rosenfeld #define	NVME_OPC_NVM_READ	0x2
3053c9168faSHans Rosenfeld #define	NVME_OPC_NVM_WRITE_UNC	0x4
3063c9168faSHans Rosenfeld #define	NVME_OPC_NVM_COMPARE	0x5
3073c9168faSHans Rosenfeld #define	NVME_OPC_NVM_WRITE_ZERO	0x8
3083c9168faSHans Rosenfeld #define	NVME_OPC_NVM_DSET_MGMT	0x9
3093c9168faSHans Rosenfeld #define	NVME_OPC_NVM_RESV_REG	0xd
3103c9168faSHans Rosenfeld #define	NVME_OPC_NVM_RESV_REPRT	0xe
3113c9168faSHans Rosenfeld #define	NVME_OPC_NVM_RESV_ACQ	0x11
3123c9168faSHans Rosenfeld #define	NVME_OPC_NVM_RESV_REL	0x12
3133c9168faSHans Rosenfeld 
3143c9168faSHans Rosenfeld /*
3153c9168faSHans Rosenfeld  * NVMe completion queue entry
3163c9168faSHans Rosenfeld  */
3173c9168faSHans Rosenfeld typedef struct {
3183c9168faSHans Rosenfeld 	uint32_t cqe_dw0;		/* Command Specific */
3193c9168faSHans Rosenfeld 	uint32_t cqe_rsvd1;
3203c9168faSHans Rosenfeld 	uint16_t cqe_sqhd;		/* SQ Head Pointer */
3213c9168faSHans Rosenfeld 	uint16_t cqe_sqid;		/* SQ Identifier */
3223c9168faSHans Rosenfeld 	uint16_t cqe_cid;		/* Command Identifier */
3233c9168faSHans Rosenfeld 	nvme_cqe_sf_t cqe_sf;		/* Status Field */
3243c9168faSHans Rosenfeld } nvme_cqe_t;
3253c9168faSHans Rosenfeld 
3263c9168faSHans Rosenfeld /*
3273c9168faSHans Rosenfeld  * NVMe Asynchronous Event Request
3283c9168faSHans Rosenfeld  */
3293c9168faSHans Rosenfeld #define	NVME_ASYNC_TYPE_ERROR		0x0	/* Error Status */
3303c9168faSHans Rosenfeld #define	NVME_ASYNC_TYPE_HEALTH		0x1	/* SMART/Health Status */
33104be5853SAndy Fiddaman #define	NVME_ASYNC_TYPE_NOTICE		0x2	/* Notice (1.2) */
33204be5853SAndy Fiddaman #define	NVME_ASYNC_TYPE_VENDOR		0x7	/* Vendor specific */
3333c9168faSHans Rosenfeld 
3343c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_INV_SQ		0x0	/* Invalid Submission Queue */
3353c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_INV_DBL	0x1	/* Invalid Doorbell Write */
3363c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_DIAGFAIL	0x2	/* Diagnostic Failure */
3373c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_PERSISTENT	0x3	/* Persistent Internal Error */
3383c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_TRANSIENT	0x4	/* Transient Internal Error */
3393c9168faSHans Rosenfeld #define	NVME_ASYNC_ERROR_FW_LOAD	0x5	/* Firmware Image Load Error */
3403c9168faSHans Rosenfeld 
3413c9168faSHans Rosenfeld #define	NVME_ASYNC_HEALTH_RELIABILITY	0x0	/* Device Reliability */
3423c9168faSHans Rosenfeld #define	NVME_ASYNC_HEALTH_TEMPERATURE	0x1	/* Temp. Above Threshold */
3433c9168faSHans Rosenfeld #define	NVME_ASYNC_HEALTH_SPARE		0x2	/* Spare Below Threshold */
3443c9168faSHans Rosenfeld 
34504be5853SAndy Fiddaman /* NVMe 1.2 */
34604be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_NS_CHANGE	0x0	/* Namespace attribute change */
34704be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_FW_ACTIVATE	0x1	/* Firmware activation start */
34804be5853SAndy Fiddaman /* NVMe 1.3 */
34904be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_TELEMETRY	0x2	/* Telemetry log changed */
35004be5853SAndy Fiddaman /* NVMe 1.4 */
35104be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_NS_ASYMM	0x3	/* Asymm. NS access change */
35204be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_LATENCYLOG	0x4	/* Pred. Latency log change */
35304be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_LBASTATUS	0x5	/* LBA status alert */
35404be5853SAndy Fiddaman #define	NVME_ASYNC_NOTICE_ENDURANCELOG	0x6	/* Endurance log change */
35504be5853SAndy Fiddaman 
3563c9168faSHans Rosenfeld typedef union {
3573c9168faSHans Rosenfeld 	struct {
3583c9168faSHans Rosenfeld 		uint8_t ae_type:3;		/* Asynchronous Event Type */
3593c9168faSHans Rosenfeld 		uint8_t ae_rsvd1:5;
3603c9168faSHans Rosenfeld 		uint8_t ae_info;		/* Asynchronous Event Info */
3613c9168faSHans Rosenfeld 		uint8_t ae_logpage;		/* Associated Log Page */
3623c9168faSHans Rosenfeld 		uint8_t ae_rsvd2;
3633c9168faSHans Rosenfeld 	} b;
3643c9168faSHans Rosenfeld 	uint32_t r;
3653c9168faSHans Rosenfeld } nvme_async_event_t;
3663c9168faSHans Rosenfeld 
3673c9168faSHans Rosenfeld /*
3683c9168faSHans Rosenfeld  * NVMe Create Completion/Submission Queue
3693c9168faSHans Rosenfeld  */
3703c9168faSHans Rosenfeld typedef union {
3713c9168faSHans Rosenfeld 	struct {
3723c9168faSHans Rosenfeld 		uint16_t q_qid;			/* Queue Identifier */
37348d370f1SRobert Mustacchi 		uint16_t q_qsize;		/* Queue Size */
3743c9168faSHans Rosenfeld 	} b;
3753c9168faSHans Rosenfeld 	uint32_t r;
3763c9168faSHans Rosenfeld } nvme_create_queue_dw10_t;
3773c9168faSHans Rosenfeld 
3783c9168faSHans Rosenfeld typedef union {
3793c9168faSHans Rosenfeld 	struct {
3803c9168faSHans Rosenfeld 		uint16_t cq_pc:1;		/* Physically Contiguous */
3813c9168faSHans Rosenfeld 		uint16_t cq_ien:1;		/* Interrupts Enabled */
3823c9168faSHans Rosenfeld 		uint16_t cq_rsvd:14;
3833c9168faSHans Rosenfeld 		uint16_t cq_iv;			/* Interrupt Vector */
3843c9168faSHans Rosenfeld 	} b;
3853c9168faSHans Rosenfeld 	uint32_t r;
3863c9168faSHans Rosenfeld } nvme_create_cq_dw11_t;
3873c9168faSHans Rosenfeld 
3883c9168faSHans Rosenfeld typedef union {
3893c9168faSHans Rosenfeld 	struct {
3903c9168faSHans Rosenfeld 		uint16_t sq_pc:1;		/* Physically Contiguous */
3913c9168faSHans Rosenfeld 		uint16_t sq_qprio:2;		/* Queue Priority */
3923c9168faSHans Rosenfeld 		uint16_t sq_rsvd:13;
3933c9168faSHans Rosenfeld 		uint16_t sq_cqid;		/* Completion Queue ID */
3943c9168faSHans Rosenfeld 	} b;
3953c9168faSHans Rosenfeld 	uint32_t r;
3963c9168faSHans Rosenfeld } nvme_create_sq_dw11_t;
3973c9168faSHans Rosenfeld 
3983c9168faSHans Rosenfeld /*
3993c9168faSHans Rosenfeld  * NVMe Abort Command
4003c9168faSHans Rosenfeld  */
4013c9168faSHans Rosenfeld typedef union {
4023c9168faSHans Rosenfeld 	struct {
4033c9168faSHans Rosenfeld 		uint16_t ac_sqid;	/* Submission Queue ID */
4043c9168faSHans Rosenfeld 		uint16_t ac_cid;	/* Command ID */
4053c9168faSHans Rosenfeld 	} b;
4063c9168faSHans Rosenfeld 	uint32_t r;
4073c9168faSHans Rosenfeld } nvme_abort_cmd_t;
4083c9168faSHans Rosenfeld 
4093c9168faSHans Rosenfeld /*
410*533affcbSRobert Mustacchi  * NVMe Get Log Page. dw12/13 are the lower and upper halves of the 64-bit
411*533affcbSRobert Mustacchi  * offset field respectively in bytes. These must be dword aligned. The offset
412*533affcbSRobert Mustacchi  * was added in NVMe v1.2, but requires controller support.
4133c9168faSHans Rosenfeld  */
4143c9168faSHans Rosenfeld typedef union {
4153c9168faSHans Rosenfeld 	struct {
4163c9168faSHans Rosenfeld 		uint8_t lp_lid;		/* Log Page Identifier */
417*533affcbSRobert Mustacchi 		/*
418*533affcbSRobert Mustacchi 		 * The log-specific field was introduced as a 4-bit field in
419*533affcbSRobert Mustacchi 		 * NVMe 1.3. It was extended to be a 7-bit field in NVMe 2.0 and
420*533affcbSRobert Mustacchi 		 * renamed log-specific parameter.
421*533affcbSRobert Mustacchi 		 */
422*533affcbSRobert Mustacchi 		uint8_t lp_lsp:7;
423*533affcbSRobert Mustacchi 		uint8_t lp_rae:1;	/* Retain Async Event  v1.3 */
424*533affcbSRobert Mustacchi 		/*
425*533affcbSRobert Mustacchi 		 * This is the lower number of dwords. This was changed in NVMe
426*533affcbSRobert Mustacchi 		 * v1.2 to be split between this field and dw11. In NVMe 1.0/1.1
427*533affcbSRobert Mustacchi 		 * this was only 12 bits long.
428*533affcbSRobert Mustacchi 		 */
429*533affcbSRobert Mustacchi 		uint16_t lp_lnumdl;	/* Number of Dwords */
4303c9168faSHans Rosenfeld 	} b;
4313c9168faSHans Rosenfeld 	uint32_t r;
432*533affcbSRobert Mustacchi } nvme_getlogpage_dw10_t;
433*533affcbSRobert Mustacchi 
434*533affcbSRobert Mustacchi typedef union {
435*533affcbSRobert Mustacchi 	struct {
436*533affcbSRobert Mustacchi 		uint16_t lp_numdu;	/* Number of dwords v1.2 */
437*533affcbSRobert Mustacchi 		uint16_t lp_lsi;	/* Log Specific Field v1.3 */
438*533affcbSRobert Mustacchi 	} b;
439*533affcbSRobert Mustacchi 	uint32_t r;
440*533affcbSRobert Mustacchi } nvme_getlogpage_dw11_t;
441*533affcbSRobert Mustacchi 
442*533affcbSRobert Mustacchi typedef union {
443*533affcbSRobert Mustacchi 	struct {
444*533affcbSRobert Mustacchi 		uint8_t lp_uuid:7;	/* UUID Index v1.4 */
445*533affcbSRobert Mustacchi 		uint8_t lp_rsvd1:1;
446*533affcbSRobert Mustacchi 		uint8_t lp_rsvd2;
447*533affcbSRobert Mustacchi 		uint8_t lp_rsvd3:7;
448*533affcbSRobert Mustacchi 		uint8_t lp_ot:1;	/* Offset Type v2.0 */
449*533affcbSRobert Mustacchi 		uint8_t lp_csi;		/* Command Set Identifier v2.0 */
450*533affcbSRobert Mustacchi 	} b;
451*533affcbSRobert Mustacchi 	uint32_t r;
452*533affcbSRobert Mustacchi } nvme_getlogpage_dw14_t;
4533c9168faSHans Rosenfeld 
4542ba19bafSJason King /*
4552ba19bafSJason King  * dword11 values for the dataset management command. Note that the dword11
4562ba19bafSJason King  * attributes are distinct from the context attributes (nr_ctxattr) values
4572ba19bafSJason King  * for an individual range (of the context attribute values defined by the NVMe
4582ba19bafSJason King  * spec, none are currently used by the NVMe driver).
4592ba19bafSJason King  */
4602ba19bafSJason King #define	NVME_DSET_MGMT_ATTR_OPT_READ	0x01
4612ba19bafSJason King #define	NVME_DSET_MGMT_ATTR_OPT_WRITE	0x02
4622ba19bafSJason King #define	NVME_DSET_MGMT_ATTR_DEALLOCATE	0x04
4632ba19bafSJason King 
4642ba19bafSJason King #define	NVME_DSET_MGMT_MAX_RANGES	256
4652ba19bafSJason King typedef struct {
4662ba19bafSJason King 	uint32_t	nr_ctxattr;
4672ba19bafSJason King 	uint32_t	nr_len;
4682ba19bafSJason King 	uint64_t	nr_lba;
4692ba19bafSJason King } nvme_range_t;
4703c9168faSHans Rosenfeld 
471*533affcbSRobert Mustacchi /*
472*533affcbSRobert Mustacchi  * NVMe Identify Command
473*533affcbSRobert Mustacchi  */
474*533affcbSRobert Mustacchi typedef union {
475*533affcbSRobert Mustacchi 	struct {
476*533affcbSRobert Mustacchi 		/*
477*533affcbSRobert Mustacchi 		 * The controller or namespace structure (CNS). This field was
478*533affcbSRobert Mustacchi 		 * originally a single bit wide in NVMe 1.0. It was two bits
479*533affcbSRobert Mustacchi 		 * wide in NVMe 1.1 and was increased to 8 bits in NVMe 1.2.
480*533affcbSRobert Mustacchi 		 */
481*533affcbSRobert Mustacchi 		uint8_t id_cns;
482*533affcbSRobert Mustacchi 		uint8_t id_rsvd0;
483*533affcbSRobert Mustacchi 		uint16_t id_cntid;	/* Controller ID, NVMe 1.2 */
484*533affcbSRobert Mustacchi 	} b;
485*533affcbSRobert Mustacchi 	uint32_t r;
486*533affcbSRobert Mustacchi } nvme_identify_dw10_t;
487*533affcbSRobert Mustacchi 
4883c9168faSHans Rosenfeld #ifdef __cplusplus
4893c9168faSHans Rosenfeld }
4903c9168faSHans Rosenfeld #endif
4913c9168faSHans Rosenfeld 
4923c9168faSHans Rosenfeld #pragma pack() /* pack(1) */
4933c9168faSHans Rosenfeld 
4943c9168faSHans Rosenfeld #endif /* _NVME_REG_H */
495