// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #pragma once #include #include // Registers in PCIE BAR0 MMIO Space #define NVME_REG_CAP 0x00 // Capabilities #define NVME_REG_VS 0x08 // Version #define NVME_REG_INTMS 0x0C // Interrupt Mask Set #define NVME_REG_INTMC 0x10 // Interrupt Mask clear #define NVME_REG_CC 0x14 // Controller Configuration #define NVME_REG_CSTS 0x1C // Controller Status #define NVME_REG_NSSR 0x20 // NVM Subsystem Reset (Optional) #define NVME_REG_AQA 0x24 // Admin Queue Attributes #define NVME_REG_ASQ 0x28 // Admin Submission Queue Base Addr #define NVME_REG_ACQ 0x30 // Admin Completion Queue Base Addr #define NVME_REG_CMBLOC 0x38 // Controller Memory Block Location (Optional) #define NVME_REG_CMBSZ 0x3C // Controller Memory Block Size (Optional) // Submission/Completion Queue Tail/Head are computed based on capabilities #define NVME_REG_SQnTDBL(n, cap) (0x1000 + (2*(n) + 0) * (4 << (NVME_CAP_DSTRD(cap) - 2))) #define NVME_REG_CQnHDBL(n, cap) (0x1000 + (2*(n) + 1) * (4 << (NVME_CAP_DSTRD(cap) - 2))) #define NVME_CAP_MPSMAX(n) ((((n) >> 52) & 0xF) + 12) // 2^x bytes #define NVME_CAP_MPSMIN(n) ((((n) >> 48) & 0xF) + 12) // 2^x bytes #define NVME_CAP_BPS(n) (((n) >> 45) & 1) #define NVME_CAP_CSS_NVM(n) (((n) >> 37) & 1) #define NVME_CAP_NSSRS(n) (((n) >> 36) & 1) #define NVME_CAP_DSTRD(n) ((((n) >> 32) & 0xF) + 2) // 2^x bytes #define NVME_CAP_TO(n) ((((n) >> 24) & 0xFF) * 500) // milliseconds #define NVME_CAP_AMS_WRR(n) (((n) >> 17) & 1) #define NVME_CAP_AMS_VS(n) (((n) >> 18) & 1) #define NVME_CAP_CQR(n) (((n) >> 16) & 1) #define NVME_CAP_MQES(n) ((n) & 0xFFFF) #define NVME_CC_IOCQES(n) (((n) & 0xF) << 20) // IO Completion Entry Size 2^n #define NVME_CC_IOSQES(n) (((n) & 0xF) << 16) // IO Submission Entry Size 2^n #define NVME_CC_SHN_NORMAL (1 << 14) // Request Normal Shutdown #define NVME_CC_SHN_ABRUPT (2 << 14) // Request Abrupt Shutdown #define NVME_CC_SHN_MASK (3 << 14) #define NVME_CC_AMS_RR (0 << 11) // Arbitration: Round-Robin #define NVME_CC_AMS_WRR (1 << 11) // Arbitration: Weighted-Round-Robin #define NVME_CC_AMS_VS (7 << 11) // Arbitration: Vendor Specific #define NVME_CC_MPS(n) (((n) & 0xF) << 7) // Memory Page Size (2^(n + 12)) #define NVME_CC_EN (1 << 0) // Enable #define NVME_CSTS_PP (1 << 5) // Processing Paused #define NVME_CSTS_NSSRO (1 << 4) // Subsystem Reset Occurred (W1C) #define NVME_CSTS_SHN_MASK (3 << 2) #define NVME_CSTS_SHN_NORMAL_OP (0 << 2) // not shutting done #define NVME_CSTS_SHN_IN_PROGRESS (1 << 2) // Shutdown is in progress #define NVME_CSTS_SHN_COMPLETE (2 << 2) // Shutdown is complete #define NVME_CSTS_CFS (1 << 1) // Controller Fatal Status #define NVME_CSTS_RDY (1 << 0) // Ready #define NVME_AQA_ACQS(n) (((n) & 0xFFF) << 16) // Admin Completion Queue Size #define NVME_AQA_ASQS(n) (((n) & 0xFFF) << 0) // Admin Submission Queue Size // Completion Queue Entry typedef struct { uint32_t cmd; uint32_t reserved; uint16_t sq_head; uint16_t sq_id; uint16_t cmd_id; uint16_t status; } nvme_cpl_t; #define NVME_CPL_SIZE 16 #define NVME_CPL_SHIFT 4 static_assert(sizeof(nvme_cpl_t) == NVME_CPL_SIZE, ""); static_assert(sizeof(nvme_cpl_t) == (1 << NVME_CPL_SHIFT), ""); #define NVME_CPL_STATUS_CODE(n) (((n) >> 1) & 0x7FF) // Submission Queue Entry typedef struct { uint32_t cmd; uint32_t nsid; uint64_t reserved; uint64_t mptr; union { uint64_t prp[2]; } dptr; union { uint32_t raw[6]; struct { uint64_t start_lba; uint16_t block_count; // minus 1 uint16_t flags; uint32_t dsm; uint32_t eilbrt; uint32_t elbat; } rw; } u; } nvme_cmd_t; #define NVME_CMD_SIZE 64 #define NVME_CMD_SHIFT 6 static_assert(sizeof(nvme_cmd_t) == NVME_CMD_SIZE, ""); static_assert(sizeof(nvme_cmd_t) == (1 << NVME_CMD_SHIFT), ""); // Common #define NVME_CMD_CID(n) (((n) & 0xFFFF) << 16) #define NVME_CMD_PRP (0 << 14) // dptr uses PRP, mptr is raw addr #define NVME_CMD_SGL (1 << 14) // dptr uses SGL, mptr is raw addr #define NVME_CMD_SGL_MSGL (2 << 14) // dptr uses SGL, mptr points at SGL[1] #define NVME_CMD_NORMAL (0 << 8) // non-fused command #define NVME_CMD_FUSED_1ST (1 << 8) // 1st part of fused command #define NVME_CMD_FUSED_2ND (2 << 8) // 2nd part of fused command #define NVME_CMD_OPC(n) ((n) & 0xFF) // Admin Opcodes #define NVME_ADMIN_OP_DELETE_IOSQ 0x00 #define NVME_ADMIN_OP_CREATE_IOSQ 0x01 #define NVME_ADMIN_OP_DELETE_IOCQ 0x04 #define NVME_ADMIN_OP_CREATE_IOCQ 0x05 #define NVME_ADMIN_OP_IDENTIFY 0x06 #define NVME_ADMIN_OP_ABORT 0x08 #define NVME_ADMIN_OP_SET_FEATURE 0x09 #define NVME_ADMIN_OP_GET_FEATURE 0x0A #define NVME_ADMIN_OP_ASYNC_EVENT 0x0C #define NVME_FEATURE_SEL_CURRENT (0 << 8) #define NVME_FEATURE_SEL_DEFAULT (1 << 8) #define NVME_FEATURE_SEL_SAVED (2 << 8) #define NVME_FEATURE_SEL_SUPPORTED (3 << 8) #define NVME_FEATURE_NUMBER_OF_QUEUES 0x07 #define NVME_LBAFMT_RP(n) (((n) >> 24) & 3) #define NVME_LBAFMT_LBADS(n) (((n) >> 16) & 0xFF) // 2^n bytes #define NVME_LBAFMT_MS(n) ((n) & 0xFFFF) // NVM Opcodes #define NVME_OP_FLUSH 0x00 #define NVME_OP_WRITE 0x01 #define NVME_OP_READ 0x02 #define NVME_RW_FLAG_LR (1 << 15) #define NVME_RW_FLAG_FUA (1 << 14) // Identify Page for Controllers typedef struct { uint32_t w[8]; } nvme_psd_t; typedef struct { //--------------------- // Controller Capabilities and Features uint16_t VID; // PCI Vendor ID uint16_t SSVID; // PCI Subsystem Vendor ID uint8_t SN[20]; // Serial Number uint8_t MN[40]; // Model Number uint8_t FR[8]; // Firmware Revision uint8_t RAB; // Recommended Arbitrartion Burst uint8_t IEEE[3]; // IEEE OUI Identifier uint8_t CMIC; // Controller Multi-Path IO and Namespace Sharing Caps uint8_t MDTS; // Maximum Data Transfer Size uint16_t CNTLID; // Controller ID uint32_t VER; // Version uint32_t RTD3R; // RTD3 Resume Latency (uS) uint32_t RTD3E; // RTD3 ENtry Latency (uS) uint32_t OAES; // Optional Asynch Events Supported; uint32_t CTRATT; // Controller Attributes uint8_t zz0[12]; // Reserved uint8_t FGUID[16]; // Field Replaceable Unit GUID uint8_t zz1[112]; // Reserved uint8_t zz2[16]; // Refer to NVMe MI Spec // -------------------- // Admin Command Set Attributes and Capabilities uint16_t OACS; // Optional Admin Command Support uint8_t ACL; // Abort Command Limit uint8_t AERL; // Async Event Request Limit uint8_t FRMW; // Firmware Updates uint8_t LPA; // Log Page Attributes; uint8_t ELPE; // Error Log Page Entries uint8_t NPSS; // Number of Power States Supported uint8_t AVSCC; // Admin Vendor Specific Command Config uint8_t APSTA; // Autonomous Power State Transition Attrs uint16_t WCTEMP; // Warning Composite Temp Threshold uint16_t CCTEMP; // Critical Composite Temp Threshold uint16_t MTFA; // Max Time for Firmware Activation (x 100mS, 0 = undef) uint32_t HMPRE; // Host Memory Buffer Preferred Size (4K pages) uint32_t HMMIN; // Host Memory Buffer Minimum Size (4K pages) uint64_t TNVMCAP_LO; // Total NVM Capacity (bytes) uint64_t TNVMCAP_HI; uint64_t UNVMCAP_LO; // Unallocated NVM Capacity (bytes) uint64_t UNVMCAP_HI; uint32_t RPMBS; // Replay Protected Memory Block Support uint16_t EDSTT; // Extended Device SelfTest Time uint8_t DSTO; // Devcie SelfTest Options uint8_t FWUG; // Firmware Upgreade Granularity uint16_t KAS; // Keep Alive Support uint16_t HCTMA; // Host Controlled Thermal Management Attrs uint16_t MNTMT; // Minimum Thermal Management Temp uint16_t MXTMT; // Maximum Thermal Management Temp uint32_t SANICAP; // Sanitize Capabilities uint8_t zz3[180]; // Reserved // -------------------- // NVM Command Set Attributes uint8_t SQES; // Submission Queue Entry Size uint8_t CQES; // Completion Queue Entry Size uint16_t MAXCMD; // Max Outstanding Commands uint32_t NN; // Number of Namespaces uint16_t ONCS; // Optional NVM Command Support uint16_t FUSES; // Fused Operation Support uint8_t FNA; // Format NVM Attributes uint8_t VWC; // Volatile Write Cache uint16_t AWUN; // Atomic Write Unit Normal uint16_t AWUPF; // Atomic Write Unit Power Fail uint8_t NVSCC; // NVM Vendor Specific Command Config uint8_t zz4; // Reserved uint16_t ACWU; // Atomic Compare and Write Unit uint16_t zz5; // Reserved uint32_t SGLS; // Scatter Gather List Support uint8_t zz6[228]; // Reserved uint8_t SUBNQN[256]; // NVM Subsystem NVMe Qualified Name uint8_t zz7[768]; // Reserved uint8_t zz8[256]; // Refer to NVME over Fabrics Spec // -------------------- // Power State Descriptors nvme_psd_t PSD[32]; // -------------------- // Vendor Specific uint8_t vendor[1024]; } nvme_identify_t; static_assert(sizeof(nvme_identify_t) == 4096, ""); #define OACS_DOORBELL_BUFFER_CONFIG (1 << 8) #define OACS_VIRTUALIZATION_MANAGEMENT (1 << 7) #define OACS_NVME_MI_SEND_RECV (1 << 6) #define OACS_DIRECTIVE_SEND_RECV (1 << 5) #define OACS_DEVICE_SELF_TEST (1 << 4) #define OACS_NAMESPACE_MANAGEMENT (1 << 3) #define OACS_FIRMWARE_DOWNLOAD_COMMIT (1 << 2) #define OACS_FORMAT_NVM (1 << 1) #define OACS_SECURITY_SEND_RECV (1 << 0) #define ONCS_TIMESTAMP (1 << 6) #define ONCS_RESERVATIONS (1 << 5) #define ONCS_SAVE_SELECT_NONZERO (1 << 4) #define ONCS_WRITE_ZEROES (1 << 3) #define ONCS_DATASET_MANAGEMENT (1 << 2) #define ONCS_WRITE_UNCORRECTABLE (1 << 1) #define ONCS_COMPARE (1 << 0) // Identify Page for Namespaces #define NSFEAT_GUIDS_NOT_REUSED (1 << 3) #define NSFEAT_DEALLOC_BLOCK_ERROR (1 << 2) #define NSFEAT_LOCAL_ATOMIC_SIZES (1 << 1) #define NSFEAT_THING_PROVISIONING (1 << 0) typedef struct { // -------------------- // Vendor Specific uint64_t NSSZ; // Namespace Size (blocks) uint64_t NCAP; // Namespace Capacity (blocks) uint64_t NUSE; // Namespace Utilization (blocks) uint8_t NSFEAT; // Namespace Features uint8_t NLBAF; // Number of LBA Formats uint8_t FLBAS; // Formatted LBA Size uint8_t MC; // Metadata Capabilities uint8_t DPC; // End-to-End Data Protection Capabilities uint8_t DPS; // End-to-End Data Protection Type Settings uint8_t NMIC; // Namespace MultiPath IO and Sharing Caps uint8_t RESCAP; // Reservation Capabilities uint8_t FPI; // Format Progress Indicator uint8_t DLFEAT; // Deallocate Logical Block Features uint16_t NAWUN; // Namespace Atomic Write Unit Normal uint16_t NAWUPF; // Namespace Atomic Write Unit Power Fail uint16_t NACWUN; // Namespace Atomic Compare and Write Unit uint16_t NABSN; // Namespace Atomic Boundary Size Normal uint16_t NABO; // Namespace Atomic Boundary Offset uint16_t NABSPF; // Namespace Atomic Boundary Size Power Fail uint16_t NOIOB; // Namespace Optimal IO Boundary uint64_t NVMCAP_LO; // NVM Capacity (bytes) uint64_t NVMCAP_HI; uint8_t zz0[40]; // Reserved uint8_t NGUID[16]; // Namespace GUID uint8_t EUI64[8]; // IEEE Extended Unique Identifier uint32_t LBAF[16]; // LBA Format Support 0..15 uint8_t zz1[192]; // Reserved uint8_t zz2[3712]; // Reserved } nvme_identify_ns_t; static_assert(sizeof(nvme_identify_ns_t) == 4096, ""); #define NSFEAT_GUIDS_NOT_REUSED (1 << 3) #define NSFEAT_DEALLOC_BLOCK_ERROR (1 << 2) #define NSFEAT_LOCAL_ATOMIC_SIZES (1 << 1) #define NSFEAT_THING_PROVISIONING (1 << 0)