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 * 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 #define NVME_OPC_VENDOR_LOW 0xC0 296 #define NVME_OPC_VENDOR_HIGH 0xFF 297 #define NVME_IS_VENDOR_SPECIFIC_CMD(x) \ 298 ((x) >= NVME_OPC_VENDOR_LOW && (x) <= NVME_OPC_VENDOR_HIGH) 299 300 /* NVMe NVM command set specific admin command opcodes */ 301 #define NVME_OPC_NVM_FORMAT 0x80 302 #define NVME_OPC_NVM_SEC_SEND 0x81 303 #define NVME_OPC_NVM_SEC_RECV 0x82 304 305 /* NVMe NVM command opcodes */ 306 #define NVME_OPC_NVM_FLUSH 0x0 307 #define NVME_OPC_NVM_WRITE 0x1 308 #define NVME_OPC_NVM_READ 0x2 309 #define NVME_OPC_NVM_WRITE_UNC 0x4 310 #define NVME_OPC_NVM_COMPARE 0x5 311 #define NVME_OPC_NVM_WRITE_ZERO 0x8 312 #define NVME_OPC_NVM_DSET_MGMT 0x9 313 #define NVME_OPC_NVM_RESV_REG 0xd 314 #define NVME_OPC_NVM_RESV_REPRT 0xe 315 #define NVME_OPC_NVM_RESV_ACQ 0x11 316 #define NVME_OPC_NVM_RESV_REL 0x12 317 318 /* 319 * NVMe completion queue entry 320 */ 321 typedef struct { 322 uint32_t cqe_dw0; /* Command Specific */ 323 uint32_t cqe_rsvd1; 324 uint16_t cqe_sqhd; /* SQ Head Pointer */ 325 uint16_t cqe_sqid; /* SQ Identifier */ 326 uint16_t cqe_cid; /* Command Identifier */ 327 nvme_cqe_sf_t cqe_sf; /* Status Field */ 328 } nvme_cqe_t; 329 330 /* 331 * NVMe Asynchronous Event Request 332 */ 333 #define NVME_ASYNC_TYPE_ERROR 0x0 /* Error Status */ 334 #define NVME_ASYNC_TYPE_HEALTH 0x1 /* SMART/Health Status */ 335 #define NVME_ASYNC_TYPE_NOTICE 0x2 /* Notice (1.2) */ 336 #define NVME_ASYNC_TYPE_VENDOR 0x7 /* Vendor specific */ 337 338 #define NVME_ASYNC_ERROR_INV_SQ 0x0 /* Invalid Submission Queue */ 339 #define NVME_ASYNC_ERROR_INV_DBL 0x1 /* Invalid Doorbell Write */ 340 #define NVME_ASYNC_ERROR_DIAGFAIL 0x2 /* Diagnostic Failure */ 341 #define NVME_ASYNC_ERROR_PERSISTENT 0x3 /* Persistent Internal Error */ 342 #define NVME_ASYNC_ERROR_TRANSIENT 0x4 /* Transient Internal Error */ 343 #define NVME_ASYNC_ERROR_FW_LOAD 0x5 /* Firmware Image Load Error */ 344 345 #define NVME_ASYNC_HEALTH_RELIABILITY 0x0 /* Device Reliability */ 346 #define NVME_ASYNC_HEALTH_TEMPERATURE 0x1 /* Temp. Above Threshold */ 347 #define NVME_ASYNC_HEALTH_SPARE 0x2 /* Spare Below Threshold */ 348 349 /* NVMe 1.2 */ 350 #define NVME_ASYNC_NOTICE_NS_CHANGE 0x0 /* Namespace attribute change */ 351 #define NVME_ASYNC_NOTICE_FW_ACTIVATE 0x1 /* Firmware activation start */ 352 /* NVMe 1.3 */ 353 #define NVME_ASYNC_NOTICE_TELEMETRY 0x2 /* Telemetry log changed */ 354 /* NVMe 1.4 */ 355 #define NVME_ASYNC_NOTICE_NS_ASYMM 0x3 /* Asymm. NS access change */ 356 #define NVME_ASYNC_NOTICE_LATENCYLOG 0x4 /* Pred. Latency log change */ 357 #define NVME_ASYNC_NOTICE_LBASTATUS 0x5 /* LBA status alert */ 358 #define NVME_ASYNC_NOTICE_ENDURANCELOG 0x6 /* Endurance log change */ 359 360 typedef union { 361 struct { 362 uint8_t ae_type:3; /* Asynchronous Event Type */ 363 uint8_t ae_rsvd1:5; 364 uint8_t ae_info; /* Asynchronous Event Info */ 365 uint8_t ae_logpage; /* Associated Log Page */ 366 uint8_t ae_rsvd2; 367 } b; 368 uint32_t r; 369 } nvme_async_event_t; 370 371 /* 372 * NVMe Create Completion/Submission Queue 373 */ 374 typedef union { 375 struct { 376 uint16_t q_qid; /* Queue Identifier */ 377 uint16_t q_qsize; /* Queue Size */ 378 } b; 379 uint32_t r; 380 } nvme_create_queue_dw10_t; 381 382 typedef union { 383 struct { 384 uint16_t cq_pc:1; /* Physically Contiguous */ 385 uint16_t cq_ien:1; /* Interrupts Enabled */ 386 uint16_t cq_rsvd:14; 387 uint16_t cq_iv; /* Interrupt Vector */ 388 } b; 389 uint32_t r; 390 } nvme_create_cq_dw11_t; 391 392 typedef union { 393 struct { 394 uint16_t sq_pc:1; /* Physically Contiguous */ 395 uint16_t sq_qprio:2; /* Queue Priority */ 396 uint16_t sq_rsvd:13; 397 uint16_t sq_cqid; /* Completion Queue ID */ 398 } b; 399 uint32_t r; 400 } nvme_create_sq_dw11_t; 401 402 /* 403 * NVMe Abort Command 404 */ 405 typedef union { 406 struct { 407 uint16_t ac_sqid; /* Submission Queue ID */ 408 uint16_t ac_cid; /* Command ID */ 409 } b; 410 uint32_t r; 411 } nvme_abort_cmd_t; 412 413 /* 414 * NVMe Get Log Page. dw12/13 are the lower and upper halves of the 64-bit 415 * offset field respectively in bytes. These must be dword aligned. The offset 416 * was added in NVMe v1.2, but requires controller support. 417 */ 418 typedef union { 419 struct { 420 uint8_t lp_lid; /* Log Page Identifier */ 421 /* 422 * The log-specific field was introduced as a 4-bit field in 423 * NVMe 1.3. It was extended to be a 7-bit field in NVMe 2.0 and 424 * renamed log-specific parameter. 425 */ 426 uint8_t lp_lsp:7; 427 uint8_t lp_rae:1; /* Retain Async Event v1.3 */ 428 /* 429 * This is the lower number of dwords. This was changed in NVMe 430 * v1.2 to be split between this field and dw11. In NVMe 1.0/1.1 431 * this was only 12 bits long. 432 */ 433 uint16_t lp_lnumdl; /* Number of Dwords */ 434 } b; 435 uint32_t r; 436 } nvme_getlogpage_dw10_t; 437 438 typedef union { 439 struct { 440 uint16_t lp_numdu; /* Number of dwords v1.2 */ 441 uint16_t lp_lsi; /* Log Specific Field v1.3 */ 442 } b; 443 uint32_t r; 444 } nvme_getlogpage_dw11_t; 445 446 typedef union { 447 struct { 448 uint8_t lp_uuid:7; /* UUID Index v1.4 */ 449 uint8_t lp_rsvd1:1; 450 uint8_t lp_rsvd2; 451 uint8_t lp_rsvd3:7; 452 uint8_t lp_ot:1; /* Offset Type v2.0 */ 453 uint8_t lp_csi; /* Command Set Identifier v2.0 */ 454 } b; 455 uint32_t r; 456 } nvme_getlogpage_dw14_t; 457 458 /* 459 * dword11 values for the dataset management command. Note that the dword11 460 * attributes are distinct from the context attributes (nr_ctxattr) values 461 * for an individual range (of the context attribute values defined by the NVMe 462 * spec, none are currently used by the NVMe driver). 463 */ 464 #define NVME_DSET_MGMT_ATTR_OPT_READ 0x01 465 #define NVME_DSET_MGMT_ATTR_OPT_WRITE 0x02 466 #define NVME_DSET_MGMT_ATTR_DEALLOCATE 0x04 467 468 #define NVME_DSET_MGMT_MAX_RANGES 256 469 typedef struct { 470 uint32_t nr_ctxattr; 471 uint32_t nr_len; 472 uint64_t nr_lba; 473 } nvme_range_t; 474 475 /* 476 * NVMe Identify Command 477 */ 478 typedef union { 479 struct { 480 /* 481 * The controller or namespace structure (CNS). This field was 482 * originally a single bit wide in NVMe 1.0. It was two bits 483 * wide in NVMe 1.1 and was increased to 8 bits in NVMe 1.2. 484 */ 485 uint8_t id_cns; 486 uint8_t id_rsvd0; 487 uint16_t id_cntid; /* Controller ID, NVMe 1.2 */ 488 } b; 489 uint32_t r; 490 } nvme_identify_dw10_t; 491 492 #ifdef __cplusplus 493 } 494 #endif 495 496 #pragma pack() /* pack(1) */ 497 498 #endif /* _NVME_REG_H */ 499