1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#pragma once
6
7#include <assert.h>
8#include <stdint.h>
9
10// Registers in PCIE BAR0 MMIO Space
11#define NVME_REG_CAP              0x00 // Capabilities
12#define NVME_REG_VS               0x08 // Version
13#define NVME_REG_INTMS            0x0C // Interrupt Mask Set
14#define NVME_REG_INTMC            0x10 // Interrupt Mask clear
15#define NVME_REG_CC               0x14 // Controller Configuration
16#define NVME_REG_CSTS             0x1C // Controller Status
17#define NVME_REG_NSSR             0x20 // NVM Subsystem Reset (Optional)
18#define NVME_REG_AQA              0x24 // Admin Queue Attributes
19#define NVME_REG_ASQ              0x28 // Admin Submission Queue Base Addr
20#define NVME_REG_ACQ              0x30 // Admin Completion Queue Base Addr
21#define NVME_REG_CMBLOC           0x38 // Controller Memory Block Location (Optional)
22#define NVME_REG_CMBSZ            0x3C // Controller Memory Block Size (Optional)
23
24// Submission/Completion Queue Tail/Head are computed based on capabilities
25#define NVME_REG_SQnTDBL(n, cap)  (0x1000 + (2*(n) + 0) * (4 << (NVME_CAP_DSTRD(cap) - 2)))
26#define NVME_REG_CQnHDBL(n, cap)  (0x1000 + (2*(n) + 1) * (4 << (NVME_CAP_DSTRD(cap) - 2)))
27
28#define NVME_CAP_MPSMAX(n)        ((((n) >> 52) & 0xF) + 12)   // 2^x bytes
29#define NVME_CAP_MPSMIN(n)        ((((n) >> 48) & 0xF) + 12)   // 2^x bytes
30#define NVME_CAP_BPS(n)           (((n) >> 45) & 1)
31#define NVME_CAP_CSS_NVM(n)       (((n) >> 37) & 1)
32#define NVME_CAP_NSSRS(n)         (((n) >> 36) & 1)
33#define NVME_CAP_DSTRD(n)         ((((n) >> 32) & 0xF) + 2)    // 2^x bytes
34#define NVME_CAP_TO(n)            ((((n) >> 24) & 0xFF) * 500)   // milliseconds
35#define NVME_CAP_AMS_WRR(n)       (((n) >> 17) & 1)
36#define NVME_CAP_AMS_VS(n)        (((n) >> 18) & 1)
37#define NVME_CAP_CQR(n)           (((n) >> 16) & 1)
38#define NVME_CAP_MQES(n)          ((n) & 0xFFFF)
39
40#define NVME_CC_IOCQES(n)         (((n) & 0xF) << 20) // IO Completion Entry Size 2^n
41#define NVME_CC_IOSQES(n)         (((n) & 0xF) << 16) // IO Submission Entry Size 2^n
42#define NVME_CC_SHN_NORMAL        (1 << 14) // Request Normal Shutdown
43#define NVME_CC_SHN_ABRUPT        (2 << 14) // Request Abrupt Shutdown
44#define NVME_CC_SHN_MASK          (3 << 14)
45#define NVME_CC_AMS_RR            (0 << 11) // Arbitration: Round-Robin
46#define NVME_CC_AMS_WRR           (1 << 11) // Arbitration: Weighted-Round-Robin
47#define NVME_CC_AMS_VS            (7 << 11) // Arbitration: Vendor Specific
48#define NVME_CC_MPS(n)            (((n) & 0xF) << 7) // Memory Page Size (2^(n + 12))
49#define NVME_CC_EN                (1 << 0) // Enable
50
51#define NVME_CSTS_PP              (1 << 5)  // Processing Paused
52#define NVME_CSTS_NSSRO           (1 << 4)  // Subsystem Reset Occurred (W1C)
53#define NVME_CSTS_SHN_MASK        (3 << 2)
54#define NVME_CSTS_SHN_NORMAL_OP   (0 << 2)  // not shutting done
55#define NVME_CSTS_SHN_IN_PROGRESS (1 << 2)  // Shutdown is in progress
56#define NVME_CSTS_SHN_COMPLETE    (2 << 2)  // Shutdown is complete
57#define NVME_CSTS_CFS             (1 << 1)  // Controller Fatal Status
58#define NVME_CSTS_RDY             (1 << 0)  // Ready
59
60#define NVME_AQA_ACQS(n)          (((n) & 0xFFF) << 16) // Admin Completion Queue Size
61#define NVME_AQA_ASQS(n)          (((n) & 0xFFF) << 0)  // Admin Submission Queue Size
62
63
64// Completion Queue Entry
65typedef struct {
66    uint32_t cmd;
67    uint32_t reserved;
68    uint16_t sq_head;
69    uint16_t sq_id;
70    uint16_t cmd_id;
71    uint16_t status;
72} nvme_cpl_t;
73
74#define NVME_CPL_SIZE 16
75#define NVME_CPL_SHIFT 4
76static_assert(sizeof(nvme_cpl_t) == NVME_CPL_SIZE, "");
77static_assert(sizeof(nvme_cpl_t) == (1 << NVME_CPL_SHIFT), "");
78
79#define NVME_CPL_STATUS_CODE(n) (((n) >> 1) & 0x7FF)
80
81
82// Submission Queue Entry
83typedef struct {
84    uint32_t cmd;
85    uint32_t nsid;
86    uint64_t reserved;
87    uint64_t mptr;
88    union {
89        uint64_t prp[2];
90    } dptr;
91    union {
92        uint32_t raw[6];
93        struct {
94            uint64_t start_lba;
95            uint16_t block_count; // minus 1
96            uint16_t flags;
97            uint32_t dsm;
98            uint32_t eilbrt;
99            uint32_t elbat;
100        } rw;
101    } u;
102} nvme_cmd_t;
103
104#define NVME_CMD_SIZE 64
105#define NVME_CMD_SHIFT 6
106static_assert(sizeof(nvme_cmd_t) == NVME_CMD_SIZE, "");
107static_assert(sizeof(nvme_cmd_t) == (1 << NVME_CMD_SHIFT), "");
108
109// Common
110#define NVME_CMD_CID(n)    (((n) & 0xFFFF) << 16)
111
112#define NVME_CMD_PRP       (0 << 14) // dptr uses PRP, mptr is raw addr
113#define NVME_CMD_SGL       (1 << 14) // dptr uses SGL, mptr is raw addr
114#define NVME_CMD_SGL_MSGL  (2 << 14) // dptr uses SGL, mptr points at SGL[1]
115
116#define NVME_CMD_NORMAL    (0 << 8) // non-fused command
117#define NVME_CMD_FUSED_1ST (1 << 8) // 1st part of fused command
118#define NVME_CMD_FUSED_2ND (2 << 8) // 2nd part of fused command
119
120#define NVME_CMD_OPC(n)    ((n) & 0xFF)
121
122
123
124// Admin Opcodes
125#define NVME_ADMIN_OP_DELETE_IOSQ   0x00
126#define NVME_ADMIN_OP_CREATE_IOSQ   0x01
127#define NVME_ADMIN_OP_DELETE_IOCQ   0x04
128#define NVME_ADMIN_OP_CREATE_IOCQ   0x05
129#define NVME_ADMIN_OP_IDENTIFY      0x06
130#define NVME_ADMIN_OP_ABORT         0x08
131#define NVME_ADMIN_OP_SET_FEATURE   0x09
132#define NVME_ADMIN_OP_GET_FEATURE   0x0A
133#define NVME_ADMIN_OP_ASYNC_EVENT   0x0C
134
135#define NVME_FEATURE_SEL_CURRENT   (0 << 8)
136#define NVME_FEATURE_SEL_DEFAULT   (1 << 8)
137#define NVME_FEATURE_SEL_SAVED     (2 << 8)
138#define NVME_FEATURE_SEL_SUPPORTED (3 << 8)
139
140#define NVME_FEATURE_NUMBER_OF_QUEUES 0x07
141
142
143#define NVME_LBAFMT_RP(n)      (((n) >> 24) & 3)
144#define NVME_LBAFMT_LBADS(n)   (((n) >> 16) & 0xFF)  // 2^n bytes
145#define NVME_LBAFMT_MS(n)      ((n) & 0xFFFF)
146
147// NVM Opcodes
148#define NVME_OP_FLUSH       0x00
149#define NVME_OP_WRITE       0x01
150#define NVME_OP_READ        0x02
151
152#define NVME_RW_FLAG_LR     (1 << 15)
153#define NVME_RW_FLAG_FUA    (1 << 14)
154
155
156// Identify Page for Controllers
157typedef struct {
158    uint32_t w[8];
159} nvme_psd_t;
160
161typedef struct {
162    //--------------------- // Controller Capabilities and Features
163    uint16_t VID;           // PCI Vendor ID
164    uint16_t SSVID;         // PCI Subsystem Vendor ID
165    uint8_t  SN[20];        // Serial Number
166    uint8_t  MN[40];        // Model Number
167    uint8_t  FR[8];         // Firmware Revision
168    uint8_t  RAB;           // Recommended Arbitrartion Burst
169    uint8_t  IEEE[3];       // IEEE OUI Identifier
170    uint8_t  CMIC;          // Controller Multi-Path IO and Namespace Sharing Caps
171    uint8_t  MDTS;          // Maximum Data Transfer Size
172    uint16_t CNTLID;        // Controller ID
173    uint32_t VER;           // Version
174    uint32_t RTD3R;         // RTD3 Resume Latency (uS)
175    uint32_t RTD3E;         // RTD3 ENtry Latency (uS)
176    uint32_t OAES;          // Optional Asynch Events Supported;
177    uint32_t CTRATT;        // Controller Attributes
178    uint8_t  zz0[12];       // Reserved
179    uint8_t  FGUID[16];     // Field Replaceable Unit GUID
180    uint8_t  zz1[112];      // Reserved
181    uint8_t  zz2[16];       // Refer to NVMe MI Spec
182
183    // -------------------- // Admin Command Set Attributes and Capabilities
184    uint16_t OACS;          // Optional Admin Command Support
185    uint8_t  ACL;           // Abort Command Limit
186    uint8_t  AERL;          // Async Event Request Limit
187    uint8_t  FRMW;          // Firmware Updates
188    uint8_t  LPA;           // Log Page Attributes;
189    uint8_t  ELPE;          // Error Log Page Entries
190    uint8_t  NPSS;          // Number of Power States Supported
191    uint8_t  AVSCC;         // Admin Vendor Specific Command Config
192    uint8_t  APSTA;         // Autonomous Power State Transition Attrs
193    uint16_t WCTEMP;        // Warning Composite Temp Threshold
194    uint16_t CCTEMP;        // Critical Composite Temp Threshold
195    uint16_t MTFA;          // Max Time for Firmware Activation (x 100mS, 0 = undef)
196    uint32_t HMPRE;         // Host Memory Buffer Preferred Size (4K pages)
197    uint32_t HMMIN;         // Host Memory Buffer Minimum Size (4K pages)
198    uint64_t TNVMCAP_LO;    // Total NVM Capacity (bytes)
199    uint64_t TNVMCAP_HI;
200    uint64_t UNVMCAP_LO;    // Unallocated NVM Capacity (bytes)
201    uint64_t UNVMCAP_HI;
202    uint32_t RPMBS;         // Replay Protected Memory Block Support
203    uint16_t EDSTT;         // Extended Device SelfTest Time
204    uint8_t  DSTO;          // Devcie SelfTest Options
205    uint8_t  FWUG;          // Firmware Upgreade Granularity
206    uint16_t KAS;           // Keep Alive Support
207    uint16_t HCTMA;         // Host Controlled Thermal Management Attrs
208    uint16_t MNTMT;         // Minimum Thermal Management Temp
209    uint16_t MXTMT;         // Maximum Thermal Management Temp
210    uint32_t SANICAP;       // Sanitize Capabilities
211    uint8_t  zz3[180];      // Reserved
212
213    // -------------------- // NVM Command Set Attributes
214    uint8_t  SQES;          // Submission Queue Entry Size
215    uint8_t  CQES;          // Completion Queue Entry Size
216    uint16_t MAXCMD;        // Max Outstanding Commands
217    uint32_t NN;            // Number of Namespaces
218    uint16_t ONCS;          // Optional NVM Command Support
219    uint16_t FUSES;         // Fused Operation Support
220    uint8_t  FNA;           // Format NVM Attributes
221    uint8_t  VWC;           // Volatile Write Cache
222    uint16_t AWUN;          // Atomic Write Unit Normal
223    uint16_t AWUPF;         // Atomic Write Unit Power Fail
224    uint8_t  NVSCC;         // NVM Vendor Specific Command Config
225    uint8_t  zz4;           // Reserved
226    uint16_t ACWU;          // Atomic Compare and Write Unit
227    uint16_t zz5;           // Reserved
228    uint32_t SGLS;          // Scatter Gather List Support
229    uint8_t  zz6[228];      // Reserved
230    uint8_t  SUBNQN[256];   // NVM Subsystem NVMe Qualified Name
231    uint8_t  zz7[768];      // Reserved
232    uint8_t  zz8[256];      // Refer to NVME over Fabrics Spec
233
234    // -------------------- // Power State Descriptors
235    nvme_psd_t PSD[32];
236
237    // -------------------- // Vendor Specific
238    uint8_t  vendor[1024];
239} nvme_identify_t;
240
241static_assert(sizeof(nvme_identify_t) == 4096, "");
242
243#define OACS_DOORBELL_BUFFER_CONFIG     (1 << 8)
244#define OACS_VIRTUALIZATION_MANAGEMENT  (1 << 7)
245#define OACS_NVME_MI_SEND_RECV          (1 << 6)
246#define OACS_DIRECTIVE_SEND_RECV        (1 << 5)
247#define OACS_DEVICE_SELF_TEST           (1 << 4)
248#define OACS_NAMESPACE_MANAGEMENT       (1 << 3)
249#define OACS_FIRMWARE_DOWNLOAD_COMMIT   (1 << 2)
250#define OACS_FORMAT_NVM                 (1 << 1)
251#define OACS_SECURITY_SEND_RECV         (1 << 0)
252
253#define ONCS_TIMESTAMP                  (1 << 6)
254#define ONCS_RESERVATIONS               (1 << 5)
255#define ONCS_SAVE_SELECT_NONZERO        (1 << 4)
256#define ONCS_WRITE_ZEROES               (1 << 3)
257#define ONCS_DATASET_MANAGEMENT         (1 << 2)
258#define ONCS_WRITE_UNCORRECTABLE        (1 << 1)
259#define ONCS_COMPARE                    (1 << 0)
260
261
262// Identify Page for Namespaces
263#define NSFEAT_GUIDS_NOT_REUSED         (1 << 3)
264#define NSFEAT_DEALLOC_BLOCK_ERROR      (1 << 2)
265#define NSFEAT_LOCAL_ATOMIC_SIZES       (1 << 1)
266#define NSFEAT_THING_PROVISIONING       (1 << 0)
267
268
269typedef struct {
270    // -------------------- // Vendor Specific
271    uint64_t NSSZ;          // Namespace Size (blocks)
272    uint64_t NCAP;          // Namespace Capacity (blocks)
273    uint64_t NUSE;          // Namespace Utilization (blocks)
274    uint8_t  NSFEAT;        // Namespace Features
275    uint8_t  NLBAF;         // Number of LBA Formats
276    uint8_t  FLBAS;         // Formatted LBA Size
277    uint8_t  MC;            // Metadata Capabilities
278    uint8_t  DPC;           // End-to-End Data Protection Capabilities
279    uint8_t  DPS;           // End-to-End Data Protection Type Settings
280    uint8_t  NMIC;          // Namespace MultiPath IO and Sharing Caps
281    uint8_t  RESCAP;        // Reservation Capabilities
282    uint8_t  FPI;           // Format Progress Indicator
283    uint8_t  DLFEAT;        // Deallocate Logical Block Features
284    uint16_t NAWUN;         // Namespace Atomic Write Unit Normal
285    uint16_t NAWUPF;        // Namespace Atomic Write Unit Power Fail
286    uint16_t NACWUN;        // Namespace Atomic Compare and Write Unit
287    uint16_t NABSN;         // Namespace Atomic Boundary Size Normal
288    uint16_t NABO;          // Namespace Atomic Boundary Offset
289    uint16_t NABSPF;        // Namespace Atomic Boundary Size Power Fail
290    uint16_t NOIOB;         // Namespace Optimal IO Boundary
291    uint64_t NVMCAP_LO;     // NVM Capacity (bytes)
292    uint64_t NVMCAP_HI;
293    uint8_t  zz0[40];       // Reserved
294    uint8_t  NGUID[16];     // Namespace GUID
295    uint8_t  EUI64[8];      // IEEE Extended Unique Identifier
296    uint32_t LBAF[16];      // LBA Format Support 0..15
297    uint8_t  zz1[192];      // Reserved
298    uint8_t  zz2[3712];     // Reserved
299} nvme_identify_ns_t;
300
301static_assert(sizeof(nvme_identify_ns_t) == 4096, "");
302
303#define NSFEAT_GUIDS_NOT_REUSED         (1 << 3)
304#define NSFEAT_DEALLOC_BLOCK_ERROR      (1 << 2)
305#define NSFEAT_LOCAL_ATOMIC_SIZES       (1 << 1)
306#define NSFEAT_THING_PROVISIONING       (1 << 0)
307