summaryrefslogtreecommitdiffstats
path: root/dma/nwl_engine.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-17 03:37:29 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-17 03:37:29 +0200
commit112030c40f88dde281073e00e4c24cc48daa99d2 (patch)
treef6486582ee46a2b3b48bba5bc9d96c8432d0b7dc /dma/nwl_engine.c
parent7ac0539951ff0eba200e64b850b5181a82915c86 (diff)
downloadipecamera-112030c40f88dde281073e00e4c24cc48daa99d2.tar.gz
ipecamera-112030c40f88dde281073e00e4c24cc48daa99d2.tar.bz2
ipecamera-112030c40f88dde281073e00e4c24cc48daa99d2.tar.xz
ipecamera-112030c40f88dde281073e00e4c24cc48daa99d2.zip
Implement DMA access synchronization for NWL implementation
Diffstat (limited to 'dma/nwl_engine.c')
-rw-r--r--dma/nwl_engine.c125
1 files changed, 66 insertions, 59 deletions
diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c
index 59e9b93..58d5522 100644
--- a/dma/nwl_engine.c
+++ b/dma/nwl_engine.c
@@ -65,88 +65,89 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
if (info->started) return 0;
+
// This will only successed if there are no parallel access to DMA engine
err = dma_nwl_allocate_engine_buffers(ctx, info);
if (err) return err;
- // Check if DMA engine is enabled
- nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
- if (val&DMA_ENG_RUNNING) {
-// info->preserve = 1;
-
- // We need to positionate buffers correctly (both read and write)
- //DSS info->tail, info->head
-
-// pcilib_error("Not implemented");
-
-// info->started = 1;
-// return 0;
- }
+ if (info->reused) {
+ info->preserve = 1;
+
+ // 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);
+ }
+#ifdef NWL_GENERATE_DMA_IRQ
+ dma_nwl_enable_engine_irq(ctx, dma);
+#endif /* NWL_GENERATE_DMA_IRQ */
+ } else {
// Disable IRQs
- err = dma_nwl_disable_engine_irq(ctx, dma);
- if (err) return err;
+ 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);
+ 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));
+ 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;
- }
+ 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);
+ 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));
+ 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;
- }
+ 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);
- }
+ // 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);
+ }
- 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->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();
+ __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);
+ 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();
+ __sync_synchronize();
#ifdef NWL_GENERATE_DMA_IRQ
- dma_nwl_enable_engine_irq(ctx, 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 (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->tail = 0;
+ info->head = (info->ring_size - 1);
+ } else {
+ info->tail = 0;
+ info->head = 0;
+ }
}
info->started = 1;
@@ -174,6 +175,12 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET|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_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);