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 * Copyright 2020 Joyent, Inc. 15 * Copyright 2019 Western Digital Corporation 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_VENDOR 0x7 /* vendor specific */ 331 332 #define NVME_ASYNC_ERROR_INV_SQ 0x0 /* Invalid Submission Queue */ 333 #define NVME_ASYNC_ERROR_INV_DBL 0x1 /* Invalid Doorbell Write */ 334 #define NVME_ASYNC_ERROR_DIAGFAIL 0x2 /* Diagnostic Failure */ 335 #define NVME_ASYNC_ERROR_PERSISTENT 0x3 /* Persistent Internal Error */ 336 #define NVME_ASYNC_ERROR_TRANSIENT 0x4 /* Transient Internal Error */ 337 #define NVME_ASYNC_ERROR_FW_LOAD 0x5 /* Firmware Image Load Error */ 338 339 #define NVME_ASYNC_HEALTH_RELIABILITY 0x0 /* Device Reliability */ 340 #define NVME_ASYNC_HEALTH_TEMPERATURE 0x1 /* Temp. Above Threshold */ 341 #define NVME_ASYNC_HEALTH_SPARE 0x2 /* Spare Below Threshold */ 342 343 typedef union { 344 struct { 345 uint8_t ae_type:3; /* Asynchronous Event Type */ 346 uint8_t ae_rsvd1:5; 347 uint8_t ae_info; /* Asynchronous Event Info */ 348 uint8_t ae_logpage; /* Associated Log Page */ 349 uint8_t ae_rsvd2; 350 } b; 351 uint32_t r; 352 } nvme_async_event_t; 353 354 /* 355 * NVMe Create Completion/Submission Queue 356 */ 357 typedef union { 358 struct { 359 uint16_t q_qid; /* Queue Identifier */ 360 uint16_t q_qsize; /* Queue Size */ 361 } b; 362 uint32_t r; 363 } nvme_create_queue_dw10_t; 364 365 typedef union { 366 struct { 367 uint16_t cq_pc:1; /* Physically Contiguous */ 368 uint16_t cq_ien:1; /* Interrupts Enabled */ 369 uint16_t cq_rsvd:14; 370 uint16_t cq_iv; /* Interrupt Vector */ 371 } b; 372 uint32_t r; 373 } nvme_create_cq_dw11_t; 374 375 typedef union { 376 struct { 377 uint16_t sq_pc:1; /* Physically Contiguous */ 378 uint16_t sq_qprio:2; /* Queue Priority */ 379 uint16_t sq_rsvd:13; 380 uint16_t sq_cqid; /* Completion Queue ID */ 381 } b; 382 uint32_t r; 383 } nvme_create_sq_dw11_t; 384 385 /* 386 * NVMe Identify 387 */ 388 389 /* NVMe Identify parameters (cdw10) */ 390 #define NVME_IDENTIFY_NSID 0x0 /* Identify Namespace */ 391 #define NVME_IDENTIFY_CTRL 0x1 /* Identify Controller */ 392 #define NVME_IDENTIFY_LIST 0x2 /* Identify List Namespaces */ 393 394 #define NVME_IDENTIFY_NSID_ALLOC_LIST 0x10 /* List Allocated NSID */ 395 #define NVME_IDENTIFY_NSID_ALLOC 0x11 /* Identify Allocated NSID */ 396 #define NVME_IDENTIFY_NSID_CTRL_LIST 0x12 /* List Controllers on NSID */ 397 #define NVME_IDENTIFY_CTRL_LIST 0x13 /* Controller List */ 398 #define NVME_IDENTIFY_PRIMARY_CAPS 0x14 /* Primary Controller Caps */ 399 400 /* 401 * NVMe Abort Command 402 */ 403 typedef union { 404 struct { 405 uint16_t ac_sqid; /* Submission Queue ID */ 406 uint16_t ac_cid; /* Command ID */ 407 } b; 408 uint32_t r; 409 } nvme_abort_cmd_t; 410 411 412 /* 413 * NVMe Get Log Page 414 */ 415 typedef union { 416 struct { 417 uint8_t lp_lid; /* Log Page Identifier */ 418 uint8_t lp_rsvd1; 419 uint16_t lp_numd:12; /* Number of Dwords */ 420 uint16_t lp_rsvd2:4; 421 } b; 422 uint32_t r; 423 } nvme_getlogpage_t; 424 425 /* 426 * dword11 values for the dataset management command. Note that the dword11 427 * attributes are distinct from the context attributes (nr_ctxattr) values 428 * for an individual range (of the context attribute values defined by the NVMe 429 * spec, none are currently used by the NVMe driver). 430 */ 431 #define NVME_DSET_MGMT_ATTR_OPT_READ 0x01 432 #define NVME_DSET_MGMT_ATTR_OPT_WRITE 0x02 433 #define NVME_DSET_MGMT_ATTR_DEALLOCATE 0x04 434 435 #define NVME_DSET_MGMT_MAX_RANGES 256 436 typedef struct { 437 uint32_t nr_ctxattr; 438 uint32_t nr_len; 439 uint64_t nr_lba; 440 } nvme_range_t; 441 442 #ifdef __cplusplus 443 } 444 #endif 445 446 #pragma pack() /* pack(1) */ 447 448 #endif /* _NVME_REG_H */ 449