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 2020 Joyent, Inc. 14 * Copyright 2022 Tintri by DDN, Inc. All rights reserved. 15 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association. 16 */ 17 18 /* 19 * NVMe hardware interface 20 */ 21 22 #ifndef _NVME_REG_H 23 #define _NVME_REG_H 24 25 #include <sys/nvme.h> 26 27 #pragma pack(1) 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 34 /* 35 * NVMe constants 36 */ 37 #define NVME_MAX_ADMIN_QUEUE_LEN 4096 38 39 /* 40 * NVMe registers and register fields 41 */ 42 #define NVME_REG_CAP 0x0 /* Controller Capabilities */ 43 #define NVME_REG_VS 0x8 /* Version */ 44 #define NVME_REG_INTMS 0xc /* Interrupt Mask Set */ 45 #define NVME_REG_INTMC 0x10 /* Interrupt Mask Clear */ 46 #define NVME_REG_CC 0x14 /* Controller Configuration */ 47 #define NVME_REG_CSTS 0x1c /* Controller Status */ 48 #define NVME_REG_NSSR 0x20 /* NVM Subsystem Reset */ 49 #define NVME_REG_AQA 0x24 /* Admin Queue Attributes */ 50 #define NVME_REG_ASQ 0x28 /* Admin Submission Queue */ 51 #define NVME_REG_ACQ 0x30 /* Admin Completion Qeueu */ 52 #define NVME_REG_CMBLOC 0x38 /* Controller Memory Buffer Location */ 53 #define NVME_REG_CMBSZ 0x3C /* Controller Memory Buffer Size */ 54 #define NVME_REG_BPINFO 0x40 /* Boot Partition Information */ 55 #define NVME_REG_BPRSEL 0x44 /* Boot Partition Read Select */ 56 #define NVME_REG_BPMBL 0x48 /* Boot Partition Memory Buffer Loc */ 57 #define NVME_REG_SQTDBL(nvme, n) \ 58 (0x1000 + ((2 * (n)) * nvme->n_doorbell_stride)) 59 #define NVME_REG_CQHDBL(nvme, n) \ 60 (0x1000 + ((2 * (n) + 1) * nvme->n_doorbell_stride)) 61 62 #define NVME_CAP_CSS_NVM 1 /* NVM Command Set */ 63 #define NVME_CAP_AMS_WRR 1 /* Weighted Round-Robin */ 64 65 /* CAP -- Controller Capabilities */ 66 typedef union { 67 struct { 68 uint16_t cap_mqes; /* Maximum Queue Entries Supported */ 69 uint8_t cap_cqr:1; /* Contiguous Queues Required */ 70 uint8_t cap_ams:2; /* Arbitration Mechanisms Supported */ 71 uint8_t cap_rsvd1:5; 72 uint8_t cap_to; /* Timeout */ 73 uint16_t cap_dstrd:4; /* Doorbell Stride */ 74 uint16_t cap_nssrs:1; /* NVM Subsystem Reset Supported */ 75 uint16_t cap_css:8; /* Command Sets Supported */ 76 uint16_t cap_rsvd2:2; 77 uint8_t cap_bps:1; /* Boot Partition Support */ 78 uint8_t cap_mpsmin:4; /* Memory Page Size Minimum */ 79 uint8_t cap_mpsmax:4; /* Memory Page Size Maximum */ 80 uint8_t cap_rsvd3; 81 } b; 82 uint64_t r; 83 } nvme_reg_cap_t; 84 85 /* VS -- Version */ 86 typedef union { 87 struct { 88 uint8_t vs_rsvd; 89 uint8_t vs_mnr; /* Minor Version Number */ 90 uint16_t vs_mjr; /* Major Version Number */ 91 } b; 92 uint32_t r; 93 } nvme_reg_vs_t; 94 95 /* CC -- Controller Configuration */ 96 #define NVME_CC_SHN_NORMAL 1 /* Normal Shutdown Notification */ 97 #define NVME_CC_SHN_ABRUPT 2 /* Abrupt Shutdown Notification */ 98 99 typedef union { 100 struct { 101 uint16_t cc_en:1; /* Enable */ 102 uint16_t cc_rsvd1:3; 103 uint16_t cc_css:3; /* I/O Command Set Selected */ 104 uint16_t cc_mps:4; /* Memory Page Size */ 105 uint16_t cc_ams:3; /* Arbitration Mechanism Selected */ 106 uint16_t cc_shn:2; /* Shutdown Notification */ 107 uint8_t cc_iosqes:4; /* I/O Submission Queue Entry Size */ 108 uint8_t cc_iocqes:4; /* I/O Completion Queue Entry Size */ 109 uint8_t cc_rsvd2; 110 } b; 111 uint32_t r; 112 } nvme_reg_cc_t; 113 114 /* CSTS -- Controller Status */ 115 #define NVME_CSTS_SHN_OCCURING 1 /* Shutdown Processing Occuring */ 116 #define NVME_CSTS_SHN_COMPLETE 2 /* Shutdown Processing Complete */ 117 118 typedef union { 119 struct { 120 uint32_t csts_rdy:1; /* Ready */ 121 uint32_t csts_cfs:1; /* Controller Fatal Status */ 122 uint32_t csts_shst:2; /* Shutdown Status */ 123 uint32_t csts_nssro:1; /* NVM Subsystem Reset Occured */ 124 uint32_t csts_pp:1; /* Processing Paused */ 125 uint32_t csts_rsvd:26; 126 } b; 127 uint32_t r; 128 } nvme_reg_csts_t; 129 130 /* NSSR -- NVM Subsystem Reset */ 131 #define NVME_NSSR_NSSRC 0x4e564d65 /* NSSR magic value */ 132 typedef uint32_t nvme_reg_nssr_t; 133 134 /* AQA -- Admin Queue Attributes */ 135 typedef union { 136 struct { 137 uint16_t aqa_asqs:12; /* Admin Submission Queue Size */ 138 uint16_t aqa_rsvd1:4; 139 uint16_t aqa_acqs:12; /* Admin Completion Queue Size */ 140 uint16_t aqa_rsvd2:4; 141 } b; 142 uint32_t r; 143 } nvme_reg_aqa_t; 144 145 /* 146 * The spec specifies the lower 12 bits of ASQ and ACQ as reserved, which is 147 * probably a specification bug. The full 64bit regs are used as base address, 148 * and the lower bits must be zero to ensure alignment on the page size 149 * specified in CC.MPS. 150 */ 151 /* ASQ -- Admin Submission Queue Base Address */ 152 typedef uint64_t nvme_reg_asq_t; /* Admin Submission Queue Base */ 153 154 /* ACQ -- Admin Completion Queue Base Address */ 155 typedef uint64_t nvme_reg_acq_t; /* Admin Completion Queue Base */ 156 157 /* CMBLOC - Controller Memory Buffer Location */ 158 typedef union { 159 struct { 160 uint32_t cmbloc_bir:3; /* Base Indicator Register */ 161 uint32_t cmbloc_rsvd:9; 162 uint32_t cmbloc_ofst:20; /* Offset */ 163 } b; 164 uint32_t r; 165 } nvme_reg_cmbloc_t; 166 167 /* CMBSZ - Controller Memory Buffer Size */ 168 typedef union { 169 struct { 170 uint32_t cmbsz_sqs:1; /* Submission Queue Support */ 171 uint32_t cmbsz_cqs:1; /* Completion Queue Support */ 172 uint32_t cmbsz_lists:1; /* PRP SGL List Support */ 173 uint32_t cmbsz_rds:1; /* Read Data Support */ 174 uint32_t cmbsz_wds:1; /* Write Data Support */ 175 uint32_t cmbsz_rsvd:3; 176 uint32_t cmbsz_szu:4; /* Size Units */ 177 uint32_t cmbsz_sz:20; /* Size */ 178 } b; 179 uint32_t r; 180 } nvme_reg_cmbsz_t; 181 182 /* BPINFO - Boot Partition Information */ 183 typedef union { 184 struct { 185 uint32_t bpinfo_bpsz:15; /* Boot Partition Size */ 186 uint32_t bpinfo_rsvd:9; 187 uint32_t bpinfo_brs:2; /* Boot Read Status */ 188 uint32_t bpinfo_rsvd2:5; 189 uint32_t bpinfo_abpid:1; /* Active Boot Partition ID */ 190 } b; 191 uint32_t r; 192 } nvme_reg_bpinfo_t; 193 194 /* BPRSEL - Boot Partition Read Select */ 195 typedef union { 196 struct { 197 uint32_t bprsel_bprsz:10; /* Boot Partition Read Size */ 198 uint32_t bprsel_bprof:20; /* Boot Partition Read Offset */ 199 uint32_t bprsel_rsvd:1; 200 uint32_t bprsel_bpid:1; /* Boot Partition Identifier */ 201 } b; 202 uint32_t r; 203 } nvme_reg_bprsel_t; 204 205 /* BPMBL - Boot Partition Memory Location Buffer Location */ 206 typedef uint64_t nvme_reg_bpbml_t; /* Memory Buffer Base Address */ 207 208 /* SQyTDBL -- Submission Queue y Tail Doorbell */ 209 typedef union { 210 struct { 211 uint16_t sqtdbl_sqt; /* Submission Queue Tail */ 212 uint16_t sqtdbl_rsvd; 213 } b; 214 uint32_t r; 215 } nvme_reg_sqtdbl_t; 216 217 /* CQyHDBL -- Completion Queue y Head Doorbell */ 218 typedef union { 219 struct { 220 uint16_t cqhdbl_cqh; /* Completion Queue Head */ 221 uint16_t cqhdbl_rsvd; 222 } b; 223 uint32_t r; 224 } nvme_reg_cqhdbl_t; 225 226 /* 227 * NVMe submission queue entries 228 */ 229 230 /* NVMe scatter/gather list descriptor */ 231 typedef struct { 232 uint64_t sgl_addr; /* Address */ 233 uint32_t sgl_len; /* Length */ 234 uint8_t sgl_rsvd[3]; 235 uint8_t sgl_zero:4; 236 uint8_t sgl_type:4; /* SGL descriptor type */ 237 } nvme_sgl_t; 238 239 /* NVMe SGL descriptor type */ 240 #define NVME_SGL_DATA_BLOCK 0 241 #define NVME_SGL_BIT_BUCKET 1 242 #define NVME_SGL_SEGMENT 2 243 #define NVME_SGL_LAST_SEGMENT 3 244 #define NVME_SGL_VENDOR 0xf 245 246 /* NVMe submission queue entry */ 247 typedef struct { 248 uint8_t sqe_opc; /* Opcode */ 249 uint8_t sqe_fuse:2; /* Fused Operation */ 250 uint8_t sqe_rsvd:5; 251 uint8_t sqe_psdt:1; /* PRP or SGL for Data Transfer */ 252 uint16_t sqe_cid; /* Command Identifier */ 253 uint32_t sqe_nsid; /* Namespace Identifier */ 254 uint64_t sqe_rsvd1; 255 union { 256 uint64_t m_ptr; /* Metadata Pointer */ 257 uint64_t m_sglp; /* Metadata SGL Segment Pointer */ 258 } sqe_m; 259 union { 260 uint64_t d_prp[2]; /* Physical Page Region Entries 1 & 2 */ 261 nvme_sgl_t d_sgl; /* SGL Entry 1 */ 262 } sqe_dptr; /* Data Pointer */ 263 uint32_t sqe_cdw10; /* Number of Dwords in Data Transfer */ 264 uint32_t sqe_cdw11; /* Number of Dwords in Metadata Xfer */ 265 uint32_t sqe_cdw12; 266 uint32_t sqe_cdw13; 267 uint32_t sqe_cdw14; 268 uint32_t sqe_cdw15; 269 } nvme_sqe_t; 270 271 /* NVMe admin command opcodes */ 272 #define NVME_OPC_DELETE_SQUEUE 0x0 273 #define NVME_OPC_CREATE_SQUEUE 0x1 274 #define NVME_OPC_GET_LOG_PAGE 0x2 275 #define NVME_OPC_DELETE_CQUEUE 0x4 276 #define NVME_OPC_CREATE_CQUEUE 0x5 277 #define NVME_OPC_IDENTIFY 0x6 278 #define NVME_OPC_ABORT 0x8 279 #define NVME_OPC_SET_FEATURES 0x9 280 #define NVME_OPC_GET_FEATURES 0xa 281 #define NVME_OPC_ASYNC_EVENT 0xc 282 #define NVME_OPC_NS_MGMT 0xd /* 1.2 */ 283 #define NVME_OPC_FW_ACTIVATE 0x10 284 #define NVME_OPC_FW_IMAGE_LOAD 0x11 285 #define NVME_OPC_SELF_TEST 0x14 /* 1.3 */ 286 #define NVME_OPC_NS_ATTACH 0x15 /* 1.2 */ 287 #define NVME_OPC_KEEP_ALIVE 0x18 /* 1.3 */ 288 #define NVME_OPC_DIRECTIVE_SEND 0x19 /* 1.3 */ 289 #define NVME_OPC_DIRECTIVE_RECV 0x1A /* 1.3 */ 290 #define NVME_OPC_VIRT_MGMT 0x1C /* 1.3 */ 291 #define NVME_OPC_NVMEMI_SEND 0x1D /* 1.3 */ 292 #define NVME_OPC_NVMEMI_RECV 0x1E /* 1.3 */ 293 #define NVME_OPC_DB_CONFIG 0x7C /* 1.3 */ 294 295 /* NVMe NVM command set specific admin command opcodes */ 296 #define NVME_OPC_NVM_FORMAT 0x80 297 #define NVME_OPC_NVM_SEC_SEND 0x81 298 #define NVME_OPC_NVM_SEC_RECV 0x82 299 300 /* NVMe NVM command opcodes */ 301 #define NVME_OPC_NVM_FLUSH 0x0 302 #define NVME_OPC_NVM_WRITE 0x1 303 #define NVME_OPC_NVM_READ 0x2 304 #define NVME_OPC_NVM_WRITE_UNC 0x4 305 #define NVME_OPC_NVM_COMPARE 0x5 306 #define NVME_OPC_NVM_WRITE_ZERO 0x8 307 #define NVME_OPC_NVM_DSET_MGMT 0x9 308 #define NVME_OPC_NVM_RESV_REG 0xd 309 #define NVME_OPC_NVM_RESV_REPRT 0xe 310 #define NVME_OPC_NVM_RESV_ACQ 0x11 311 #define NVME_OPC_NVM_RESV_REL 0x12 312 313 /* 314 * NVMe completion queue entry 315 */ 316 typedef struct { 317 uint32_t cqe_dw0; /* Command Specific */ 318 uint32_t cqe_rsvd1; 319 uint16_t cqe_sqhd; /* SQ Head Pointer */ 320 uint16_t cqe_sqid; /* SQ Identifier */ 321 uint16_t cqe_cid; /* Command Identifier */ 322 nvme_cqe_sf_t cqe_sf; /* Status Field */ 323 } nvme_cqe_t; 324 325 /* 326 * NVMe Asynchronous Event Request 327 */ 328 #define NVME_ASYNC_TYPE_ERROR 0x0 /* Error Status */ 329 #define NVME_ASYNC_TYPE_HEALTH 0x1 /* SMART/Health Status */ 330 #define NVME_ASYNC_TYPE_NOTICE 0x2 /* Notice (1.2) */ 331 #define NVME_ASYNC_TYPE_VENDOR 0x7 /* Vendor specific */ 332 333 #define NVME_ASYNC_ERROR_INV_SQ 0x0 /* Invalid Submission Queue */ 334 #define NVME_ASYNC_ERROR_INV_DBL 0x1 /* Invalid Doorbell Write */ 335 #define NVME_ASYNC_ERROR_DIAGFAIL 0x2 /* Diagnostic Failure */ 336 #define NVME_ASYNC_ERROR_PERSISTENT 0x3 /* Persistent Internal Error */ 337 #define NVME_ASYNC_ERROR_TRANSIENT 0x4 /* Transient Internal Error */ 338 #define NVME_ASYNC_ERROR_FW_LOAD 0x5 /* Firmware Image Load Error */ 339 340 #define NVME_ASYNC_HEALTH_RELIABILITY 0x0 /* Device Reliability */ 341 #define NVME_ASYNC_HEALTH_TEMPERATURE 0x1 /* Temp. Above Threshold */ 342 #define NVME_ASYNC_HEALTH_SPARE 0x2 /* Spare Below Threshold */ 343 344 /* NVMe 1.2 */ 345 #define NVME_ASYNC_NOTICE_NS_CHANGE 0x0 /* Namespace attribute change */ 346 #define NVME_ASYNC_NOTICE_FW_ACTIVATE 0x1 /* Firmware activation start */ 347 /* NVMe 1.3 */ 348 #define NVME_ASYNC_NOTICE_TELEMETRY 0x2 /* Telemetry log changed */ 349 /* NVMe 1.4 */ 350 #define NVME_ASYNC_NOTICE_NS_ASYMM 0x3 /* Asymm. NS access change */ 351 #define NVME_ASYNC_NOTICE_LATENCYLOG 0x4 /* Pred. Latency log change */ 352 #define NVME_ASYNC_NOTICE_LBASTATUS 0x5 /* LBA status alert */ 353 #define NVME_ASYNC_NOTICE_ENDURANCELOG 0x6 /* Endurance log change */ 354 355 typedef union { 356 struct { 357 uint8_t ae_type:3; /* Asynchronous Event Type */ 358 uint8_t ae_rsvd1:5; 359 uint8_t ae_info; /* Asynchronous Event Info */ 360 uint8_t ae_logpage; /* Associated Log Page */ 361 uint8_t ae_rsvd2; 362 } b; 363 uint32_t r; 364 } nvme_async_event_t; 365 366 /* 367 * NVMe Create Completion/Submission Queue 368 */ 369 typedef union { 370 struct { 371 uint16_t q_qid; /* Queue Identifier */ 372 uint16_t q_qsize; /* Queue Size */ 373 } b; 374 uint32_t r; 375 } nvme_create_queue_dw10_t; 376 377 typedef union { 378 struct { 379 uint16_t cq_pc:1; /* Physically Contiguous */ 380 uint16_t cq_ien:1; /* Interrupts Enabled */ 381 uint16_t cq_rsvd:14; 382 uint16_t cq_iv; /* Interrupt Vector */ 383 } b; 384 uint32_t r; 385 } nvme_create_cq_dw11_t; 386 387 typedef union { 388 struct { 389 uint16_t sq_pc:1; /* Physically Contiguous */ 390 uint16_t sq_qprio:2; /* Queue Priority */ 391 uint16_t sq_rsvd:13; 392 uint16_t sq_cqid; /* Completion Queue ID */ 393 } b; 394 uint32_t r; 395 } nvme_create_sq_dw11_t; 396 397 /* 398 * NVMe Abort Command 399 */ 400 typedef union { 401 struct { 402 uint16_t ac_sqid; /* Submission Queue ID */ 403 uint16_t ac_cid; /* Command ID */ 404 } b; 405 uint32_t r; 406 } nvme_abort_cmd_t; 407 408 /* 409 * NVMe Get Log Page 410 */ 411 typedef union { 412 struct { 413 uint8_t lp_lid; /* Log Page Identifier */ 414 uint8_t lp_rsvd1; 415 uint16_t lp_numd:12; /* Number of Dwords */ 416 uint16_t lp_rsvd2:4; 417 } b; 418 uint32_t r; 419 } nvme_getlogpage_t; 420 421 /* 422 * dword11 values for the dataset management command. Note that the dword11 423 * attributes are distinct from the context attributes (nr_ctxattr) values 424 * for an individual range (of the context attribute values defined by the NVMe 425 * spec, none are currently used by the NVMe driver). 426 */ 427 #define NVME_DSET_MGMT_ATTR_OPT_READ 0x01 428 #define NVME_DSET_MGMT_ATTR_OPT_WRITE 0x02 429 #define NVME_DSET_MGMT_ATTR_DEALLOCATE 0x04 430 431 #define NVME_DSET_MGMT_MAX_RANGES 256 432 typedef struct { 433 uint32_t nr_ctxattr; 434 uint32_t nr_len; 435 uint64_t nr_lba; 436 } nvme_range_t; 437 438 #ifdef __cplusplus 439 } 440 #endif 441 442 #pragma pack() /* pack(1) */ 443 444 #endif /* _NVME_REG_H */ 445