xref: /illumos-gate/usr/src/uts/common/io/nvme/nvme_reg.h (revision d7c57852794a9ac50d4b6a9c4161cb10919658aa)
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. All rights reserved.
14  */
15 
16 /*
17  * NVMe hardware interface
18  */
19 
20 #ifndef _NVME_REG_H
21 #define	_NVME_REG_H
22 
23 #include <sys/nvme.h>
24 
25 #pragma pack(1)
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 
32 /*
33  * NVMe constants
34  */
35 #define	NVME_MAX_ADMIN_QUEUE_LEN	4096
36 
37 /*
38  * NVMe registers and register fields
39  */
40 #define	NVME_REG_CAP	0x0		/* Controller Capabilities */
41 #define	NVME_REG_VS	0x8		/* Version */
42 #define	NVME_REG_INTMS	0xc		/* Interrupt Mask Set */
43 #define	NVME_REG_INTMC	0x10		/* Interrupt Mask Clear */
44 #define	NVME_REG_CC	0x14		/* Controller Configuration */
45 #define	NVME_REG_CSTS	0x1c		/* Controller Status */
46 #define	NVME_REG_NSSR	0x20		/* NVM Subsystem Reset */
47 #define	NVME_REG_AQA	0x24		/* Admin Queue Attributes */
48 #define	NVME_REG_ASQ	0x28		/* Admin Submission Queue */
49 #define	NVME_REG_ACQ	0x30		/* Admin Completion Qeueu */
50 #define	NVME_REG_SQTDBL(nvme, n) \
51 	(0x1000 + ((2 * (n)) * nvme->n_doorbell_stride))
52 #define	NVME_REG_CQHDBL(nvme, n) \
53 	(0x1000 + ((2 * (n) + 1) * nvme->n_doorbell_stride))
54 
55 #define	 NVME_CAP_CSS_NVM	1	/* NVM Command Set */
56 #define	 NVME_CAP_AMS_WRR	1	/* Weighted Round-Robin */
57 
58 /* CAP -- Controller Capabilities */
59 typedef union {
60 	struct {
61 		uint16_t cap_mqes;	/* Maximum Queue Entries Supported */
62 		uint8_t cap_cqr:1;	/* Contiguous Queues Required */
63 		uint8_t cap_ams:2;	/* Arbitration Mechanisms Supported */
64 		uint8_t cap_rsvd1:5;
65 		uint8_t cap_to;		/* Timeout */
66 		uint16_t cap_dstrd:4;	/* Doorbell Stride */
67 		uint16_t cap_nssrs:1;	/* NVM Subsystem Reset Supported */
68 		uint16_t cap_css:8;	/* Command Sets Supported */
69 		uint16_t cap_rsvd2:3;
70 		uint8_t cap_mpsmin:4;	/* Memory Page Size Minimum */
71 		uint8_t cap_mpsmax:4;	/* Memory Page Size Maximum */
72 		uint8_t cap_rsvd3;
73 	} b;
74 	uint64_t r;
75 } nvme_reg_cap_t;
76 
77 /* VS -- Version */
78 typedef union {
79 	struct {
80 		uint8_t vs_rsvd;
81 		uint8_t vs_mnr;		/* Minor Version Number */
82 		uint16_t vs_mjr;	/* Major Version Number */
83 	} b;
84 	uint32_t r;
85 } nvme_reg_vs_t;
86 
87 /* CC -- Controller Configuration */
88 #define	NVME_CC_SHN_NORMAL	1	/* Normal Shutdown Notification */
89 #define	NVME_CC_SHN_ABRUPT	2	/* Abrupt Shutdown Notification */
90 
91 typedef union {
92 	struct {
93 		uint16_t cc_en:1;	/* Enable */
94 		uint16_t cc_rsvd1:3;
95 		uint16_t cc_css:3;	/* I/O Command Set Selected */
96 		uint16_t cc_mps:4;	/* Memory Page Size */
97 		uint16_t cc_ams:3;	/* Arbitration Mechanism Selected */
98 		uint16_t cc_shn:2;	/* Shutdown Notification */
99 		uint8_t cc_iosqes:4;	/* I/O Submission Queue Entry Size */
100 		uint8_t cc_iocqes:4;	/* I/O Completion Queue Entry Size */
101 		uint8_t cc_rsvd2;
102 	} b;
103 	uint32_t r;
104 } nvme_reg_cc_t;
105 
106 /* CSTS -- Controller Status */
107 #define	NVME_CSTS_SHN_OCCURING	1	/* Shutdown Processing Occuring */
108 #define	NVME_CSTS_SHN_COMPLETE	2	/* Shutdown Processing Complete */
109 
110 typedef union {
111 	struct {
112 		uint32_t csts_rdy:1;	/* Ready */
113 		uint32_t csts_cfs:1;	/* Controller Fatal Status */
114 		uint32_t csts_shst:2;	/* Shutdown Status */
115 		uint32_t csts_nssro:1;	/* NVM Subsystem Reset Occured */
116 		uint32_t csts_rsvd:27;
117 	} b;
118 	uint32_t r;
119 } nvme_reg_csts_t;
120 
121 /* NSSR -- NVM Subsystem Reset */
122 #define	NVME_NSSR_NSSRC	0x4e564d65	/* NSSR magic value */
123 typedef uint32_t nvme_reg_nssr_t;
124 
125 /* AQA -- Admin Queue Attributes */
126 typedef union {
127 	struct {
128 		uint16_t aqa_asqs:12;	/* Admin Submission Queue Size */
129 		uint16_t aqa_rsvd1:4;
130 		uint16_t aqa_acqs:12;	/* Admin Completion Queue Size */
131 		uint16_t aqa_rsvd2:4;
132 	} b;
133 	uint32_t r;
134 } nvme_reg_aqa_t;
135 
136 /*
137  * The spec specifies the lower 12 bits of ASQ and ACQ as reserved, which is
138  * probably a specification bug. The full 64bit regs are used as base address,
139  * and the lower bits must be zero to ensure alignment on the page size
140  * specified in CC.MPS.
141  */
142 /* ASQ -- Admin Submission Queue Base Address */
143 typedef uint64_t nvme_reg_asq_t;	/* Admin Submission Queue Base */
144 
145 /* ACQ -- Admin Completion Queue Base Address */
146 typedef uint64_t nvme_reg_acq_t;	/* Admin Completion Queue Base */
147 
148 /* SQyTDBL -- Submission Queue y Tail Doorbell */
149 typedef union {
150 	struct {
151 		uint16_t sqtdbl_sqt;	/* Submission Queue Tail */
152 		uint16_t sqtdbl_rsvd;
153 	} b;
154 	uint32_t r;
155 } nvme_reg_sqtdbl_t;
156 
157 /* CQyHDBL -- Completion Queue y Head Doorbell */
158 typedef union {
159 	struct {
160 		uint16_t cqhdbl_cqh;	/* Completion Queue Head */
161 		uint16_t cqhdbl_rsvd;
162 	} b;
163 	uint32_t r;
164 } nvme_reg_cqhdbl_t;
165 
166 /*
167  * NVMe submission queue entries
168  */
169 
170 /* NVMe scatter/gather list descriptor */
171 typedef struct {
172 	uint64_t sgl_addr;		/* Address */
173 	uint32_t sgl_len;		/* Length */
174 	uint8_t sgl_rsvd[3];
175 	uint8_t sgl_zero:4;
176 	uint8_t sgl_type:4;		/* SGL descriptor type */
177 } nvme_sgl_t;
178 
179 /* NVMe SGL descriptor type */
180 #define	NVME_SGL_DATA_BLOCK	0
181 #define	NVME_SGL_BIT_BUCKET	1
182 #define	NVME_SGL_SEGMENT	2
183 #define	NVME_SGL_LAST_SEGMENT	3
184 #define	NVME_SGL_VENDOR		0xf
185 
186 /* NVMe submission queue entry */
187 typedef struct {
188 	uint8_t sqe_opc;		/* Opcode */
189 	uint8_t sqe_fuse:2;		/* Fused Operation */
190 	uint8_t sqe_rsvd:5;
191 	uint8_t sqe_psdt:1;		/* PRP or SGL for Data Transfer */
192 	uint16_t sqe_cid;		/* Command Identifier */
193 	uint32_t sqe_nsid;		/* Namespace Identifier */
194 	uint64_t sqe_rsvd1;
195 	union {
196 		uint64_t m_ptr;		/* Metadata Pointer */
197 		uint64_t m_sglp;	/* Metadata SGL Segment Pointer */
198 	} sqe_m;
199 	union {
200 		uint64_t d_prp[2];	/* Physical Page Region Entries 1 & 2 */
201 		nvme_sgl_t d_sgl;	/* SGL Entry 1 */
202 	} sqe_dptr;			/* Data Pointer */
203 	uint32_t sqe_cdw10;		/* Number of Dwords in Data Transfer */
204 	uint32_t sqe_cdw11;		/* Number of Dwords in Metadata Xfer */
205 	uint32_t sqe_cdw12;
206 	uint32_t sqe_cdw13;
207 	uint32_t sqe_cdw14;
208 	uint32_t sqe_cdw15;
209 } nvme_sqe_t;
210 
211 /* NVMe admin command opcodes */
212 #define	NVME_OPC_DELETE_SQUEUE	0x0
213 #define	NVME_OPC_CREATE_SQUEUE	0x1
214 #define	NVME_OPC_GET_LOG_PAGE	0x2
215 #define	NVME_OPC_DELETE_CQUEUE	0x4
216 #define	NVME_OPC_CREATE_CQUEUE	0x5
217 #define	NVME_OPC_IDENTIFY	0x6
218 #define	NVME_OPC_ABORT		0x8
219 #define	NVME_OPC_SET_FEATURES	0x9
220 #define	NVME_OPC_GET_FEATURES	0xa
221 #define	NVME_OPC_ASYNC_EVENT	0xc
222 #define	NVME_OPC_FW_ACTIVATE	0x10
223 #define	NVME_OPC_FW_IMAGE_LOAD	0x11
224 
225 /* NVMe NVM command set specific admin command opcodes */
226 #define	NVME_OPC_NVM_FORMAT	0x80
227 #define	NVME_OPC_NVM_SEC_SEND	0x81
228 #define	NVME_OPC_NVM_SEC_RECV	0x82
229 
230 /* NVMe NVM command opcodes */
231 #define	NVME_OPC_NVM_FLUSH	0x0
232 #define	NVME_OPC_NVM_WRITE	0x1
233 #define	NVME_OPC_NVM_READ	0x2
234 #define	NVME_OPC_NVM_WRITE_UNC	0x4
235 #define	NVME_OPC_NVM_COMPARE	0x5
236 #define	NVME_OPC_NVM_WRITE_ZERO	0x8
237 #define	NVME_OPC_NVM_DSET_MGMT	0x9
238 #define	NVME_OPC_NVM_RESV_REG	0xd
239 #define	NVME_OPC_NVM_RESV_REPRT	0xe
240 #define	NVME_OPC_NVM_RESV_ACQ	0x11
241 #define	NVME_OPC_NVM_RESV_REL	0x12
242 
243 /*
244  * NVMe completion queue entry
245  */
246 typedef struct {
247 	uint32_t cqe_dw0;		/* Command Specific */
248 	uint32_t cqe_rsvd1;
249 	uint16_t cqe_sqhd;		/* SQ Head Pointer */
250 	uint16_t cqe_sqid;		/* SQ Identifier */
251 	uint16_t cqe_cid;		/* Command Identifier */
252 	nvme_cqe_sf_t cqe_sf;		/* Status Field */
253 } nvme_cqe_t;
254 
255 /* NVMe completion status code type */
256 #define	NVME_CQE_SCT_GENERIC	0	/* Generic Command Status */
257 #define	NVME_CQE_SCT_SPECIFIC	1	/* Command Specific Status */
258 #define	NVME_CQE_SCT_INTEGRITY	2	/* Media and Data Integrity Errors */
259 #define	NVME_CQE_SCT_VENDOR	7	/* Vendor Specific */
260 
261 /* NVMe completion status code (generic) */
262 #define	NVME_CQE_SC_GEN_SUCCESS		0x0	/* Successful Completion */
263 #define	NVME_CQE_SC_GEN_INV_OPC		0x1	/* Invalid Command Opcode */
264 #define	NVME_CQE_SC_GEN_INV_FLD		0x2	/* Invalid Field in Command */
265 #define	NVME_CQE_SC_GEN_ID_CNFL		0x3	/* Command ID Conflict */
266 #define	NVME_CQE_SC_GEN_DATA_XFR_ERR	0x4	/* Data Transfer Error */
267 #define	NVME_CQE_SC_GEN_ABORT_PWRLOSS	0x5	/* Cmds Aborted / Pwr Loss */
268 #define	NVME_CQE_SC_GEN_INTERNAL_ERR	0x6	/* Internal Error */
269 #define	NVME_CQE_SC_GEN_ABORT_REQUEST	0x7	/* Command Abort Requested */
270 #define	NVME_CQE_SC_GEN_ABORT_SQ_DEL	0x8	/* Cmd Aborted / SQ deletion */
271 #define	NVME_CQE_SC_GEN_ABORT_FUSE_FAIL	0x9	/* Cmd Aborted / Failed Fused */
272 #define	NVME_CQE_SC_GEN_ABORT_FUSE_MISS	0xa	/* Cmd Aborted / Missing Fusd */
273 #define	NVME_CQE_SC_GEN_INV_NS		0xb	/* Inval Namespace or Format */
274 #define	NVME_CQE_SC_GEN_CMD_SEQ_ERR	0xc	/* Command Sequence Error */
275 #define	NVME_CQE_SC_GEN_INV_SGL_LAST	0xd	/* Inval SGL Last Seg Desc */
276 #define	NVME_CQE_SC_GEN_INV_SGL_NUM	0xe	/* Inval Number of SGL Desc */
277 #define	NVME_CQE_SC_GEN_INV_DSGL_LEN	0xf	/* Data SGL Length Invalid */
278 #define	NVME_CQE_SC_GEN_INV_MSGL_LEN	0x10	/* Metadata SGL Length Inval */
279 #define	NVME_CQE_SC_GEN_INV_SGL_DESC	0x11	/* SGL Descriptor Type Inval */
280 
281 /* NVMe completion status code (generic NVM commands) */
282 #define	NVME_CQE_SC_GEN_NVM_LBA_RANGE	0x80	/* LBA Out Of Range */
283 #define	NVME_CQE_SC_GEN_NVM_CAP_EXC	0x81	/* Capacity Exceeded */
284 #define	NVME_CQE_SC_GEN_NVM_NS_NOTRDY	0x82	/* Namespace Not Ready */
285 #define	NVME_CQE_SC_GEN_NVM_RSV_CNFLCT	0x83	/* Reservation Conflict */
286 
287 /* NVMe completion status code (command specific) */
288 #define	NVME_CQE_SC_SPC_INV_CQ		0x0	/* Completion Queue Invalid */
289 #define	NVME_CQE_SC_SPC_INV_QID		0x1	/* Invalid Queue Identifier */
290 #define	NVME_CQE_SC_SPC_MAX_QSZ_EXC	0x2	/* Max Queue Size Exceeded */
291 #define	NVME_CQE_SC_SPC_ABRT_CMD_EXC	0x3	/* Abort Cmd Limit Exceeded */
292 #define	NVME_CQE_SC_SPC_ASYNC_EVREQ_EXC	0x5	/* Async Event Request Limit */
293 #define	NVME_CQE_SC_SPC_INV_FW_SLOT	0x6	/* Invalid Firmware Slot */
294 #define	NVME_CQE_SC_SPC_INV_FW_IMG	0x7	/* Invalid Firmware Image */
295 #define	NVME_CQE_SC_SPC_INV_INT_VECT	0x8	/* Invalid Interrupt Vector */
296 #define	NVME_CQE_SC_SPC_INV_LOG_PAGE	0x9	/* Invalid Log Page */
297 #define	NVME_CQE_SC_SPC_INV_FORMAT	0xa	/* Invalid Format */
298 #define	NVME_CQE_SC_SPC_FW_RESET	0xb	/* FW Application Reset Reqd */
299 #define	NVME_CQE_SC_SPC_INV_Q_DEL	0xc	/* Invalid Queue Deletion */
300 #define	NVME_CQE_SC_SPC_FEAT_SAVE	0xd	/* Feature Id Not Saveable */
301 #define	NVME_CQE_SC_SPC_FEAT_CHG	0xe	/* Feature Not Changeable */
302 #define	NVME_CQE_SC_SPC_FEAT_NS_SPEC	0xf	/* Feature Not Namespace Spec */
303 #define	NVME_CQE_SC_SPC_FW_NSSR		0x10	/* FW Application NSSR Reqd */
304 
305 /* NVMe completion status code (NVM command specific */
306 #define	NVME_CQE_SC_SPC_NVM_CNFL_ATTR	0x80	/* Conflicting Attributes */
307 #define	NVME_CQE_SC_SPC_NVM_INV_PROT	0x81	/* Invalid Protection */
308 #define	NVME_CQE_SC_SPC_NVM_READONLY	0x82	/* Write to Read Only Range */
309 
310 /* NVMe completion status code (data / metadata integrity) */
311 #define	NVME_CQE_SC_INT_NVM_WRITE	0x80	/* Write Fault */
312 #define	NVME_CQE_SC_INT_NVM_READ	0x81	/* Unrecovered Read Error */
313 #define	NVME_CQE_SC_INT_NVM_GUARD	0x82	/* Guard Check Error */
314 #define	NVME_CQE_SC_INT_NVM_APPL_TAG	0x83	/* Application Tag Check Err */
315 #define	NVME_CQE_SC_INT_NVM_REF_TAG	0x84	/* Reference Tag Check Err */
316 #define	NVME_CQE_SC_INT_NVM_COMPARE	0x85	/* Compare Failure */
317 #define	NVME_CQE_SC_INT_NVM_ACCESS	0x86	/* Access Denied */
318 
319 /*
320  * NVMe Asynchronous Event Request
321  */
322 #define	NVME_ASYNC_TYPE_ERROR		0x0	/* Error Status */
323 #define	NVME_ASYNC_TYPE_HEALTH		0x1	/* SMART/Health Status */
324 #define	NVME_ASYNC_TYPE_VENDOR		0x7	/* vendor specific */
325 
326 #define	NVME_ASYNC_ERROR_INV_SQ		0x0	/* Invalid Submission Queue */
327 #define	NVME_ASYNC_ERROR_INV_DBL	0x1	/* Invalid Doorbell Write */
328 #define	NVME_ASYNC_ERROR_DIAGFAIL	0x2	/* Diagnostic Failure */
329 #define	NVME_ASYNC_ERROR_PERSISTENT	0x3	/* Persistent Internal Error */
330 #define	NVME_ASYNC_ERROR_TRANSIENT	0x4	/* Transient Internal Error */
331 #define	NVME_ASYNC_ERROR_FW_LOAD	0x5	/* Firmware Image Load Error */
332 
333 #define	NVME_ASYNC_HEALTH_RELIABILITY	0x0	/* Device Reliability */
334 #define	NVME_ASYNC_HEALTH_TEMPERATURE	0x1	/* Temp. Above Threshold */
335 #define	NVME_ASYNC_HEALTH_SPARE		0x2	/* Spare Below Threshold */
336 
337 typedef union {
338 	struct {
339 		uint8_t ae_type:3;		/* Asynchronous Event Type */
340 		uint8_t ae_rsvd1:5;
341 		uint8_t ae_info;		/* Asynchronous Event Info */
342 		uint8_t ae_logpage;		/* Associated Log Page */
343 		uint8_t ae_rsvd2;
344 	} b;
345 	uint32_t r;
346 } nvme_async_event_t;
347 
348 /*
349  * NVMe Create Completion/Submission Queue
350  */
351 typedef union {
352 	struct {
353 		uint16_t q_qid;			/* Queue Identifier */
354 		uint16_t q_qsize; 		/* Queue Size */
355 	} b;
356 	uint32_t r;
357 } nvme_create_queue_dw10_t;
358 
359 typedef union {
360 	struct {
361 		uint16_t cq_pc:1;		/* Physically Contiguous */
362 		uint16_t cq_ien:1;		/* Interrupts Enabled */
363 		uint16_t cq_rsvd:14;
364 		uint16_t cq_iv;			/* Interrupt Vector */
365 	} b;
366 	uint32_t r;
367 } nvme_create_cq_dw11_t;
368 
369 typedef union {
370 	struct {
371 		uint16_t sq_pc:1;		/* Physically Contiguous */
372 		uint16_t sq_qprio:2;		/* Queue Priority */
373 		uint16_t sq_rsvd:13;
374 		uint16_t sq_cqid;		/* Completion Queue ID */
375 	} b;
376 	uint32_t r;
377 } nvme_create_sq_dw11_t;
378 
379 /*
380  * NVMe Identify
381  */
382 
383 /* NVMe Identify parameters (cdw10) */
384 #define	NVME_IDENTIFY_NSID	0x0	/* Identify Namespace */
385 #define	NVME_IDENTIFY_CTRL	0x1	/* Identify Controller */
386 #define	NVME_IDENTIFY_LIST	0x2	/* Identify List Namespaces */
387 
388 
389 /*
390  * NVMe Abort Command
391  */
392 typedef union {
393 	struct {
394 		uint16_t ac_sqid;	/* Submission Queue ID */
395 		uint16_t ac_cid;	/* Command ID */
396 	} b;
397 	uint32_t r;
398 } nvme_abort_cmd_t;
399 
400 
401 /*
402  * NVMe Get Log Page
403  */
404 typedef union {
405 	struct {
406 		uint8_t lp_lid;		/* Log Page Identifier */
407 		uint8_t lp_rsvd1;
408 		uint16_t lp_numd:12;	/* Number of Dwords */
409 		uint16_t lp_rsvd2:4;
410 	} b;
411 	uint32_t r;
412 } nvme_getlogpage_t;
413 
414 
415 #ifdef __cplusplus
416 }
417 #endif
418 
419 #pragma pack() /* pack(1) */
420 
421 #endif /* _NVME_REG_H */
422