Logo
Dune NVMe Storage Support
DuneNvme  1.0.2
This is a simple NVMe test environment that allows experimentation with the low level PCIe NVMe interfaces as available on a Xilinx FPGA environment.
NvmeAccess.h
1 /*******************************************************************************
2  * NvmeAccess.h Provides access to an Nvme storage device on FpgaFabric
3  * T.Barnaby, Beam Ltd, 2020-04-10
4  *******************************************************************************
5  */
44 #pragma once
45 
46 #include <BeamLibBasic.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <errno.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <sys/mman.h>
54 #include <arpa/inet.h>
55 #include <pthread.h>
56 #include <sys/ioctl.h>
57 #include <bfpga_driver/bfpga.h>
58 
59 const Bool UseFpgaConfigure = 0;
60 const Bool UseConfigEngine = 0;
61 const Bool UseQueueEngine = 1;
62 const BUInt PcieMaxPayloadSize = 32;
63 const BUInt MaxPayloadSize = 1024;
64 const BUInt BlockSize = 4096;
65 
66 const BUInt RegIdent = 0x000;
67 const BUInt RegControl = 0x004;
68 const BUInt RegStatus = 0x008;
69 const BUInt RegTotalBlocks = 0x00C;
70 const BUInt RegLostBlocks = 0x010;
71 
72 const BUInt RegDataChunkStart = 0x040;
73 const BUInt RegDataChunkSize = 0x044;
74 const BUInt RegWriteError = 0x048;
75 const BUInt RegWriteNumBlocks = 0x04C;
76 const BUInt RegWriteTime = 0x050;
77 const BUInt RegWritePeakLatency = 0x054;
78 
79 const BUInt RegReadControl = 0x080;
80 const BUInt RegReadStatus = 0x084;
81 const BUInt RegReadBlock = 0x088;
82 const BUInt RegReadNumBlocks = 0x08C;
83 const BUInt RegReadError = 0x090;
84 
85 const BUInt NvmeRegCapLow = 0x000;
86 const BUInt NvmeRegCapHigh = 0x004;
87 
89 public:
91  memset(this, 0, sizeof(*this));
92  }
93 
94  BUInt64 address;
95  BUInt32 numWords:11;
96  BUInt32 request:4;
97  BUInt32 fill2:1;
98  BUInt32 requesterId:16;
99  BUInt32 tag:8;
100  BUInt32 completerId:16;
101  BUInt32 requesterIdEnable:1;
102  BUInt32 fill3:7;
103  BUInt32 data[MaxPayloadSize];
104 };
105 
107 public:
108  NvmeReplyPacket(){
109  memset(this, 0, sizeof(*this));
110  }
111 
112  BUInt32 address:12;
113  BUInt32 error:4;
114  BUInt32 numBytes:13;
115  BUInt32 fill1:3;
116  BUInt32 numWords:11;
117  BUInt32 status:3;
118  BUInt32 fill2:2;
119  BUInt32 requesterId:16;
120  BUInt32 tag:8;
121  BUInt32 completerId:16;
122  BUInt32 fill3:7;
123  BUInt32 reply:1;
124  BUInt32 data[MaxPayloadSize];
125 };
126 
127 const BUInt NvmeSglTypeData = 0;
128 
129 class NvmeSgl {
130  BUInt64 address;
131  BUInt32 length;
132  BUInt8 fill0[2];
133  BUInt8 subtype:4;
134  BUInt8 type:4;
135 };
136 
138 class NvmeAccess {
139 public:
140  NvmeAccess();
141  ~NvmeAccess();
142 
143  int init();
144  void close();
145 
146  void setNvme(BUInt n);
147  BUInt getNvme();
148  void reset();
149  void start();
150 
151  // Send a queued request to the NVMe
152  int nvmeRequest(Bool wait, int queue, int opcode, BUInt nameSpace, BUInt32 address, BUInt32 arg10, BUInt32 arg11 = 0, BUInt32 arg12 = 0);
153 
154  // NVMe process received requests thread
155  int nvmeProcess();
156  virtual void nvmeDataPacket(NvmeRequestPacket& packet);
157 
158  // NvmeStorage units register access
159  BUInt32 readNvmeStorageReg(BUInt32 address);
160  void writeNvmeStorageReg(BUInt32 address, BUInt32 data);
161 
162  // NVMe register access
163  int readNvmeReg32(BUInt32 address, BUInt32& data);
164  int writeNvmeReg32(BUInt32 address, BUInt32 data);
165  int readNvmeReg64(BUInt32 address, BUInt64& data);
166  int writeNvmeReg64(BUInt32 address, BUInt64 data);
167 
168  // Perform register access over PCIe both config and NVMe registers
169  int pcieWrite(BUInt8 request, BUInt32 address, BUInt32 num, BUInt32* data);
170  int pcieRead(BUInt8 request, BUInt32 address, BUInt32 num, BUInt32* data);
171 
172  // Packet send and receive
173  int packetSend(const NvmeRequestPacket& packet);
174  int packetSend(const NvmeReplyPacket& packet);
175  int readAvailable();
176 
177  // Debug
178  void dumpRegs(int nvmeNum = -1);
179  void dumpDmaRegs(bool c2h, int chan);
180  void dumpStatus();
181 
182 
183 protected:
184  int oregsFd;
188  volatile BUInt32* oregs;
189  volatile BUInt32* odmaRegs;
190 
191  BUInt32* obufTx;
192  BUInt32* obufRx;
193  BUInt8 otag;
194 
198 
199  pthread_t othread;
200  BUInt32 onvmeNum;
201  BUInt32 onvmeRegbase;
202  BUInt32 oqueueNum;
203 
204  BUInt32 oqueueAdminMem[4096];
205  BUInt32 oqueueAdminRx;
206  BUInt32 oqueueAdminTx;
207  BUInt32 oqueueAdminId;
208 
209  BUInt32 oqueueDataMem[4096];
210  BUInt32 oqueueDataRx;
211  BUInt32 oqueueDataTx;
212 
213  BUInt32 odataBlockMem[8192];
214 };
BUInt64 address
The 64bit read/write address.
Definition: NvmeAccess.h:94
BUInt32 address
The lower 12 bits of the address.
Definition: NvmeAccess.h:112
Nvme access class.
Definition: NvmeAccess.h:138
BSemaphore opacketReplySem
Semaphore when a reply packet has been received.
Definition: NvmeAccess.h:195
BUInt32 numWords
The number of 32bit words in this reply.
Definition: NvmeAccess.h:116
Semaphore class.
Definition: BeamLibBasic.h:88
BUInt32 status
The status for the request.
Definition: NvmeAccess.h:117
BUInt32 data[MaxPayloadSize]
The data words (Max of 1024 bytes but can be increased)
Definition: NvmeAccess.h:124
BUInt32 numBytes
The total number of bytes to be transfered.
Definition: NvmeAccess.h:114
int ohostRecvFd
Device driver fd for DMA receive channel.
Definition: NvmeAccess.h:186
virtual void nvmeDataPacket(NvmeRequestPacket &packet)
Called when read data packet received.
Definition: NvmeAccess.cpp:492
BUInt32 tag
The requests tag.
Definition: NvmeAccess.h:120
NvmeReplyPacket opacketReply
Reply to request.
Definition: NvmeAccess.h:196
BUInt32 completerId
The completer id.
Definition: NvmeAccess.h:121
BUInt32 requesterId
The requestors ID.
Definition: NvmeAccess.h:119
BUInt32 data[MaxPayloadSize]
The data words (Max of 1024 bytes but can be increased)
Definition: NvmeAccess.h:103
Definition: bfpga.h:49
BUInt32 requesterId
The requestors ID used as the stream ID.
Definition: NvmeAccess.h:98
BUInt32 onvmeRegbase
The register base address.
Definition: NvmeAccess.h:201
int nvmeProcess()
This function runs as a separate thread in order to receive both replies and requests from the Nvme.
Definition: NvmeAccess.cpp:322
BSemaphore oqueueReplySem
Semaphore when a queue reply packet has been received.
Definition: NvmeAccess.h:197
void start()
Start NVMe request processing thread.
Definition: NvmeAccess.cpp:234
int oregsFd
Device drive fd for register access.
Definition: NvmeAccess.h:184
volatile BUInt32 * odmaRegs
FPGA's PCIe XDMA modules DMA control registers memory mapped.
Definition: NvmeAccess.h:189
Definition: NvmeAccess.h:106
BUInt32 reply
This bit indicates a reply (we have used an unused bit for this)
Definition: NvmeAccess.h:123
BUInt32 error
An error number.
Definition: NvmeAccess.h:113
Definition: NvmeAccess.h:129
BUInt32 request
The request (0 - read, 1 - write etc.)
Definition: NvmeAccess.h:96
BUInt32 tag
A tag for this request, returned in the reply.
Definition: NvmeAccess.h:99
int ohostSendFd
Device driver fd for DMA send channel.
Definition: NvmeAccess.h:185
volatile BUInt32 * oregs
FPGA design's registers memory mapped.
Definition: NvmeAccess.h:188
BUInt32 numWords
The number of 32bit data words to transfer.
Definition: NvmeAccess.h:95
BUInt32 completerId
The completers ID.
Definition: NvmeAccess.h:100
BUInt32 onvmeNum
The nvme to communicate with, 0 is both.
Definition: NvmeAccess.h:200
BFpgaInfo oinfo
Device driver information.
Definition: NvmeAccess.h:187
int readAvailable()
The number of bytes available on the receive stream.
Definition: NvmeAccess.cpp:644
Definition: NvmeAccess.h:88
BUInt32 requesterIdEnable
Enable the manual use of the requestorId field.
Definition: NvmeAccess.h:101