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
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.
13 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
14 * Copyright (c) 2018, Joyent, Inc.
18 * NVMe hardware interface
36 #define NVME_MAX_ADMIN_QUEUE_LEN 4096
39 * NVMe registers and register fields
41 #define NVME_REG_CAP 0x0 /* Controller Capabilities */
42 #define NVME_REG_VS 0x8 /* Version */
43 #define NVME_REG_INTMS 0xc /* Interrupt Mask Set */
44 #define NVME_REG_INTMC 0x10 /* Interrupt Mask Clear */
45 #define NVME_REG_CC 0x14 /* Controller Configuration */
46 #define NVME_REG_CSTS 0x1c /* Controller Status */
47 #define NVME_REG_NSSR 0x20 /* NVM Subsystem Reset */
48 #define NVME_REG_AQA 0x24 /* Admin Queue Attributes */
49 #define NVME_REG_ASQ 0x28 /* Admin Submission Queue */
50 #define NVME_REG_ACQ 0x30 /* Admin Completion Qeueu */
51 #define NVME_REG_CMBLOC 0x38 /* Controller Memory Buffer Location */
52 #define NVME_REG_CMBSZ 0x3C /* Controller Memory Buffer Size */
53 #define NVME_REG_BPINFO 0x40 /* Boot Partition Information */
54 #define NVME_REG_BPRSEL 0x44 /* Boot Partition Read Select */
55 #define NVME_REG_BPMBL 0x48 /* Boot Partition Memory Buffer Loc */
56 #define NVME_REG_SQTDBL(nvme, n) \
57 (0x1000 + ((2 * (n)) * nvme->n_doorbell_stride))
58 #define NVME_REG_CQHDBL(nvme, n) \
59 (0x1000 + ((2 * (n) + 1) * nvme->n_doorbell_stride))
61 #define NVME_CAP_CSS_NVM 1 /* NVM Command Set */
62 #define NVME_CAP_AMS_WRR 1 /* Weighted Round-Robin */
64 /* CAP -- Controller Capabilities */
67 uint16_t cap_mqes
; /* Maximum Queue Entries Supported */
68 uint8_t cap_cqr
:1; /* Contiguous Queues Required */
69 uint8_t cap_ams
:2; /* Arbitration Mechanisms Supported */
71 uint8_t cap_to
; /* Timeout */
72 uint16_t cap_dstrd
:4; /* Doorbell Stride */
73 uint16_t cap_nssrs
:1; /* NVM Subsystem Reset Supported */
74 uint16_t cap_css
:8; /* Command Sets Supported */
76 uint8_t cap_bps
:1; /* Boot Partition Support */
77 uint8_t cap_mpsmin
:4; /* Memory Page Size Minimum */
78 uint8_t cap_mpsmax
:4; /* Memory Page Size Maximum */
88 uint8_t vs_mnr
; /* Minor Version Number */
89 uint16_t vs_mjr
; /* Major Version Number */
94 /* CC -- Controller Configuration */
95 #define NVME_CC_SHN_NORMAL 1 /* Normal Shutdown Notification */
96 #define NVME_CC_SHN_ABRUPT 2 /* Abrupt Shutdown Notification */
100 uint16_t cc_en
:1; /* Enable */
102 uint16_t cc_css
:3; /* I/O Command Set Selected */
103 uint16_t cc_mps
:4; /* Memory Page Size */
104 uint16_t cc_ams
:3; /* Arbitration Mechanism Selected */
105 uint16_t cc_shn
:2; /* Shutdown Notification */
106 uint8_t cc_iosqes
:4; /* I/O Submission Queue Entry Size */
107 uint8_t cc_iocqes
:4; /* I/O Completion Queue Entry Size */
113 /* CSTS -- Controller Status */
114 #define NVME_CSTS_SHN_OCCURING 1 /* Shutdown Processing Occuring */
115 #define NVME_CSTS_SHN_COMPLETE 2 /* Shutdown Processing Complete */
119 uint32_t csts_rdy
:1; /* Ready */
120 uint32_t csts_cfs
:1; /* Controller Fatal Status */
121 uint32_t csts_shst
:2; /* Shutdown Status */
122 uint32_t csts_nssro
:1; /* NVM Subsystem Reset Occured */
123 uint32_t csts_pp
:1; /* Processing Paused */
124 uint32_t csts_rsvd
:26;
129 /* NSSR -- NVM Subsystem Reset */
130 #define NVME_NSSR_NSSRC 0x4e564d65 /* NSSR magic value */
131 typedef uint32_t nvme_reg_nssr_t
;
133 /* AQA -- Admin Queue Attributes */
136 uint16_t aqa_asqs
:12; /* Admin Submission Queue Size */
137 uint16_t aqa_rsvd1
:4;
138 uint16_t aqa_acqs
:12; /* Admin Completion Queue Size */
139 uint16_t aqa_rsvd2
:4;
145 * The spec specifies the lower 12 bits of ASQ and ACQ as reserved, which is
146 * probably a specification bug. The full 64bit regs are used as base address,
147 * and the lower bits must be zero to ensure alignment on the page size
148 * specified in CC.MPS.
150 /* ASQ -- Admin Submission Queue Base Address */
151 typedef uint64_t nvme_reg_asq_t
; /* Admin Submission Queue Base */
153 /* ACQ -- Admin Completion Queue Base Address */
154 typedef uint64_t nvme_reg_acq_t
; /* Admin Completion Queue Base */
156 /* CMBLOC - Controller Memory Buffer Location */
159 uint32_t cmbloc_bir
:3; /* Base Indicator Register */
160 uint32_t cmbloc_rsvd
:9;
161 uint32_t cmbloc_ofst
:20; /* Offset */
166 /* CMBSZ - Controller Memory Buffer Size */
169 uint32_t cmbsz_sqs
:1; /* Submission Queue Support */
170 uint32_t cmbsz_cqs
:1; /* Completion Queue Support */
171 uint32_t cmbsz_lists
:1; /* PRP SGL List Support */
172 uint32_t cmbsz_rds
:1; /* Read Data Support */
173 uint32_t cmbsz_wds
:1; /* Write Data Support */
174 uint32_t cmbsz_rsvd
:3;
175 uint32_t cmbsz_szu
:4; /* Size Units */
176 uint32_t cmbsz_sz
:20; /* Size */
181 /* BPINFO - Boot Partition Information */
184 uint32_t bpinfo_bpsz
:15; /* Boot Partition Size */
185 uint32_t bpinfo_rsvd
:9;
186 uint32_t bpinfo_brs
:2; /* Boot Read Status */
187 uint32_t bpinfo_rsvd2
:5;
188 uint32_t bpinfo_abpid
:1; /* Active Boot Partition ID */
193 /* BPRSEL - Boot Partition Read Select */
196 uint32_t bprsel_bprsz
:10; /* Boot Partition Read Size */
197 uint32_t bprsel_bprof
:20; /* Boot Partition Read Offset */
198 uint32_t bprsel_rsvd
:1;
199 uint32_t bprsel_bpid
:1; /* Boot Partition Identifier */
204 /* BPMBL - Boot Partition Memory Location Buffer Location */
205 typedef uint64_t nvme_reg_bpbml_t
; /* Memory Buffer Base Address */
207 /* SQyTDBL -- Submission Queue y Tail Doorbell */
210 uint16_t sqtdbl_sqt
; /* Submission Queue Tail */
211 uint16_t sqtdbl_rsvd
;
216 /* CQyHDBL -- Completion Queue y Head Doorbell */
219 uint16_t cqhdbl_cqh
; /* Completion Queue Head */
220 uint16_t cqhdbl_rsvd
;
226 * NVMe submission queue entries
229 /* NVMe scatter/gather list descriptor */
231 uint64_t sgl_addr
; /* Address */
232 uint32_t sgl_len
; /* Length */
235 uint8_t sgl_type
:4; /* SGL descriptor type */
238 /* NVMe SGL descriptor type */
239 #define NVME_SGL_DATA_BLOCK 0
240 #define NVME_SGL_BIT_BUCKET 1
241 #define NVME_SGL_SEGMENT 2
242 #define NVME_SGL_LAST_SEGMENT 3
243 #define NVME_SGL_VENDOR 0xf
245 /* NVMe submission queue entry */
247 uint8_t sqe_opc
; /* Opcode */
248 uint8_t sqe_fuse
:2; /* Fused Operation */
250 uint8_t sqe_psdt
:1; /* PRP or SGL for Data Transfer */
251 uint16_t sqe_cid
; /* Command Identifier */
252 uint32_t sqe_nsid
; /* Namespace Identifier */
255 uint64_t m_ptr
; /* Metadata Pointer */
256 uint64_t m_sglp
; /* Metadata SGL Segment Pointer */
259 uint64_t d_prp
[2]; /* Physical Page Region Entries 1 & 2 */
260 nvme_sgl_t d_sgl
; /* SGL Entry 1 */
261 } sqe_dptr
; /* Data Pointer */
262 uint32_t sqe_cdw10
; /* Number of Dwords in Data Transfer */
263 uint32_t sqe_cdw11
; /* Number of Dwords in Metadata Xfer */
270 /* NVMe admin command opcodes */
271 #define NVME_OPC_DELETE_SQUEUE 0x0
272 #define NVME_OPC_CREATE_SQUEUE 0x1
273 #define NVME_OPC_GET_LOG_PAGE 0x2
274 #define NVME_OPC_DELETE_CQUEUE 0x4
275 #define NVME_OPC_CREATE_CQUEUE 0x5
276 #define NVME_OPC_IDENTIFY 0x6
277 #define NVME_OPC_ABORT 0x8
278 #define NVME_OPC_SET_FEATURES 0x9
279 #define NVME_OPC_GET_FEATURES 0xa
280 #define NVME_OPC_ASYNC_EVENT 0xc
281 #define NVME_OPC_NS_MGMT 0xd /* 1.2 */
282 #define NVME_OPC_FW_ACTIVATE 0x10
283 #define NVME_OPC_FW_IMAGE_LOAD 0x11
284 #define NVME_OPC_SELF_TEST 0x14 /* 1.3 */
285 #define NVME_OPC_NS_ATTACH 0x15 /* 1.2 */
286 #define NVME_OPC_KEEP_ALIVE 0x18 /* 1.3 */
287 #define NVME_OPC_DIRECTIVE_SEND 0x19 /* 1.3 */
288 #define NVME_OPC_DIRECTIVE_RECV 0x1A /* 1.3 */
289 #define NVME_OPC_VIRT_MGMT 0x1C /* 1.3 */
290 #define NVME_OPC_NVMEMI_SEND 0x1D /* 1.3 */
291 #define NVME_OPC_NVMEMI_RECV 0x1E /* 1.3 */
292 #define NVME_OPC_DB_CONFIG 0x7C /* 1.3 */
294 /* NVMe NVM command set specific admin command opcodes */
295 #define NVME_OPC_NVM_FORMAT 0x80
296 #define NVME_OPC_NVM_SEC_SEND 0x81
297 #define NVME_OPC_NVM_SEC_RECV 0x82
299 /* NVMe NVM command opcodes */
300 #define NVME_OPC_NVM_FLUSH 0x0
301 #define NVME_OPC_NVM_WRITE 0x1
302 #define NVME_OPC_NVM_READ 0x2
303 #define NVME_OPC_NVM_WRITE_UNC 0x4
304 #define NVME_OPC_NVM_COMPARE 0x5
305 #define NVME_OPC_NVM_WRITE_ZERO 0x8
306 #define NVME_OPC_NVM_DSET_MGMT 0x9
307 #define NVME_OPC_NVM_RESV_REG 0xd
308 #define NVME_OPC_NVM_RESV_REPRT 0xe
309 #define NVME_OPC_NVM_RESV_ACQ 0x11
310 #define NVME_OPC_NVM_RESV_REL 0x12
313 * NVMe completion queue entry
316 uint32_t cqe_dw0
; /* Command Specific */
318 uint16_t cqe_sqhd
; /* SQ Head Pointer */
319 uint16_t cqe_sqid
; /* SQ Identifier */
320 uint16_t cqe_cid
; /* Command Identifier */
321 nvme_cqe_sf_t cqe_sf
; /* Status Field */
324 /* NVMe completion status code type */
325 #define NVME_CQE_SCT_GENERIC 0 /* Generic Command Status */
326 #define NVME_CQE_SCT_SPECIFIC 1 /* Command Specific Status */
327 #define NVME_CQE_SCT_INTEGRITY 2 /* Media and Data Integrity Errors */
328 #define NVME_CQE_SCT_VENDOR 7 /* Vendor Specific */
330 /* NVMe completion status code (generic) */
331 #define NVME_CQE_SC_GEN_SUCCESS 0x0 /* Successful Completion */
332 #define NVME_CQE_SC_GEN_INV_OPC 0x1 /* Invalid Command Opcode */
333 #define NVME_CQE_SC_GEN_INV_FLD 0x2 /* Invalid Field in Command */
334 #define NVME_CQE_SC_GEN_ID_CNFL 0x3 /* Command ID Conflict */
335 #define NVME_CQE_SC_GEN_DATA_XFR_ERR 0x4 /* Data Transfer Error */
336 #define NVME_CQE_SC_GEN_ABORT_PWRLOSS 0x5 /* Cmds Aborted / Pwr Loss */
337 #define NVME_CQE_SC_GEN_INTERNAL_ERR 0x6 /* Internal Error */
338 #define NVME_CQE_SC_GEN_ABORT_REQUEST 0x7 /* Command Abort Requested */
339 #define NVME_CQE_SC_GEN_ABORT_SQ_DEL 0x8 /* Cmd Aborted / SQ deletion */
340 #define NVME_CQE_SC_GEN_ABORT_FUSE_FAIL 0x9 /* Cmd Aborted / Failed Fused */
341 #define NVME_CQE_SC_GEN_ABORT_FUSE_MISS 0xa /* Cmd Aborted / Missing Fusd */
342 #define NVME_CQE_SC_GEN_INV_NS 0xb /* Inval Namespace or Format */
343 #define NVME_CQE_SC_GEN_CMD_SEQ_ERR 0xc /* Command Sequence Error */
344 #define NVME_CQE_SC_GEN_INV_SGL_LAST 0xd /* Inval SGL Last Seg Desc */
345 #define NVME_CQE_SC_GEN_INV_SGL_NUM 0xe /* Inval Number of SGL Desc */
346 #define NVME_CQE_SC_GEN_INV_DSGL_LEN 0xf /* Data SGL Length Invalid */
347 #define NVME_CQE_SC_GEN_INV_MSGL_LEN 0x10 /* Metadata SGL Length Inval */
348 #define NVME_CQE_SC_GEN_INV_SGL_DESC 0x11 /* SGL Descriptor Type Inval */
350 /* NVMe completion status code (generic NVM commands) */
351 #define NVME_CQE_SC_GEN_NVM_LBA_RANGE 0x80 /* LBA Out Of Range */
352 #define NVME_CQE_SC_GEN_NVM_CAP_EXC 0x81 /* Capacity Exceeded */
353 #define NVME_CQE_SC_GEN_NVM_NS_NOTRDY 0x82 /* Namespace Not Ready */
354 #define NVME_CQE_SC_GEN_NVM_RSV_CNFLCT 0x83 /* Reservation Conflict */
356 /* NVMe completion status code (command specific) */
357 #define NVME_CQE_SC_SPC_INV_CQ 0x0 /* Completion Queue Invalid */
358 #define NVME_CQE_SC_SPC_INV_QID 0x1 /* Invalid Queue Identifier */
359 #define NVME_CQE_SC_SPC_MAX_QSZ_EXC 0x2 /* Max Queue Size Exceeded */
360 #define NVME_CQE_SC_SPC_ABRT_CMD_EXC 0x3 /* Abort Cmd Limit Exceeded */
361 #define NVME_CQE_SC_SPC_ASYNC_EVREQ_EXC 0x5 /* Async Event Request Limit */
362 #define NVME_CQE_SC_SPC_INV_FW_SLOT 0x6 /* Invalid Firmware Slot */
363 #define NVME_CQE_SC_SPC_INV_FW_IMG 0x7 /* Invalid Firmware Image */
364 #define NVME_CQE_SC_SPC_INV_INT_VECT 0x8 /* Invalid Interrupt Vector */
365 #define NVME_CQE_SC_SPC_INV_LOG_PAGE 0x9 /* Invalid Log Page */
366 #define NVME_CQE_SC_SPC_INV_FORMAT 0xa /* Invalid Format */
367 #define NVME_CQE_SC_SPC_FW_RESET 0xb /* FW Application Reset Reqd */
368 #define NVME_CQE_SC_SPC_INV_Q_DEL 0xc /* Invalid Queue Deletion */
369 #define NVME_CQE_SC_SPC_FEAT_SAVE 0xd /* Feature Id Not Saveable */
370 #define NVME_CQE_SC_SPC_FEAT_CHG 0xe /* Feature Not Changeable */
371 #define NVME_CQE_SC_SPC_FEAT_NS_SPEC 0xf /* Feature Not Namespace Spec */
372 #define NVME_CQE_SC_SPC_FW_NSSR 0x10 /* FW Application NSSR Reqd */
374 /* NVMe completion status code (NVM command specific */
375 #define NVME_CQE_SC_SPC_NVM_CNFL_ATTR 0x80 /* Conflicting Attributes */
376 #define NVME_CQE_SC_SPC_NVM_INV_PROT 0x81 /* Invalid Protection */
377 #define NVME_CQE_SC_SPC_NVM_READONLY 0x82 /* Write to Read Only Range */
379 /* NVMe completion status code (data / metadata integrity) */
380 #define NVME_CQE_SC_INT_NVM_WRITE 0x80 /* Write Fault */
381 #define NVME_CQE_SC_INT_NVM_READ 0x81 /* Unrecovered Read Error */
382 #define NVME_CQE_SC_INT_NVM_GUARD 0x82 /* Guard Check Error */
383 #define NVME_CQE_SC_INT_NVM_APPL_TAG 0x83 /* Application Tag Check Err */
384 #define NVME_CQE_SC_INT_NVM_REF_TAG 0x84 /* Reference Tag Check Err */
385 #define NVME_CQE_SC_INT_NVM_COMPARE 0x85 /* Compare Failure */
386 #define NVME_CQE_SC_INT_NVM_ACCESS 0x86 /* Access Denied */
389 * NVMe Asynchronous Event Request
391 #define NVME_ASYNC_TYPE_ERROR 0x0 /* Error Status */
392 #define NVME_ASYNC_TYPE_HEALTH 0x1 /* SMART/Health Status */
393 #define NVME_ASYNC_TYPE_VENDOR 0x7 /* vendor specific */
395 #define NVME_ASYNC_ERROR_INV_SQ 0x0 /* Invalid Submission Queue */
396 #define NVME_ASYNC_ERROR_INV_DBL 0x1 /* Invalid Doorbell Write */
397 #define NVME_ASYNC_ERROR_DIAGFAIL 0x2 /* Diagnostic Failure */
398 #define NVME_ASYNC_ERROR_PERSISTENT 0x3 /* Persistent Internal Error */
399 #define NVME_ASYNC_ERROR_TRANSIENT 0x4 /* Transient Internal Error */
400 #define NVME_ASYNC_ERROR_FW_LOAD 0x5 /* Firmware Image Load Error */
402 #define NVME_ASYNC_HEALTH_RELIABILITY 0x0 /* Device Reliability */
403 #define NVME_ASYNC_HEALTH_TEMPERATURE 0x1 /* Temp. Above Threshold */
404 #define NVME_ASYNC_HEALTH_SPARE 0x2 /* Spare Below Threshold */
408 uint8_t ae_type
:3; /* Asynchronous Event Type */
410 uint8_t ae_info
; /* Asynchronous Event Info */
411 uint8_t ae_logpage
; /* Associated Log Page */
415 } nvme_async_event_t
;
418 * NVMe Create Completion/Submission Queue
422 uint16_t q_qid
; /* Queue Identifier */
423 uint16_t q_qsize
; /* Queue Size */
426 } nvme_create_queue_dw10_t
;
430 uint16_t cq_pc
:1; /* Physically Contiguous */
431 uint16_t cq_ien
:1; /* Interrupts Enabled */
433 uint16_t cq_iv
; /* Interrupt Vector */
436 } nvme_create_cq_dw11_t
;
440 uint16_t sq_pc
:1; /* Physically Contiguous */
441 uint16_t sq_qprio
:2; /* Queue Priority */
443 uint16_t sq_cqid
; /* Completion Queue ID */
446 } nvme_create_sq_dw11_t
;
452 /* NVMe Identify parameters (cdw10) */
453 #define NVME_IDENTIFY_NSID 0x0 /* Identify Namespace */
454 #define NVME_IDENTIFY_CTRL 0x1 /* Identify Controller */
455 #define NVME_IDENTIFY_LIST 0x2 /* Identify List Namespaces */
457 #define NVME_IDENTIFY_NSID_ALLOC_LIST 0x10 /* List Allocated NSID */
458 #define NVME_IDENTIFY_NSID_ALLOC 0x11 /* Identify Allocated NSID */
459 #define NVME_IDENTIFY_NSID_CTRL_LIST 0x12 /* List Controllers on NSID */
460 #define NVME_IDENTIFY_CTRL_LIST 0x13 /* Controller List */
461 #define NVME_IDENTIFY_PRIMARY_CAPS 0x14 /* Primary Controller Caps */
468 uint16_t ac_sqid
; /* Submission Queue ID */
469 uint16_t ac_cid
; /* Command ID */
480 uint8_t lp_lid
; /* Log Page Identifier */
482 uint16_t lp_numd
:12; /* Number of Dwords */
493 #pragma pack() /* pack(1) */
495 #endif /* _NVME_REG_H */