summaryrefslogtreecommitdiffstats
path: root/dma/nwl_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'dma/nwl_engine.c')
-rw-r--r--dma/nwl_engine.c136
1 files changed, 65 insertions, 71 deletions
diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c
index f541d0b..a437948 100644
--- a/dma/nwl_engine.c
+++ b/dma/nwl_engine.c
@@ -10,46 +10,41 @@
#include "pcilib.h"
#include "error.h"
#include "tools.h"
-#include "nwl_private.h"
+#include "nwl_private.h"
#include "nwl_defines.h"
-
#include "nwl_engine_buffers.h"
-int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
+int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_dma_engine_description_t *info, const 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;
+ info->addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT;
+ if ((info->addr > PCILIB_MAX_DMA_ENGINES)||(info->addr < 0)) return PCILIB_ERROR_INVALID_DATA;
switch (val & DMA_ENG_DIRECTION_MASK) {
case DMA_ENG_C2S:
- info->desc.direction = PCILIB_DMA_FROM_DEVICE;
+ info->direction = PCILIB_DMA_FROM_DEVICE;
break;
default:
- info->desc.direction = PCILIB_DMA_TO_DEVICE;
+ info->direction = PCILIB_DMA_TO_DEVICE;
}
switch (val & DMA_ENG_TYPE_MASK) {
case DMA_ENG_BLOCK:
- info->desc.type = PCILIB_DMA_TYPE_BLOCK;
+ info->type = PCILIB_DMA_TYPE_BLOCK;
break;
case DMA_ENG_PACKET:
- info->desc.type = PCILIB_DMA_TYPE_PACKET;
+ info->type = PCILIB_DMA_TYPE_PACKET;
break;
default:
- info->desc.type = PCILIB_DMA_TYPE_UNKNOWN;
+ info->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;
+ info->addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT;
return 0;
}
@@ -60,22 +55,21 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
uint32_t ring_pa;
struct timeval start, cur;
- pcilib_nwl_engine_description_t *info = ctx->engines + dma;
+ pcilib_nwl_engine_context_t *ectx = ctx->engines + dma;
char *base = ctx->engines[dma].base_addr;
- if (info->started) return 0;
-
+ if (ectx->started) return 0;
// This will only successed if there are no parallel access to DMA engine
- err = dma_nwl_allocate_engine_buffers(ctx, info);
+ err = dma_nwl_allocate_engine_buffers(ctx, ectx);
if (err) {
- info->started = 1;
+ ectx->started = 1;
dma_nwl_stop_engine(ctx, dma);
return err;
}
- if (info->reused) {
- info->preserve = 1;
+ if (ectx->reused) {
+ ectx->preserve = 1;
dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma);
@@ -86,7 +80,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
// Disable IRQs
err = dma_nwl_disable_engine_irq(ctx, dma);
if (err) {
- info->started = 1;
+ ectx->started = 1;
dma_nwl_stop_engine(ctx, dma);
return err;
}
@@ -102,9 +96,9 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
} 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);
+ pcilib_error("Timeout during reset of DMA engine %i", ectx->desc->addr);
- info->started = 1;
+ ectx->started = 1;
dma_nwl_stop_engine(ctx, dma);
return PCILIB_ERROR_TIMEOUT;
}
@@ -119,24 +113,24 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
} 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);
+ pcilib_error("Timeout during reset of DMA engine %i", ectx->desc->addr);
- info->started = 1;
+ ectx->started = 1;
dma_nwl_stop_engine(ctx, dma);
return PCILIB_ERROR_TIMEOUT;
}
dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma);
- 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);
+ ring_pa = pcilib_kmem_get_pa(ctx->dmactx.pcilib, ectx->ring);
+ nwl_write_register(ring_pa, ctx, ectx->base_addr, REG_DMA_ENG_NEXT_BD);
+ nwl_write_register(ring_pa, ctx, ectx->base_addr, REG_SW_NEXT_BD);
__sync_synchronize();
- nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+ nwl_read_register(val, ctx, ectx->base_addr, REG_DMA_ENG_CTRL_STATUS);
val |= (DMA_ENG_ENABLE);
- nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+ nwl_write_register(val, ctx, ectx->base_addr, REG_DMA_ENG_CTRL_STATUS);
__sync_synchronize();
@@ -144,19 +138,19 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
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);
+ if (ectx->desc->direction == PCILIB_DMA_FROM_DEVICE) {
+ ring_pa += (ectx->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+ nwl_write_register(ring_pa, ctx, ectx->base_addr, REG_SW_NEXT_BD);
- info->tail = 0;
- info->head = (info->ring_size - 1);
+ ectx->tail = 0;
+ ectx->head = (ectx->ring_size - 1);
} else {
- info->tail = 0;
- info->head = 0;
+ ectx->tail = 0;
+ ectx->head = 0;
}
}
- info->started = 1;
+ ectx->started = 1;
return 0;
}
@@ -170,17 +164,17 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
pcilib_kmem_flags_t flags;
- pcilib_nwl_engine_description_t *info = ctx->engines + dma;
+ pcilib_nwl_engine_context_t *ectx = ctx->engines + dma;
char *base = ctx->engines[dma].base_addr;
- if (!info->started) return 0;
+ if (!ectx->started) return 0;
- info->started = 0;
+ ectx->started = 0;
err = dma_nwl_disable_engine_irq(ctx, dma);
if (err) return err;
- if (!info->preserve) {
+ if (!ectx->preserve) {
// Stopping DMA is not enough reset is required
val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET|DMA_ENG_RESET;
nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
@@ -191,30 +185,30 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
gettimeofday(&cur, NULL);
} while ((val & (DMA_ENG_RUNNING))&&(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < PCILIB_REGISTER_TIMEOUT));
- 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);
+ if (ectx->ring) {
+ ring_pa = pcilib_kmem_get_pa(ctx->dmactx.pcilib, ectx->ring);
+ nwl_write_register(ring_pa, ctx, ectx->base_addr, REG_DMA_ENG_NEXT_BD);
+ nwl_write_register(ring_pa, ctx, ectx->base_addr, REG_SW_NEXT_BD);
}
}
dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma);
- if (info->preserve) {
+ if (ectx->preserve) {
flags = PCILIB_KMEM_FLAG_REUSE;
} else {
flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT;
}
// Clean buffers
- if (info->ring) {
- pcilib_free_kernel_memory(ctx->pcilib, info->ring, flags);
- info->ring = NULL;
+ if (ectx->ring) {
+ pcilib_free_kernel_memory(ctx->dmactx.pcilib, ectx->ring, flags);
+ ectx->ring = NULL;
}
- if (info->pages) {
- pcilib_free_kernel_memory(ctx->pcilib, info->pages, flags);
- info->pages = NULL;
+ if (ectx->pages) {
+ pcilib_free_kernel_memory(ctx->dmactx.pcilib, ectx->pages, flags);
+ ectx->pages = NULL;
}
return 0;
@@ -226,28 +220,28 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
size_t bufnum;
nwl_dma_t *ctx = (nwl_dma_t*)vctx;
- pcilib_nwl_engine_description_t *info = ctx->engines + dma;
+ pcilib_nwl_engine_context_t *ectx = ctx->engines + dma;
err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
if (err) return err;
if (data) {
- for (pos = 0; pos < size; pos += info->page_size) {
- int block_size = min2(size - pos, info->page_size);
+ for (pos = 0; pos < size; pos += ectx->page_size) {
+ int block_size = min2(size - pos, ectx->page_size);
- bufnum = dma_nwl_get_next_buffer(ctx, info, 1, timeout);
+ bufnum = dma_nwl_get_next_buffer(ctx, ectx, 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);
+ void *buf = pcilib_kmem_get_block_ua(ctx->dmactx.pcilib, ectx->pages, bufnum);
- pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum);
+ pcilib_kmem_sync_block(ctx->dmactx.pcilib, ectx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum);
memcpy(buf, data, block_size);
- pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum);
+ pcilib_kmem_sync_block(ctx->dmactx.pcilib, ectx->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum);
- err = dma_nwl_push_buffer(ctx, info, block_size, (flags&PCILIB_DMA_FLAG_EOP)&&((pos + block_size) == size), timeout);
+ err = dma_nwl_push_buffer(ctx, ectx, block_size, (flags&PCILIB_DMA_FLAG_EOP)&&((pos + block_size) == size), timeout);
if (err) {
if (written) *written = pos;
return err;
@@ -258,7 +252,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
if (written) *written = size;
if (flags&PCILIB_DMA_FLAG_WAIT) {
- bufnum = dma_nwl_get_next_buffer(ctx, info, PCILIB_NWL_DMA_PAGES - 1, timeout);
+ bufnum = dma_nwl_get_next_buffer(ctx, ectx, PCILIB_NWL_DMA_PAGES - 1, timeout);
if (bufnum == PCILIB_DMA_BUFFER_INVALID) return PCILIB_ERROR_TIMEOUT;
}
@@ -276,7 +270,7 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
int eop;
- pcilib_nwl_engine_description_t *info = ctx->engines + dma;
+ pcilib_nwl_engine_context_t *ectx = ctx->engines + dma;
err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
if (err) return err;
@@ -288,21 +282,21 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
// case PCILIB_STREAMING_CHECK: wait = 0; break;
}
- bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, wait);
+ bufnum = dma_nwl_wait_buffer(ctx, ectx, &bufsize, &eop, wait);
if (bufnum == PCILIB_DMA_BUFFER_INVALID) {
return (ret&PCILIB_STREAMING_FAIL)?PCILIB_ERROR_TIMEOUT:0;
}
// EOP is not respected in IPE Camera
- if (ctx->dmactx.ignore_eop) eop = 1;
+ if (ctx->ignore_eop) eop = 1;
- pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum);
- void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, info->pages, bufnum);
+ pcilib_kmem_sync_block(ctx->dmactx.pcilib, ectx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, bufnum);
+ void *buf = pcilib_kmem_get_block_ua(ctx->dmactx.pcilib, ectx->pages, bufnum);
ret = cb(cbattr, (eop?PCILIB_DMA_FLAG_EOP:0), bufsize, buf);
if (ret < 0) return -ret;
// DS: Fixme, it looks like we can avoid calling this for the sake of performance
-// pcilib_kmem_sync_block(ctx->pcilib, info->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum);
- dma_nwl_return_buffer(ctx, info);
+// pcilib_kmem_sync_block(ctx->dmactx.pcilib, ectx->pages, PCILIB_KMEM_SYNC_TODEVICE, bufnum);
+ dma_nwl_return_buffer(ctx, ectx);
res += bufsize;