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