summaryrefslogtreecommitdiffstats
path: root/dma
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-12 14:39:06 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-12 14:39:06 +0200
commit493958c9cf11eaa25251d91e9ecab9a28bd6d68f (patch)
treebdda549da425acc5bdbddb5006b6980ec4233a77 /dma
parentde984f8b9706cfac79f7658e5b3863e78b052458 (diff)
downloadipecamera-493958c9cf11eaa25251d91e9ecab9a28bd6d68f.tar.gz
ipecamera-493958c9cf11eaa25251d91e9ecab9a28bd6d68f.tar.bz2
ipecamera-493958c9cf11eaa25251d91e9ecab9a28bd6d68f.tar.xz
ipecamera-493958c9cf11eaa25251d91e9ecab9a28bd6d68f.zip
Provide IRQ enable/disable call
Diffstat (limited to 'dma')
-rw-r--r--dma/nwl.c80
-rw-r--r--dma/nwl.h5
-rw-r--r--dma/nwl_dma.h7
-rw-r--r--dma/nwl_irq.c42
-rw-r--r--dma/nwl_irq.h5
5 files changed, 121 insertions, 18 deletions
diff --git a/dma/nwl.c b/dma/nwl.c
index 6c3079a..bca0c5c 100644
--- a/dma/nwl.c
+++ b/dma/nwl.c
@@ -240,7 +240,7 @@ int dma_nwl_start(nwl_dma_t *ctx) {
if (ctx->started) return 0;
#ifdef NWL_GENERATE_DMA_IRQ
- dma_nwl_enable_irq(ctx, PCILIB_DMA_IRQ);
+ dma_nwl_enable_irq(ctx, PCILIB_DMA_IRQ, 0);
#endif /* NWL_GENERATE_DMA_IRQ */
ctx->started = 1;
@@ -255,7 +255,7 @@ int dma_nwl_stop(nwl_dma_t *ctx) {
ctx->started = 0;
- err = dma_nwl_disable_irq(ctx);
+ err = dma_nwl_free_irq(ctx);
if (err) return err;
err = dma_nwl_stop_loopback(ctx);
@@ -355,7 +355,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
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;
@@ -431,6 +431,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
uint32_t val;
uint32_t *buf, *cmp;
const char *error = NULL;
+// pcilib_register_value_t regval;
size_t us = 0;
struct timeval start, cur;
@@ -446,9 +447,12 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
if (size%sizeof(uint32_t)) size = 1 + size / sizeof(uint32_t);
else size /= sizeof(uint32_t);
+ // Not supported
+ if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
+
// Stop Generators and drain old data
dma_nwl_stop_loopback(ctx);
- dma_nwl_stop_engine(ctx, readid); // DS: replace with something better
+// dma_nwl_stop_engine(ctx, readid); // DS: replace with something better
__sync_synchronize();
@@ -456,15 +460,26 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
#ifdef NWL_GENERATE_DMA_IRQ
dma_nwl_enable_engine_irq(ctx, readid);
+ dma_nwl_enable_engine_irq(ctx, writeid);
#endif /* NWL_GENERATE_DMA_IRQ */
+
dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t));
/*
+ printf("Packet size: %li\n", size * sizeof(uint32_t));
+ pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", &regval);
+ printf("Count write: %lx\n", regval);
+
nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS);
printf("Read DMA control: %lx\n", val);
nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS);
printf("Write DMA control: %lx\n", val);
+
+ nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD);
+ printf("Pointer1: %lx\n", val);
+ nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD);
+ printf("Pointer2: %lx\n", val);
*/
// Allocate memory and prepare data
@@ -486,12 +501,28 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
err = pcilib_write_dma(ctx->pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes);
if ((err)||(bytes != size * sizeof(uint32_t))) {
- printf("%i %lu write\n", err, bytes);
error = "Write failed";
break;
}
}
/*
+ printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", &regval));
+ printf("Count write (%i of %i): %lx\n", i, iterations, regval);
+
+ printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1r_counter", &regval));
+ printf("Count read (%i of %i): %lx\n", i, iterations, regval);
+
+
+ nwl_read_register(val, ctx, read_base, REG_DMA_ENG_COMP_BYTES);
+ printf("Compl Bytes (read): %lx\n", val);
+
+ nwl_read_register(val, ctx, write_base, REG_DMA_ENG_COMP_BYTES);
+ printf("Compl Bytes (write): %lx\n", val);
+
+ nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS);
+ printf("Read DMA control (after write): %lx\n", val);
+*/
+/*
nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS);
printf("Read DMA control (after write): %lx\n", val);
nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS);
@@ -504,7 +535,23 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
if ((err)||(bytes != size * sizeof(uint32_t))) {
- printf("%i %lu read\n", err, bytes);
+/*
+ nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS);
+ printf("Read DMA control: %lx\n", val);
+ nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS);
+ printf("Write DMA control: %lx\n", val);
+ nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD);
+ printf("After Pointer wr1: %lx\n", val);
+ nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD);
+ printf("After Pointer wr2: %lx\n", val);
+ pcilib_read_register(ctx->pcilib, NULL, "end_address", &regval);
+ printf("End address: %lx\n", regval);
+
+ nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD);
+ printf("After Pointer read1: %lx\n", val);
+ nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD);
+ printf("After Pointer read2: %lx\n", val);
+*/
error = "Read failed";
break;
}
@@ -512,16 +559,33 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
if (direction == PCILIB_DMA_BIDIRECTIONAL) {
res = memcmp(buf, cmp, size * sizeof(uint32_t));
if (res) {
- puts("verify");
error = "Written and read values does not match";
break;
}
}
}
+
+ if (error) {
+ pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, i, err, bytes);
+ }
+
+/*
+ puts("Finished...");
+ nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD);
+ printf("After Pointer read1: %lx\n", val);
+ nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD);
+ printf("After Pointer read2: %lx\n", val);
+
+ nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD);
+ printf("After Pointer wr1: %lx\n", val);
+ nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD);
+ printf("After Pointer wr2: %lx\n", val);
+*/
#ifdef NWL_GENERATE_DMA_IRQ
- dma_nwl_disable_irq(ctx);
+ dma_nwl_disable_engine_irq(ctx, writeid);
+ dma_nwl_disable_engine_irq(ctx, readid);
#endif /* NWL_GENERATE_DMA_IRQ */
dma_nwl_stop_loopback(ctx);
diff --git a/dma/nwl.h b/dma/nwl.h
index 1ee6f5d..4e15418 100644
--- a/dma/nwl.h
+++ b/dma/nwl.h
@@ -28,9 +28,10 @@ struct nwl_dma_s {
pcilib_register_bank_description_t *dma_bank;
char *base_addr;
-
+
+ int irq_init; /**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */
pcilib_irq_type_t irq_enabled; /**< indicates that IRQs are enabled */
- int irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */
+ pcilib_irq_type_t irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */
int started; /**< indicates that DMA subsystem is initialized and DMA engine can start */
pcilib_dma_engine_t n_engines;
diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h
index 5ba9b18..70b9d97 100644
--- a/dma/nwl_dma.h
+++ b/dma/nwl_dma.h
@@ -11,6 +11,9 @@ 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);
+int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags);
+int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags);
+
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 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);
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);
@@ -20,8 +23,8 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
pcilib_dma_api_description_t nwl_dma_api = {
dma_nwl_init,
dma_nwl_free,
- NULL,
- NULL,
+ dma_nwl_enable_irq,
+ dma_nwl_disable_irq,
NULL,
NULL,
dma_nwl_write_fragment,
diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c
index 51705ff..04ac908 100644
--- a/dma/nwl_irq.c
+++ b/dma/nwl_irq.c
@@ -13,12 +13,39 @@
#include "nwl.h"
#include "nwl_defines.h"
-int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type) {
+int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val) {
+ if (val&(DMA_INT_ENABLE|DMA_USER_INT_ENABLE)) {
+ if (val&DMA_INT_ENABLE) ctx->irq_preserve |= PCILIB_DMA_IRQ;
+ if (val&DMA_USER_INT_ENABLE) ctx->irq_preserve |= PCILIB_EVENT_IRQ;
+ }
+
+ ctx->irq_init = 1;
+ return 0;
+}
+
+int dma_nwl_free_irq(nwl_dma_t *ctx) {
+ if (ctx->irq_init) {
+ dma_nwl_disable_irq((pcilib_dma_context_t*)ctx, 0);
+ if (ctx->irq_preserve) dma_nwl_enable_irq((pcilib_dma_context_t*)ctx, ctx->irq_preserve, 0);
+ ctx->irq_enabled = 0;
+ ctx->irq_init = 0;
+ }
+ return 0;
+}
+
+int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags) {
uint32_t val;
+ nwl_dma_t *ctx = (nwl_dma_t*)vctx;
- if (ctx->irq_enabled == type) return 0;
+ if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->irq_preserve |= type;
+ if (ctx->irq_enabled == type) return 0;
+
+ type |= ctx->irq_enabled;
+
nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS);
+ if (!ctx->irq_init) dma_nwl_init_irq(ctx, val);
+
val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE);
nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS);
@@ -33,22 +60,28 @@ int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type) {
return 0;
}
-int dma_nwl_disable_irq(nwl_dma_t *ctx) {
+
+int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags) {
uint32_t val;
+ nwl_dma_t *ctx = (nwl_dma_t*)vctx;
ctx->irq_enabled = 0;
nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS);
+ if (!ctx->irq_init) dma_nwl_init_irq(ctx, val);
val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE);
nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS);
+ if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->irq_preserve = 0;
+
return 0;
}
+
int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
uint32_t val;
- dma_nwl_enable_irq(ctx, ctx->irq_enabled|PCILIB_DMA_IRQ);
+ dma_nwl_enable_irq(ctx, ctx->irq_enabled|PCILIB_DMA_IRQ, 0);
nwl_read_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS);
val |= (DMA_ENG_INT_ENABLE);
@@ -68,4 +101,5 @@ int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
}
+
// ACK
diff --git a/dma/nwl_irq.h b/dma/nwl_irq.h
index 685d74c..811b632 100644
--- a/dma/nwl_irq.h
+++ b/dma/nwl_irq.h
@@ -1,8 +1,9 @@
#ifndef _PCILIB_NWL_IRQ_H
#define _PCILIB_NWL_IRQ_H
-int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type);
-int dma_nwl_disable_irq(nwl_dma_t *ctx);
+int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val);
+int dma_nwl_free_irq(nwl_dma_t *ctx);
+
int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma);
int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma);