diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-12 14:51:11 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-12 14:51:11 +0200 |
commit | 6c922712fd8ee7e75a1b45c4980be22d36d0d1d9 (patch) | |
tree | f10f58ea417b269447f3c3db805e7a5269e845cf | |
parent | 493958c9cf11eaa25251d91e9ecab9a28bd6d68f (diff) | |
download | ipecamera-6c922712fd8ee7e75a1b45c4980be22d36d0d1d9.tar.gz ipecamera-6c922712fd8ee7e75a1b45c4980be22d36d0d1d9.tar.bz2 ipecamera-6c922712fd8ee7e75a1b45c4980be22d36d0d1d9.tar.xz ipecamera-6c922712fd8ee7e75a1b45c4980be22d36d0d1d9.zip |
Another reorganization of NWL sources
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | dma/nwl.c | 279 | ||||
-rw-r--r-- | dma/nwl.h | 19 | ||||
-rw-r--r-- | dma/nwl_buffers.h | 11 | ||||
-rw-r--r-- | dma/nwl_dma.h | 4 | ||||
-rw-r--r-- | dma/nwl_engine.c | 266 | ||||
-rw-r--r-- | dma/nwl_engine.h | 7 |
7 files changed, 302 insertions, 286 deletions
@@ -14,7 +14,7 @@ include common.mk ############################################################### # Target definitions -OBJECTS = pci.o register.o kmem.o irq.o dma.o event.o default.o tools.o dma/nwl.o dma/nwl_register.o dma/nwl_irq.o ipecamera/model.o ipecamera/image.o +OBJECTS = pci.o register.o kmem.o irq.o dma.o event.o default.o tools.o dma/nwl.o dma/nwl_register.o dma/nwl_irq.o dma/nwl_engine.o ipecamera/model.o ipecamera/image.o libpcilib.so: $(OBJECTS) echo -e "LD \t$@" @@ -8,199 +8,14 @@ #include <sys/time.h> #include "pci.h" -#include "dma.h" #include "pcilib.h" #include "error.h" #include "tools.h" #include "nwl.h" #include "nwl_defines.h" -#include "nwl_register.h" -#define NWL_XAUI_ENGINE 0 -#define NWL_XRAWDATA_ENGINE 1 -#define NWL_FIX_EOP_FOR_BIG_PACKETS // requires precise sizes in read requests -//#define NWL_GENERATE_DMA_IRQ - -#define PCILIB_NWL_ALIGNMENT 64 // in bytes -#define PCILIB_NWL_DMA_DESCRIPTOR_SIZE 64 // in bytes -#define PCILIB_NWL_DMA_PAGES 512 // 1024 - - -static int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) { - uint32_t val; - - info->base_addr = base; - - nwl_read_register(val, ctx, base, REG_DMA_ENG_CAP); - - if ((val & DMA_ENG_PRESENT_MASK) == 0) return PCILIB_ERROR_NOTAVAILABLE; - - info->desc.addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT; - if ((info->desc.addr > PCILIB_MAX_DMA_ENGINES)||(info->desc.addr < 0)) return PCILIB_ERROR_INVALID_DATA; - - switch (val & DMA_ENG_DIRECTION_MASK) { - case DMA_ENG_C2S: - info->desc.direction = PCILIB_DMA_FROM_DEVICE; - break; - default: - info->desc.direction = PCILIB_DMA_TO_DEVICE; - } - - switch (val & DMA_ENG_TYPE_MASK) { - case DMA_ENG_BLOCK: - info->desc.type = PCILIB_DMA_TYPE_BLOCK; - break; - case DMA_ENG_PACKET: - info->desc.type = PCILIB_DMA_TYPE_PACKET; - break; - default: - info->desc.type = PCILIB_DMA_TYPE_UNKNOWN; - } - - info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT; - - info->base_addr = base; - - return 0; -} - - -int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - int err; - uint32_t val; - uint32_t ring_pa; - struct timeval start, cur; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - char *base = ctx->engines[dma].base_addr; - - if (info->started) return 0; - - // Disable IRQs - err = dma_nwl_disable_engine_irq(ctx, dma); - if (err) return err; - - // Disable Engine & Reseting - val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - gettimeofday(&start, NULL); - do { - nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - gettimeofday(&cur, NULL); - } while ((val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET))&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); - - if (val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET)) { - pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); - return PCILIB_ERROR_TIMEOUT; - } - - val = DMA_ENG_RESET; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - gettimeofday(&start, NULL); - do { - nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - gettimeofday(&cur, NULL); - } while ((val & DMA_ENG_RESET)&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); - - if (val & DMA_ENG_RESET) { - pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); - return PCILIB_ERROR_TIMEOUT; - } - - // Acknowledge asserted engine interrupts - if (val & DMA_ENG_INT_ACTIVE_MASK) { - val |= DMA_ENG_ALLINT_MASK; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - } - - err = dma_nwl_start(ctx); - if (err) return err; - - err = dma_nwl_allocate_engine_buffers(ctx, info); - if (err) return err; - - ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - - __sync_synchronize(); - - nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - val |= (DMA_ENG_ENABLE); - nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); - - __sync_synchronize(); - -#ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_enable_engine_irq(ctx, dma); -#endif /* NWL_GENERATE_DMA_IRQ */ - - if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) { - ring_pa += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - - info->tail = 0; - info->head = (info->ring_size - 1); - } else { - info->tail = 0; - info->head = 0; - } - - info->started = 1; - - return 0; -} - - -int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { - int err; - uint32_t val; - uint32_t ring_pa; - struct timeval start, cur; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - char *base = ctx->engines[dma].base_addr; - - info->started = 0; - - err = dma_nwl_disable_engine_irq(ctx, dma); - if (err) return err; - - val = DMA_ENG_DISABLE; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - - if (info->ring) { - ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); - nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); - } - - // Acknowledge asserted engine interrupts - if (val & DMA_ENG_INT_ACTIVE_MASK) { - val |= DMA_ENG_ALLINT_MASK; - nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); - } - - // Clean buffers - if (info->ring) { - pcilib_free_kernel_memory(ctx->pcilib, info->ring); - info->ring = NULL; - } - - if (info->pages) { - pcilib_free_kernel_memory(ctx->pcilib, info->pages); - info->pages = NULL; - } - - - - return 0; -} - int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) { uint32_t val; @@ -328,100 +143,6 @@ void dma_nwl_free(pcilib_dma_context_t *vctx) { } } -int dma_nwl_sync_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, pcilib_kmem_handle_t *kmem) { - switch (info->desc.direction) { - case PCILIB_DMA_FROM_DEVICE: - return pcilib_sync_kernel_memory(ctx->pcilib, kmem, PCILIB_KMEM_SYNC_FROMDEVICE); - case PCILIB_DMA_TO_DEVICE: - return pcilib_sync_kernel_memory(ctx->pcilib, kmem, PCILIB_KMEM_SYNC_TODEVICE); - } - - return 0; -} - -#include "nwl_buffers.h" - -int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written) { - int err; - size_t pos; - size_t bufnum; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - - err = dma_nwl_start_engine(ctx, dma); - if (err) return err; - - if (data) { - for (pos = 0; pos < size; pos += info->page_size) { - int block_size = min2(size - pos, info->page_size); - - bufnum = dma_nwl_get_next_buffer(ctx, info, 1, timeout); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) { - if (written) *written = pos; - return PCILIB_ERROR_TIMEOUT; - } - - void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); - memcpy(buf, data, block_size); - - err = dma_nwl_push_buffer(ctx, info, block_size, (flags&PCILIB_DMA_FLAG_EOP)&&((pos + block_size) == size), timeout); - if (err) { - if (written) *written = pos; - return err; - } - } - } - - if (written) *written = size; - - if (flags&PCILIB_DMA_FLAG_WAIT) { - bufnum = dma_nwl_get_next_buffer(ctx, info, PCILIB_NWL_DMA_PAGES - 1, timeout); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT; - } - - return 0; -} - -int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { - int err, ret; - size_t res = 0; - size_t bufnum; - size_t bufsize; - nwl_dma_t *ctx = (nwl_dma_t*)vctx; - - size_t buf_size; - int eop; - - pcilib_nwl_engine_description_t *info = ctx->engines + dma; - - err = dma_nwl_start_engine(ctx, dma); - if (err) return err; - - do { - bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, timeout); - if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT; - -#ifdef NWL_FIX_EOP_FOR_BIG_PACKETS - if (size > 65536) { -// printf("%i %i\n", res + bufsize, size); - if ((res+bufsize) < size) eop = 0; - else if ((res+bufsize) == size) eop = 1; - } -#endif /* NWL_FIX_EOP_FOR_BIG_PACKETS */ - - //sync - void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); - ret = cb(cbattr, eop?PCILIB_DMA_FLAG_EOP:0, bufsize, buf); - dma_nwl_return_buffer(ctx, info); - - res += bufsize; - - } while (ret); - - return 0; -} - double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { int i; @@ -1,14 +1,29 @@ #ifndef _PCILIB_NWL_H #define _PCILIB_NWL_H +typedef struct nwl_dma_s nwl_dma_t; +typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t; + +#define NWL_DMA_IRQ_SOURCE 0 + +#define NWL_XAUI_ENGINE 0 +#define NWL_XRAWDATA_ENGINE 1 +#define NWL_FIX_EOP_FOR_BIG_PACKETS // requires precise sizes in read requests +//#define NWL_GENERATE_DMA_IRQ + +#define PCILIB_NWL_ALIGNMENT 64 // in bytes +#define PCILIB_NWL_DMA_DESCRIPTOR_SIZE 64 // in bytes +#define PCILIB_NWL_DMA_PAGES 512 // 1024 + #include "nwl_dma.h" #include "nwl_irq.h" #include "nwl_register.h" +#include "nwl_engine.h" #define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess) #define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess) -typedef struct { +struct pcilib_nwl_engine_description_s { pcilib_dma_engine_description_t desc; char *base_addr; @@ -20,7 +35,7 @@ typedef struct { int started; /**< indicates that DMA buffers are initialized and reading is allowed */ int writting; /**< indicates that we are in middle of writting packet */ int preserve; /**< indicates that DMA should not be stopped during clean-up */ -} pcilib_nwl_engine_description_t; +}; struct nwl_dma_s { diff --git a/dma/nwl_buffers.h b/dma/nwl_buffers.h index e059b97..35f4781 100644 --- a/dma/nwl_buffers.h +++ b/dma/nwl_buffers.h @@ -2,6 +2,17 @@ #define NWL_RING_SET(data, offset, val) *(uint32_t*)(((char*)(data)) + (offset)) = (val) #define NWL_RING_UPDATE(data, offset, mask, val) *(uint32_t*)(((char*)(data)) + (offset)) = ((*(uint32_t*)(((char*)(data)) + (offset)))&(mask))|(val) +int dma_nwl_sync_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, pcilib_kmem_handle_t *kmem) { + switch (info->desc.direction) { + case PCILIB_DMA_FROM_DEVICE: + return pcilib_sync_kernel_memory(ctx->pcilib, kmem, PCILIB_KMEM_SYNC_FROMDEVICE); + case PCILIB_DMA_TO_DEVICE: + return pcilib_sync_kernel_memory(ctx->pcilib, kmem, PCILIB_KMEM_SYNC_TODEVICE); + } + + return 0; +} + int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) { int err = 0; diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h index 70b9d97..0ed8158 100644 --- a/dma/nwl_dma.h +++ b/dma/nwl_dma.h @@ -4,10 +4,6 @@ #include <stdio.h> #include "pcilib.h" -#define NWL_DMA_IRQ_SOURCE 0 - -typedef struct nwl_dma_s nwl_dma_t; - pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx); void dma_nwl_free(pcilib_dma_context_t *vctx); diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c new file mode 100644 index 0000000..3258da6 --- /dev/null +++ b/dma/nwl_engine.c @@ -0,0 +1,266 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> + +#include "pci.h" +#include "pcilib.h" +#include "error.h" +#include "tools.h" +#include "nwl.h" + +#include "nwl_defines.h" + +int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) { + uint32_t val; + + info->base_addr = base; + + nwl_read_register(val, ctx, base, REG_DMA_ENG_CAP); + + if ((val & DMA_ENG_PRESENT_MASK) == 0) return PCILIB_ERROR_NOTAVAILABLE; + + info->desc.addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT; + if ((info->desc.addr > PCILIB_MAX_DMA_ENGINES)||(info->desc.addr < 0)) return PCILIB_ERROR_INVALID_DATA; + + switch (val & DMA_ENG_DIRECTION_MASK) { + case DMA_ENG_C2S: + info->desc.direction = PCILIB_DMA_FROM_DEVICE; + break; + default: + info->desc.direction = PCILIB_DMA_TO_DEVICE; + } + + switch (val & DMA_ENG_TYPE_MASK) { + case DMA_ENG_BLOCK: + info->desc.type = PCILIB_DMA_TYPE_BLOCK; + break; + case DMA_ENG_PACKET: + info->desc.type = PCILIB_DMA_TYPE_PACKET; + break; + default: + info->desc.type = PCILIB_DMA_TYPE_UNKNOWN; + } + + info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT; + + info->base_addr = base; + + return 0; +} + +int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { + int err; + uint32_t val; + uint32_t ring_pa; + struct timeval start, cur; + + pcilib_nwl_engine_description_t *info = ctx->engines + dma; + char *base = ctx->engines[dma].base_addr; + + if (info->started) return 0; + + // Disable IRQs + err = dma_nwl_disable_engine_irq(ctx, dma); + if (err) return err; + + // Disable Engine & Reseting + val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET; + nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + + gettimeofday(&start, NULL); + do { + nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + gettimeofday(&cur, NULL); + } while ((val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET))&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); + + if (val & (DMA_ENG_STATE_MASK|DMA_ENG_USER_RESET)) { + pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); + return PCILIB_ERROR_TIMEOUT; + } + + val = DMA_ENG_RESET; + nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + + gettimeofday(&start, NULL); + do { + nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + gettimeofday(&cur, NULL); + } while ((val & DMA_ENG_RESET)&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT)); + + if (val & DMA_ENG_RESET) { + pcilib_error("Timeout during reset of DMA engine %i", info->desc.addr); + return PCILIB_ERROR_TIMEOUT; + } + + // Acknowledge asserted engine interrupts + if (val & DMA_ENG_INT_ACTIVE_MASK) { + val |= DMA_ENG_ALLINT_MASK; + nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + } + + err = dma_nwl_start(ctx); + if (err) return err; + + err = dma_nwl_allocate_engine_buffers(ctx, info); + if (err) return err; + + ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); + nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); + nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); + + __sync_synchronize(); + + nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); + val |= (DMA_ENG_ENABLE); + nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS); + + __sync_synchronize(); + +#ifdef NWL_GENERATE_DMA_IRQ + dma_nwl_enable_engine_irq(ctx, dma); +#endif /* NWL_GENERATE_DMA_IRQ */ + + if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) { + ring_pa += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE; + nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); + + info->tail = 0; + info->head = (info->ring_size - 1); + } else { + info->tail = 0; + info->head = 0; + } + + info->started = 1; + + return 0; +} + + +int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { + int err; + uint32_t val; + uint32_t ring_pa; + struct timeval start, cur; + + pcilib_nwl_engine_description_t *info = ctx->engines + dma; + char *base = ctx->engines[dma].base_addr; + + info->started = 0; + + err = dma_nwl_disable_engine_irq(ctx, dma); + if (err) return err; + + val = DMA_ENG_DISABLE; + nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + + if (info->ring) { + ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring); + nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD); + nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD); + } + + // Acknowledge asserted engine interrupts + if (val & DMA_ENG_INT_ACTIVE_MASK) { + val |= DMA_ENG_ALLINT_MASK; + nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS); + } + + // Clean buffers + if (info->ring) { + pcilib_free_kernel_memory(ctx->pcilib, info->ring); + info->ring = NULL; + } + + if (info->pages) { + pcilib_free_kernel_memory(ctx->pcilib, info->pages); + info->pages = NULL; + } + + return 0; +} + +#include "nwl_buffers.h" + +int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written) { + int err; + size_t pos; + size_t bufnum; + nwl_dma_t *ctx = (nwl_dma_t*)vctx; + + pcilib_nwl_engine_description_t *info = ctx->engines + dma; + + err = dma_nwl_start_engine(ctx, dma); + if (err) return err; + + if (data) { + for (pos = 0; pos < size; pos += info->page_size) { + int block_size = min2(size - pos, info->page_size); + + bufnum = dma_nwl_get_next_buffer(ctx, info, 1, timeout); + if (bufnum == PCILIB_DMA_BUFFER_INVALID) { + if (written) *written = pos; + return PCILIB_ERROR_TIMEOUT; + } + + void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); + memcpy(buf, data, block_size); + + err = dma_nwl_push_buffer(ctx, info, block_size, (flags&PCILIB_DMA_FLAG_EOP)&&((pos + block_size) == size), timeout); + if (err) { + if (written) *written = pos; + return err; + } + } + } + + if (written) *written = size; + + if (flags&PCILIB_DMA_FLAG_WAIT) { + bufnum = dma_nwl_get_next_buffer(ctx, info, PCILIB_NWL_DMA_PAGES - 1, timeout); + if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT; + } + + return 0; +} + +int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { + int err, ret; + size_t res = 0; + size_t bufnum; + size_t bufsize; + nwl_dma_t *ctx = (nwl_dma_t*)vctx; + + size_t buf_size; + int eop; + + pcilib_nwl_engine_description_t *info = ctx->engines + dma; + + err = dma_nwl_start_engine(ctx, dma); + if (err) return err; + + do { + bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, timeout); + if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT; + +#ifdef NWL_FIX_EOP_FOR_BIG_PACKETS + if (size > 65536) { +// printf("%i %i\n", res + bufsize, size); + if ((res+bufsize) < size) eop = 0; + else if ((res+bufsize) == size) eop = 1; + } +#endif /* NWL_FIX_EOP_FOR_BIG_PACKETS */ + + //sync + void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum); + ret = cb(cbattr, eop?PCILIB_DMA_FLAG_EOP:0, bufsize, buf); + dma_nwl_return_buffer(ctx, info); + + res += bufsize; + + } while (ret); + + return 0; +} diff --git a/dma/nwl_engine.h b/dma/nwl_engine.h new file mode 100644 index 0000000..778dc8a --- /dev/null +++ b/dma/nwl_engine.h @@ -0,0 +1,7 @@ +#ifndef _PCILIB_DMA_NWL_ENGINE_H +#define _PCILIB_DMA_NWL_ENGINE_H + +int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base); + +#endif /* _PCILIB_DMA_NWL_ENGINE_H */ + |