diff options
Diffstat (limited to 'dma/ipe.c')
-rw-r--r-- | dma/ipe.c | 70 |
1 files changed, 52 insertions, 18 deletions
@@ -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); |