// NVMe datastructures and constants // // Copyright 2017 Amazon.com, Inc. or its affiliates. // // This file may be distributed under the terms of the GNU LGPLv3 license. #ifndef __NVME_INT_H #define __NVME_INT_H #include "types.h" // u32 #include "pcidevice.h" // struct pci_device /* Data structures */ /* The register file of a NVMe host controller. This struct follows the naming scheme in the NVMe specification. */ struct nvme_reg { u64 cap; /* controller capabilities */ u32 vs; /* version */ u32 intms; /* interrupt mask set */ u32 intmc; /* interrupt mask clear */ u32 cc; /* controller configuration */ u32 _res0; u32 csts; /* controller status */ u32 _res1; u32 aqa; /* admin queue attributes */ u64 asq; /* admin submission queue base address */ u64 acq; /* admin completion queue base address */ }; /* Submission queue entry */ struct nvme_sqe { union { u32 dword[16]; struct { u32 cdw0; /* Command DWORD 0 */ u32 nsid; /* Namespace ID */ u64 _res0; u64 mptr; /* metadata ptr */ u64 dptr_prp1; u64 dptr_prp2; }; }; }; /* Completion queue entry */ struct nvme_cqe { union { u32 dword[4]; struct { u32 cdw0; u32 _res0; u16 sq_head; u16 sq_id; u16 cid; u16 status; }; }; }; /* The common part of every submission or completion queue. */ struct nvme_queue { u32 *dbl; /* doorbell */ u16 mask; /* length - 1 */ }; struct nvme_cq { struct nvme_queue common; struct nvme_cqe *cqe; /* We have read upto (but not including) this entry in the queue. */ u16 head; /* The current phase bit the controller uses to indicate that it has written a new entry. This is inverted after each wrap. */ unsigned phase : 1; }; struct nvme_sq { struct nvme_queue common; struct nvme_sqe *sqe; /* Corresponding completion queue. We only support a single SQ per CQ. */ struct nvme_cq *cq; /* The last entry the controller has fetched. */ u16 head; /* The last value we have written to the tail doorbell. */ u16 tail; }; struct nvme_ctrl { struct pci_device *pci; struct nvme_reg volatile *reg; u32 doorbell_stride; /* in bytes */ struct nvme_sq admin_sq; struct nvme_cq admin_cq; u32 ns_count; struct nvme_sq io_sq; struct nvme_cq io_cq; }; struct nvme_namespace { struct drive_s drive; struct nvme_ctrl *ctrl; u32 ns_id; u64 lba_count; /* The total amount of sectors. */ u32 block_size; u32 metadata_size; u32 max_req_size; }; /* Data structures for NVMe admin identify commands */ struct nvme_identify_ctrl { u16 vid; u16 ssvid; char sn[20]; char mn[40]; char fr[8]; u8 rab; u8 ieee[3]; u8 cmic; u8 mdts; char _boring[516 - 78]; u32 nn; /* number of namespaces */ }; struct nvme_identify_ns_list { u32 ns_id[1024]; }; struct nvme_lba_format { u16 ms; u8 lbads; u8 rp; u8 res; }; struct nvme_identify_ns { u64 nsze; u64 ncap; u64 nuse; u8 nsfeat; u8 nlbaf; u8 flbas; char _boring[128 - 27]; struct nvme_lba_format lbaf[16]; }; union nvme_identify { struct nvme_identify_ns ns; struct nvme_identify_ctrl ctrl; struct nvme_identify_ns_list ns_list; }; /* NVMe constants */ #define NVME_CAP_CSS_NVME (1ULL << 37) #define NVME_CSTS_FATAL (1U << 1) #define NVME_CSTS_RDY (1U << 0) #define NVME_CC_EN (1U << 0) #define NVME_SQE_OPC_ADMIN_CREATE_IO_SQ 1U #define NVME_SQE_OPC_ADMIN_CREATE_IO_CQ 5U #define NVME_SQE_OPC_ADMIN_IDENTIFY 6U #define NVME_SQE_OPC_IO_WRITE 1U #define NVME_SQE_OPC_IO_READ 2U #define NVME_ADMIN_IDENTIFY_CNS_ID_NS 0U #define NVME_ADMIN_IDENTIFY_CNS_ID_CTRL 1U #define NVME_ADMIN_IDENTIFY_CNS_GET_NS_LIST 2U #define NVME_CQE_DW3_P (1U << 16) #define NVME_PAGE_SIZE 4096 #define NVME_PAGE_MASK ~(NVME_PAGE_SIZE - 1) /* Length for the queue entries. */ #define NVME_SQE_SIZE_LOG 6 #define NVME_CQE_SIZE_LOG 4 #endif /* EOF */