summaryrefslogtreecommitdiffstats
path: root/dma/ipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'dma/ipe.c')
-rw-r--r--dma/ipe.c70
1 files changed, 52 insertions, 18 deletions
diff --git a/dma/ipe.c b/dma/ipe.c
index 63f2fa3..ef3196d 100644
--- a/dma/ipe.c
+++ b/dma/ipe.c
@@ -1,12 +1,14 @@
#define _PCILIB_DMA_IPE_C
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
+#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
+#include <time.h>
#include <sys/time.h>
#include <arpa/inet.h>
@@ -45,6 +47,10 @@ pcilib_dma_context_t *dma_ipe_init(pcilib_t *pcilib, const char *model, const vo
ctx->dma_bank = model_info->banks + dma_bank;
ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr);
+
+ RD(IPEDMA_REG_VERSION, value);
+ ctx->version = value;
+
RD(IPEDMA_REG_PCIE_GEN, value);
#ifdef IPEDMA_ENFORCE_64BIT_MODE
@@ -101,7 +107,27 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->preserve = 1;
if (ctx->pages) return 0;
-
+
+ if (!pcilib_read_register(ctx->dmactx.pcilib, "dmaconf", "dma_timeout", &value))
+ ctx->dma_timeout = value;
+ else
+ ctx->dma_timeout = IPEDMA_DMA_TIMEOUT;
+
+ if (!pcilib_read_register(ctx->dmactx.pcilib, "dmaconf", "dma_page_size", &value))
+ ctx->dma_page_size = value;
+ else
+ ctx->dma_page_size = IPEDMA_PAGE_SIZE;
+
+ if (!pcilib_read_register(ctx->dmactx.pcilib, "dmaconf", "dma_pages", &value))
+ ctx->dma_pages = value;
+ else
+ ctx->dma_pages = IPEDMA_DMA_PAGES;
+
+ if (!pcilib_read_register(ctx->dmactx.pcilib, "dmaconf", "ipedma_flags", &value))
+ ctx->dma_flags = value;
+ else
+ ctx->dma_flags = 0;
+
kflags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ctx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0);
pcilib_kmem_handle_t *desc = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, IPEDMA_DESCRIPTOR_SIZE, IPEDMA_DESCRIPTOR_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x00), kflags);
pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, IPEDMA_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x00), kflags);
@@ -409,17 +435,9 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
volatile uint32_t *empty_detected_ptr;
pcilib_dma_flags_t packet_flags = PCILIB_DMA_FLAG_EOP;
- size_t nodata_sleep;
- switch (sched_getscheduler(0)) {
- case SCHED_FIFO:
- case SCHED_RR:
- nodata_sleep = IPEDMA_NODATA_SLEEP;
- break;
- default:
- pcilib_info_once("Streaming DMA data using non real-time thread (may cause extra CPU load)", errno);
- nodata_sleep = 0;
- }
+ size_t nodata_sleep;
+ struct timespec sleep_ts = {0};
size_t cur_read;
@@ -435,6 +453,19 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
empty_detected_ptr = last_written_addr_ptr - 2;
+ switch (sched_getscheduler(0)) {
+ case SCHED_FIFO:
+ case SCHED_RR:
+ if (ctx->dma_flags&IPEDMA_FLAG_NOSLEEP)
+ nodata_sleep = 0;
+ else
+ nodata_sleep = IPEDMA_NODATA_SLEEP;
+ break;
+ default:
+ pcilib_info_once("Streaming DMA data using non real-time thread (may cause extra CPU load)", errno);
+ nodata_sleep = 0;
+ }
+
do {
switch (ret&PCILIB_STREAMING_TIMEOUT_MASK) {
case PCILIB_STREAMING_CONTINUE:
@@ -444,10 +475,10 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
wait = 0;
else
#endif /* IPEDMA_SUPPORT_EMPTY_DETECTED */
- wait = IPEDMA_DMA_TIMEOUT;
+ wait = ctx->dma_timeout;
break;
case PCILIB_STREAMING_WAIT:
- wait = (timeout > IPEDMA_DMA_TIMEOUT)?timeout:IPEDMA_DMA_TIMEOUT;
+ wait = (timeout > ctx->dma_timeout)?timeout:ctx->dma_timeout;
break;
// case PCILIB_STREAMING_CHECK: wait = 0; break;
}
@@ -460,8 +491,10 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
gettimeofday(&start, NULL);
memcpy(&cur, &start, sizeof(struct timeval));
while (((*last_written_addr_ptr == 0)||(ctx->last_read_addr == (*last_written_addr_ptr)))&&((wait == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < wait))) {
- if (nodata_sleep)
- usleep(nodata_sleep);
+ if (nodata_sleep) {
+ sleep_ts.tv_nsec = nodata_sleep;
+ nanosleep(&sleep_ts, NULL);
+ }
#ifdef IPEDMA_SUPPORT_EMPTY_DETECTED
if ((ret != PCILIB_STREAMING_REQ_PACKET)&&(*empty_detected_ptr)) break;
@@ -494,13 +527,14 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
else packet_flags = 0;
#endif /* IPEDMA_DETECT_PACKETS */
- pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, cur_read);
+ if ((ctx->dma_flags&IPEDMA_FLAG_NOSYNC) == 0)
+ pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, cur_read);
void *buf = pcilib_kmem_get_block_ua(ctx->dmactx.pcilib, ctx->pages, cur_read);
ret = cb(cbattr, packet_flags, ctx->page_size, buf);
if (ret < 0) return -ret;
// We don't need this because hardware does not intend to read anything from the memory
-// pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read);
+ //pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read);
// Return buffer into the DMA pool when processed
if (ctx->streaming) {
@@ -510,7 +544,7 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
else last_free = IPEDMA_DMA_PAGES - 1;
uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, last_free);
- WR(IPEDMA_REG_PAGE_ADDR, buf_ba);
+ WR(IPEDMA_REG_PAGE_ADDR, buf_ba);
# ifdef IPEDMA_STREAMING_CHECKS
pcilib_register_value_t streaming_status;
RD(IPEDMA_REG_STREAMING_STATUS, streaming_status);