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