summaryrefslogtreecommitdiffstats
path: root/dma.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-10-26 07:12:31 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-10-26 07:12:31 +0200
commit32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e (patch)
tree7cf6cf29b564505655db004d5df11fa28c687278 /dma.c
parent39125f647c27a19abf85b25c753fc97832708d38 (diff)
downloadipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.gz
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.bz2
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.xz
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.zip
Improvements of DMA engine
Diffstat (limited to 'dma.c')
-rw-r--r--dma.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/dma.c b/dma.c
index 9527c0b..216aa60 100644
--- a/dma.c
+++ b/dma.c
@@ -168,20 +168,29 @@ typedef struct {
size_t size;
void *data;
size_t pos;
+
+ pcilib_dma_flags_t flags;
} pcilib_dma_read_callback_context_t;
static int pcilib_dma_read_callback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
pcilib_dma_read_callback_context_t *ctx = (pcilib_dma_read_callback_context_t*)arg;
if (ctx->pos + bufsize > ctx->size) {
- pcilib_error("Buffer size (%li) is not large enough for DMA packet, at least %li bytes is required", ctx->size, ctx->pos + bufsize);
- return PCILIB_ERROR_INVALID_DATA;
+ if ((ctx->flags&PCILIB_DMA_FLAG_IGNORE_ERRORS) == 0)
+ pcilib_error("Buffer size (%li) is not large enough for DMA packet, at least %li bytes is required", ctx->size, ctx->pos + bufsize);
+ return -PCILIB_ERROR_TOOBIG;
}
memcpy(ctx->data + ctx->pos, buf, bufsize);
ctx->pos += bufsize;
- if (flags & PCILIB_DMA_FLAG_EOP) return 0;
+ if (flags & PCILIB_DMA_FLAG_EOP) {
+ if ((ctx->pos < ctx->size)&&(ctx->flags&PCILIB_DMA_FLAG_MULTIPACKET)) {
+ if (ctx->flags&PCILIB_DMA_FLAG_WAIT) return 2;
+ else return 3;
+ }
+ return 0;
+ }
return 1;
}
@@ -229,11 +238,23 @@ int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, si
return ctx->model_info.dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr);
}
+int pcilib_read_dma_custom(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *read_bytes) {
+ int err;
+
+ pcilib_dma_read_callback_context_t opts = {
+ size, buf, 0, flags
+ };
+
+ err = pcilib_stream_dma(ctx, dma, addr, size, flags, timeout, pcilib_dma_read_callback, &opts);
+ if (read_bytes) *read_bytes = opts.pos;
+ return err;
+}
+
int pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *read_bytes) {
int err;
pcilib_dma_read_callback_context_t opts = {
- size, buf, 0
+ size, buf, 0, 0
};
err = pcilib_stream_dma(ctx, dma, addr, size, PCILIB_DMA_FLAGS_DEFAULT, PCILIB_DMA_TIMEOUT, pcilib_dma_read_callback, &opts);
@@ -241,6 +262,7 @@ int pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size
return err;
}
+
int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) {
int err;
struct timeval tv, cur;