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