diff --git a/include/villas/fpga/dma.h b/include/villas/fpga/dma.h index bf94399e9..f97965c93 100644 --- a/include/villas/fpga/dma.h +++ b/include/villas/fpga/dma.h @@ -18,20 +18,32 @@ #include +#define FPGA_DMA_BASEADDR 0x00000000 +#define FPGA_DMA_BOUNDARY 0x1000 +#define FPGA_DMA_BD_OFFSET 0xC0000000 +#define FPGA_DMA_BD_SIZE (32 << 20) // 32 MB + #define XAXIDMA_SR_SGINCL_MASK 0x00000008 -struct dma { - XAxiDma inst; -}; - struct dma_mem { - uint32_t base_virt; - uint32_t base_phys; + char *base_virt; + char *base_phys; size_t len; }; +struct dma { + XAxiDma inst; + + struct dma_mem bd; +}; + struct ip; +int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b); + +int dma_alloc(struct ip *c, struct dma_mem *mem, size_t len, int flags); +int dma_free(struct ip *c, struct dma_mem *mem); + int dma_write(struct ip *c, char *buf, size_t len); int dma_read(struct ip *c, char *buf, size_t len); int dma_read_complete(struct ip *c, char **buf, size_t *len); diff --git a/lib/fpga/dma.c b/lib/fpga/dma.c index f34baf9dd..9e63ae93c 100644 --- a/lib/fpga/dma.c +++ b/lib/fpga/dma.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -18,6 +19,60 @@ #include "fpga/dma.h" #include "fpga/ip.h" +int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b) +{ + int split = o->len / 2; + + a->base_virt = o->base_virt; + a->base_phys = o->base_phys; + + b->base_virt = a->base_virt + split; + b->base_phys = a->base_phys + split; + + a->len = split; + b->len = o->len - split; + + return 0; +} + +int dma_alloc(struct ip *c, struct dma_mem *mem, size_t len, int flags) +{ + int ret; + + /* Align to next bigger page size chunk */ + if (len & 0xFFF) { + len += 0x1000; + len &= ~0xFFF; + } + + mem->len = len; + mem->base_phys = -1; /* find free */ + mem->base_virt = mmap(0, mem->len, PROT_READ | PROT_WRITE, flags | MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, 0, 0); + if (mem->base_virt == MAP_FAILED) + return -1; + + ret = vfio_map_dma(c->card->vd.group->container, mem); + if (ret) + return -2; + + return 0; +} + +int dma_free(struct ip *c, struct dma_mem *mem) +{ + int ret; + + ret = vfio_unmap_dma(c->card->vd.group->container, mem); + if (ret) + return ret; + + ret = munmap(mem->base_virt, mem->len); + if (ret) + return ret; + + return 0; +} + int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len) { int ret;