summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli.c120
-rw-r--r--dma.c30
-rw-r--r--dma.h8
-rw-r--r--dma/nwl.c6
-rw-r--r--dma/nwl.h4
-rw-r--r--dma/nwl_dma.h2
-rw-r--r--dma/nwl_engine.c45
-rw-r--r--dma/nwl_engine.h2
-rw-r--r--dma/nwl_engine_buffers.h85
-rw-r--r--dma/nwl_irq.c2
-rw-r--r--dma/nwl_loopback.c132
-rw-r--r--dma/nwl_register.c6
-rw-r--r--dma/nwl_register.h8
-rw-r--r--error.h3
-rw-r--r--pcilib.h27
15 files changed, 298 insertions, 182 deletions
diff --git a/cli.c b/cli.c
index 53c8f75..e07a470 100644
--- a/cli.c
+++ b/cli.c
@@ -74,6 +74,11 @@ typedef enum {
} ACCESS_MODE;
typedef enum {
+ FLAG_MULTIPACKET = 1,
+ FLAG_WAIT = 2
+} FLAGS;
+
+typedef enum {
OPT_DEVICE = 'd',
OPT_MODEL = 'm',
OPT_BAR = 'b',
@@ -101,7 +106,9 @@ typedef enum {
OPT_LIST_KMEM,
OPT_FREE_KMEM,
OPT_READ_KMEM,
- OPT_FORCE
+ OPT_FORCE,
+ OPT_WAIT,
+ OPT_MULTIPACKET
} OPTIONS;
static struct option long_options[] = {
@@ -132,6 +139,8 @@ static struct option long_options[] = {
{"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM },
{"quiete", no_argument, 0, OPT_QUIETE },
{"force", no_argument, 0, OPT_FORCE },
+ {"multipacket", no_argument, 0, OPT_MULTIPACKET },
+ {"wait", no_argument, 0, OPT_WAIT },
{"help", no_argument, 0, OPT_HELP },
{ 0, 0, 0, 0 }
};
@@ -194,6 +203,10 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" -o <file> - Append output to file (default: stdout)\n"
" -t <timeout> - Timeout in microseconds\n"
"\n"
+" DMA Options:\n"
+" --multipacket - Read multiple packets\n"
+" --wait - Wait until data arrives\n"
+"\n"
" Information:\n"
" -q - Quiete mode (suppress warnings)\n"
"\n"
@@ -393,8 +406,8 @@ int Benchmark(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
}
for (size = min_size; size <= max_size; size *= 4) {
- mbs_in = pcilib_benchmark_dma(handle, dma, addr, size, BENCHMARK_ITERATIONS, PCILIB_DMA_FROM_DEVICE);
- mbs_out = pcilib_benchmark_dma(handle, dma, addr, size, BENCHMARK_ITERATIONS, PCILIB_DMA_TO_DEVICE);
+ mbs_in = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_FROM_DEVICE);
+ mbs_out = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_TO_DEVICE);
mbs = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_BIDIRECTIONAL);
err = pcilib_wait_irq(handle, 0, 0, &irqs);
if (err) irqs = 0;
@@ -571,15 +584,45 @@ int Benchmark(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
#define pci2host16(endianess, value) endianess?
+/*
+typedef struct {
+ size_t size;
+ void *data;
+ size_t pos;
+
+ int multi_mode;
+} DMACallbackContext;
+
+static int DMACallback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
+ DMACallbackContext *ctx = (DMACallbackContext*)arg;
+
+ if ((ctx->pos + bufsize > ctx->size)||(!ctx->data)) {
+ ctx->size *= 2;
+ ctx->data = realloc(ctx->data, ctx->size);
+ if (!ctx->data) {
+ Error("Allocation of %i bytes of memory have failed", ctx->size);
+ return 0;
+ }
+ }
+
+ memcpy(ctx->data + ctx->pos, buf, bufsize);
+ ctx->pos += bufsize;
+
+ if (flags & PCILIB_DMA_FLAG_EOP) return 0;
+ return 1;
+}
+*/
+
-int ReadData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, FILE *o) {
+int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, size_t timeout, FILE *o) {
void *buf;
int i, err;
- size_t ret;
+ size_t ret, bytes;
int size = n * abs(access);
int block_width, blocks_per_line;
int numbers_per_block, numbers_per_line;
pcilib_dma_engine_t dmaid;
+ pcilib_dma_flags_t dma_flags = 0;
numbers_per_block = BLOCK_SIZE / access;
@@ -588,18 +631,45 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, p
if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
numbers_per_line = blocks_per_line * numbers_per_block;
-// buf = alloca(size);
- err = posix_memalign( (void**)&buf, 256, size );
- if ((err)||(!buf)) Error("Allocation of %i bytes of memory have failed", size);
+ if (size) {
+ buf = malloc(size);
+ if (!buf) Error("Allocation of %i bytes of memory have failed", size);
+ } else {
+ buf = NULL;
+ }
switch (mode) {
case ACCESS_DMA:
+ if (timeout == (size_t)-1) timeout = PCILIB_DMA_TIMEOUT;
+
dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
- err = pcilib_read_dma(handle, dmaid, addr, size, buf, &ret);
- if ((err)||(ret <= 0)) Error("No data is returned by DMA engine");
- size = ret;
- n = ret / abs(access);
+
+ if (flags&FLAG_MULTIPACKET) dma_flags |= PCILIB_DMA_FLAG_MULTIPACKET;
+ if (flags&FLAG_WAIT) dma_flags |= PCILIB_DMA_FLAG_WAIT;
+
+ if (size) {
+ err = pcilib_read_dma_custom(handle, dmaid, addr, size, dma_flags, timeout, buf, &bytes);
+ if (err) Error("Error (%i) is reported by DMA engine", err);
+ } else {
+ dma_flags |= PCILIB_DMA_FLAG_IGNORE_ERRORS;
+
+ size = 2048; bytes = 0;
+ do {
+ size *= 2;
+ buf = realloc(buf, size);
+ err = pcilib_read_dma_custom(handle, dmaid, addr, size - bytes, dma_flags, timeout, buf + bytes, &ret);
+ bytes += ret;
+
+ if ((!err)&&(flags&FLAG_MULTIPACKET)) {
+ err = PCILIB_ERROR_TOOBIG;
+ if ((flags&FLAG_WAIT)==0) timeout = 0;
+ }
+ } while (err == PCILIB_ERROR_TOOBIG);
+ }
+ if (bytes <= 0) Error("No data is returned by DMA engine");
+ size = bytes;
+ n = bytes / abs(access);
addr = 0;
break;
case ACCESS_FIFO:
@@ -639,6 +709,7 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, p
free(buf);
+ return 0;
}
@@ -703,6 +774,8 @@ int ReadRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const
}
printf("\n");
}
+
+ return 0;
}
#define WRITE_REGVAL(buf, n, access, o) {\
@@ -818,12 +891,14 @@ int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
if ((read_back)&&(memcmp(buf, check, size))) {
printf("Write failed: the data written and read differ, the foolowing is read back:\n");
if (endianess) pcilib_swap(check, check, abs(access), n);
- ReadData(handle, mode, dma, bar, addr, n, access, endianess, NULL);
+ ReadData(handle, mode, 0, dma, bar, addr, n, access, endianess, (size_t)-1, NULL);
exit(-1);
}
free(check);
free(buf);
+
+ return 0;
}
int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, size_t n, char ** data) {
@@ -856,6 +931,8 @@ int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info,
free(check);
free(buf);
+
+ return 0;
}
@@ -1412,6 +1489,7 @@ int main(int argc, char **argv) {
pcilib_model_t model = PCILIB_MODEL_DETECT;
pcilib_model_description_t *model_info;
MODE mode = MODE_INVALID;
+ FLAGS flags = 0;
const char *type = NULL;
ACCESS_MODE amode = ACCESS_BAR;
const char *fpga_device = DEFAULT_FPGA_DEVICE;
@@ -1442,7 +1520,7 @@ int main(int argc, char **argv) {
pcilib_t *handle;
int size_set = 0;
-
+ int timeout_set = 0;
while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) {
extern int optind;
@@ -1645,6 +1723,7 @@ int main(int argc, char **argv) {
case OPT_TIMEOUT:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1))
Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
+ timeout_set = 1;
break;
case OPT_OUTPUT:
output = optarg;
@@ -1652,7 +1731,6 @@ int main(int argc, char **argv) {
case OPT_ITERATIONS:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &iterations) != 1))
Usage(argc, argv, "Invalid number of iterations is specified (%s)", optarg);
- size_set = 1;
break;
case OPT_QUIETE:
quiete = 1;
@@ -1660,6 +1738,12 @@ int main(int argc, char **argv) {
case OPT_FORCE:
force = 1;
break;
+ case OPT_MULTIPACKET:
+ flags |= FLAG_MULTIPACKET;
+ break;
+ case OPT_WAIT:
+ flags |= FLAG_WAIT;
+ break;
default:
Usage(argc, argv, "Unknown option (%s) with argument (%s)", optarg?argv[optind-2]:argv[optind-1], optarg?optarg:"(null)");
}
@@ -1823,8 +1907,10 @@ int main(int argc, char **argv) {
Benchmark(handle, amode, dma, bar, start, size_set?size:0, access, iterations);
break;
case MODE_READ:
- if ((addr)||(amode == ACCESS_DMA)) {
- ReadData(handle, amode, dma, bar, start, size, access, endianess, ofile);
+ if (amode == ACCESS_DMA) {
+ ReadData(handle, amode, flags, dma, bar, start, size_set?size:0, access, endianess, timeout_set?timeout:(size_t)-1, ofile);
+ } else if (addr) {
+ ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile);
} else {
Error("Address to read is not specified");
}
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;
diff --git a/dma.h b/dma.h
index 8da1c96..375763f 100644
--- a/dma.h
+++ b/dma.h
@@ -6,7 +6,6 @@
typedef uint32_t pcilib_dma_modification_t;
-
typedef struct {
int started;
size_t ring_size, buffer_size;
@@ -25,7 +24,7 @@ struct pcilib_dma_api_description_s {
pcilib_dma_context_t *(*init)(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg);
void (*free)(pcilib_dma_context_t *ctx);
- int (*status)(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers);
+ int (*status)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers);
int (*enable_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags);
int (*disable_irq)(pcilib_dma_context_t *ctx, pcilib_dma_flags_t flags);
@@ -40,6 +39,11 @@ struct pcilib_dma_api_description_s {
double (*benchmark)(pcilib_dma_context_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction);
};
+struct pcilib_dma_context_s {
+ int ignore_eop;
+};
+
+
int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc);
int pcilib_get_dma_status(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers);
diff --git a/dma/nwl.c b/dma/nwl.c
index 7d2c964..cc03687 100644
--- a/dma/nwl.c
+++ b/dma/nwl.c
@@ -88,6 +88,10 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib, pcilib_dma_modification_t t
ctx->pcilib = pcilib;
ctx->type = type;
+ if (type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
+ ctx->dmactx.ignore_eop = 1;
+ }
+
pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
if (dma_bank == PCILIB_REGISTER_BANK_INVALID) {
free(ctx);
@@ -132,7 +136,7 @@ void dma_nwl_free(pcilib_dma_context_t *vctx) {
if (ctx) {
if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx);
dma_nwl_free_irq(ctx);
- dma_nwl_stop(ctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT);
+ dma_nwl_stop(vctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT);
free(ctx);
}
diff --git a/dma/nwl.h b/dma/nwl.h
index db48fdc..0e4b5ae 100644
--- a/dma/nwl.h
+++ b/dma/nwl.h
@@ -8,7 +8,7 @@ typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t;
#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_MAX_PACKET_SIZE 4096 //16384
//#define NWL_GENERATE_DMA_IRQ
#define PCILIB_NWL_ALIGNMENT 64 // in bytes
@@ -44,6 +44,8 @@ struct pcilib_nwl_engine_description_s {
struct nwl_dma_s {
+ struct pcilib_dma_context_s dmactx;
+
pcilib_t *pcilib;
pcilib_dma_modification_t type;
diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h
index f87c68f..f9873f7 100644
--- a/dma/nwl_dma.h
+++ b/dma/nwl_dma.h
@@ -9,7 +9,7 @@
pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg);
void dma_nwl_free(pcilib_dma_context_t *vctx);
-int dma_nwl_get_status(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers);
+int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers);
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);
diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c
index 037ab02..806173d 100644
--- a/dma/nwl_engine.c
+++ b/dma/nwl_engine.c
@@ -77,7 +77,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
if (info->reused) {
info->preserve = 1;
- dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
+ dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma);
#ifdef NWL_GENERATE_DMA_IRQ
dma_nwl_enable_engine_irq(ctx, dma);
@@ -126,7 +126,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
return PCILIB_ERROR_TIMEOUT;
}
- dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
+ 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);
@@ -198,7 +198,7 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
}
}
- dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
+ dma_nwl_acknowledge_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, dma);
if (info->preserve) {
flags = PCILIB_KMEM_FLAG_REUSE;
@@ -228,7 +228,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
pcilib_nwl_engine_description_t *info = ctx->engines + dma;
- err = dma_nwl_start(ctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
+ err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
if (err) return err;
if (data) {
@@ -266,7 +266,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
}
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;
+ int err, ret = 1;
size_t res = 0;
size_t bufnum;
size_t bufsize;
@@ -277,28 +277,31 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
pcilib_nwl_engine_description_t *info = ctx->engines + dma;
- err = dma_nwl_start(ctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
+ err = dma_nwl_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
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;
+ if (ret > 2) {
+ bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, 0);
+ if (bufnum == PCILIB_DMA_BUFFER_INVALID) return 0;
+ } else {
+ bufnum = dma_nwl_wait_buffer(ctx, info, &bufsize, &eop, timeout);
+ if (bufnum == PCILIB_DMA_BUFFER_INVALID) {
+ if (ret == 1) return PCILIB_ERROR_TIMEOUT;
+ return 0;
+ }
}
-#endif /* NWL_FIX_EOP_FOR_BIG_PACKETS */
+
+ // EOP is not respected in IPE Camera
+ if (ctx->dmactx.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);
- ret = cb(cbattr, eop?PCILIB_DMA_FLAG_EOP:0, bufsize, buf);
+ ret = cb(cbattr, (eop?PCILIB_DMA_FLAG_EOP:0), bufsize, buf);
// 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);
+ if (ret < 0) return -ret;
dma_nwl_return_buffer(ctx, info);
-
res += bufsize;
@@ -306,3 +309,9 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
return 0;
}
+
+int dma_nwl_wait_completion(nwl_dma_t * ctx, pcilib_dma_engine_t dma, pcilib_timeout_t timeout) {
+ if (dma_nwl_get_next_buffer(ctx, ctx->engines + dma, PCILIB_NWL_DMA_PAGES - 1, PCILIB_DMA_TIMEOUT) == (PCILIB_NWL_DMA_PAGES - 1)) return 0;
+ else return PCILIB_ERROR_TIMEOUT;
+}
+
diff --git a/dma/nwl_engine.h b/dma/nwl_engine.h
index 176eaeb..f9f3f60 100644
--- a/dma/nwl_engine.h
+++ b/dma/nwl_engine.h
@@ -5,6 +5,8 @@ int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *
int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma);
int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma);
+int dma_nwl_wait_completion(nwl_dma_t * ctx, pcilib_dma_engine_t dma, pcilib_timeout_t timeout);
+
#endif /* _PCILIB_DMA_NWL_ENGINE_H */
diff --git a/dma/nwl_engine_buffers.h b/dma/nwl_engine_buffers.h
index 8f31bb6..b97e469 100644
--- a/dma/nwl_engine_buffers.h
+++ b/dma/nwl_engine_buffers.h
@@ -276,13 +276,6 @@ static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *
val = ring_pa + info->head * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD);
-// nwl_read_register(val, ctx, info->base_addr, 0x18);
-
-// usleep(10000);
-
-// nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_LAST_BD);
-// printf("Last BD(Write): %lx %lx\n", ring, val);
-
return 0;
}
@@ -293,27 +286,16 @@ static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_
struct timeval start, cur;
uint32_t status_size, status, control;
-// usleep(10000);
-
unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
-// status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
-// printf("Status0: %lx\n", status_size);
-
ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
gettimeofday(&start, NULL);
-// printf("Waiting %li\n", info->tail);
-// nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_LAST_BD);
-// printf("Last BD(Read): %lx %lx\n", ring, val);
-
do {
status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
status = status_size & DMA_BD_STATUS_MASK;
-// printf("%i: %lx\n", info->tail, status_size);
-
if (status & DMA_BD_ERROR_MASK) {
pcilib_error("NWL DMA Engine reported error in ring descriptor");
return (size_t)-1;
@@ -322,10 +304,17 @@ static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_
if (status & DMA_BD_COMP_MASK) {
if (status & DMA_BD_EOP_MASK) *eop = 1;
else *eop = 0;
-
+
*size = status_size & DMA_BD_BUFL_MASK;
+
+/*
+ if (mrd) {
+ if ((info->tail + 1) == info->ring_size) ring -= info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+ else ring += PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+ *mrd = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_COMP_MASK;
+ }
+*/
-// printf("Status: %lx\n", status_size);
return info->tail;
}
@@ -333,11 +322,19 @@ static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_
gettimeofday(&cur, NULL);
} while ((timeout == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < timeout));
-// printf("Final status: %lx\n", status_size);
-
return (size_t)-1;
}
+static int dma_nwl_is_overflown(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
+ uint32_t status;
+ unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
+ if (info->tail > 0) ring += (info->tail - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+ else ring += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+
+ status = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
+ return status&DMA_BD_COMP_MASK?1:0;
+}
+
static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
uint32_t val;
@@ -346,7 +343,6 @@ static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t
size_t bufsz = pcilib_kmem_get_block_size(ctx->pcilib, info->pages, info->tail);
ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
-// printf("Returning: %i\n", info->tail);
#ifdef NWL_GENERATE_DMA_IRQ
NWL_RING_SET(ring, DMA_BD_BUFL_CTRL_OFFSET, bufsz | DMA_BD_INT_ERROR_MASK | DMA_BD_INT_COMP_MASK);
@@ -358,13 +354,12 @@ static int dma_nwl_return_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t
val = ring_pa + info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
nwl_write_register(val, ctx, info->base_addr, REG_SW_NEXT_BD);
-// nwl_read_register(val, ctx, info->base_addr, 0x18);
info->tail++;
if (info->tail == info->ring_size) info->tail = 0;
}
-int dma_nwl_get_status(pcilib_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) {
+int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) {
size_t i;
uint32_t bstatus;
nwl_dma_t *ctx = (nwl_dma_t*)vctx;
@@ -410,43 +405,3 @@ int dma_nwl_get_status(pcilib_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engin
return 0;
}
-
-/*
- unsigned char *ring = pcilib_kmem_get_ua(ctx->pcilib, info->ring);
-
-// status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
-// printf("Status0: %lx\n", status_size);
-
- ring += info->tail * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
-
- gettimeofday(&start, NULL);
-
-// printf("Waiting %li\n", info->tail);
-// nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_LAST_BD);
-// printf("Last BD(Read): %lx %lx\n", ring, val);
-
- do {
- status_size = NWL_RING_GET(ring, DMA_BD_BUFL_STATUS_OFFSET);
- status = status_size & DMA_BD_STATUS_MASK;
-
-// printf("%i: %lx\n", info->tail, status_size);
-
- if (status & DMA_BD_ERROR_MASK) {
- pcilib_error("NWL DMA Engine reported error in ring descriptor");
- return (size_t)-1;
- }
-
- if (status & DMA_BD_COMP_MASK) {
- if (status & DMA_BD_EOP_MASK) *eop = 1;
- else *eop = 0;
-
- *size = status_size & DMA_BD_BUFL_MASK;
-
-// printf("Status: %lx\n", status_size);
- return info->tail;
- }
-
- usleep(10);
- gettimeofday(&cur, NULL);
- } while ((timeout == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < timeout));
-*/ \ No newline at end of file
diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c
index ae4aacc..ee5f520 100644
--- a/dma/nwl_irq.c
+++ b/dma/nwl_irq.c
@@ -81,7 +81,7 @@ int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags) {
int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
uint32_t val;
- dma_nwl_enable_irq(ctx, PCILIB_DMA_IRQ, 0);
+ dma_nwl_enable_irq((pcilib_dma_context_t*)ctx, PCILIB_DMA_IRQ, 0);
nwl_read_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS);
val |= (DMA_ENG_INT_ENABLE);
diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c
index a87c109..11f7f34 100644
--- a/dma/nwl_loopback.c
+++ b/dma/nwl_loopback.c
@@ -13,6 +13,8 @@
#include "nwl_defines.h"
+#define NWL_BUG_EXTRA_DATA
+
int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) {
uint32_t val;
@@ -66,11 +68,12 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
int iter, i;
int res;
int err;
- size_t bytes;
+ size_t bytes, rbytes;
uint32_t val;
uint32_t *buf, *cmp;
const char *error = NULL;
pcilib_register_value_t regval;
+ size_t packet_size, blocks;
size_t us = 0;
struct timeval start, cur;
@@ -87,8 +90,10 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
else size /= sizeof(uint32_t);
// Not supported
- if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
- else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.;
+ if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) {
+ if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
+ }
+// else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.;
// Stop Generators and drain old data
if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx);
@@ -107,63 +112,107 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
dma_nwl_enable_engine_irq(ctx, writeid);
#endif /* NWL_GENERATE_DMA_IRQ */
- dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t));
+ if (size * sizeof(uint32_t) > NWL_MAX_PACKET_SIZE) {
+ packet_size = NWL_MAX_PACKET_SIZE;
+ blocks = (size * sizeof(uint32_t)) / packet_size + (((size*sizeof(uint32_t))%packet_size)?1:0);
+ } else {
+ packet_size = size * sizeof(uint32_t);
+ blocks = 1;
+ }
+
+ dma_nwl_start_loopback(ctx, direction, packet_size);
// Allocate memory and prepare data
- buf = malloc(size * sizeof(uint32_t));
- cmp = malloc(size * sizeof(uint32_t));
+ buf = malloc(blocks * packet_size * sizeof(uint32_t));
+ cmp = malloc(blocks * packet_size * sizeof(uint32_t));
if ((!buf)||(!cmp)) {
if (buf) free(buf);
if (cmp) free(cmp);
return -1;
}
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e5);
usleep(100000);
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
+
+ // This way causes more problems with garbage
+ //pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1);
}
-//#endif /* DEBUG_HARDWARE */
// Benchmark
for (iter = 0; iter < iterations; iter++) {
memset(cmp, 0x13 + iter, size * sizeof(uint32_t));
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
}
-//#endif /* DEBUG_HARDWARE */
- gettimeofday(&start, NULL);
- if (direction&PCILIB_DMA_TO_DEVICE) {
+ if ((direction&PCILIB_DMA_TO_DEVICE)||(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) {
memcpy(buf, cmp, size * sizeof(uint32_t));
+ if (direction&PCILIB_DMA_TO_DEVICE) {
+ gettimeofday(&start, NULL);
+ }
+
err = pcilib_write_dma(ctx->pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes);
if ((err)||(bytes != size * sizeof(uint32_t))) {
error = "Write failed";
- break;
+ break;
+ }
+
+ if (direction&PCILIB_DMA_TO_DEVICE) {
+ // wait written
+ if (direction == PCILIB_DMA_TO_DEVICE) {
+ dma_nwl_wait_completion(ctx, writeid, PCILIB_DMA_TIMEOUT);
+ }
+ gettimeofday(&cur, NULL);
+ us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
}
}
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1);
}
-//#endif /* DEBUG_HARDWARE */
memset(buf, 0, size * sizeof(uint32_t));
-
- err = pcilib_read_dma(ctx->pcilib, readid, addr, size * sizeof(uint32_t), buf, &bytes);
- gettimeofday(&cur, NULL);
- us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
+ if (direction&PCILIB_DMA_FROM_DEVICE) {
+ gettimeofday(&start, NULL);
+ }
+
+ for (i = 0, bytes = 0; i < blocks; i++) {
+#ifdef NWL_BUG_EXTRA_DATA
+ retry:
+#endif
+
+ err = pcilib_read_dma(ctx->pcilib, readid, addr, packet_size * sizeof(uint32_t), buf + (bytes>>2), &rbytes);
+ if ((err)||(rbytes%sizeof(uint32_t))) {
+ break;
+ }
+#ifdef NWL_BUG_EXTRA_DATA
+ else if (rbytes == 8) {
+ goto retry;
+ }
+#endif
+ bytes += rbytes;
+ }
+
+ if (direction&PCILIB_DMA_FROM_DEVICE) {
+ gettimeofday(&cur, NULL);
+ us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
+ }
+#ifdef NWL_BUG_EXTRA_DATA
+ if ((err)||((bytes != size * sizeof(uint32_t))&&((bytes - 8) != size * sizeof(uint32_t)))) {
+#else
if ((err)||(bytes != size * sizeof(uint32_t))) {
- error = "Read failed";
- break;
+#endif
+ printf("Expected: %zu bytes, but %zu read, error: %i\n", size * sizeof(uint32_t), bytes, err);
+ error = "Read failed";
+ break;
}
+#ifndef NWL_BUG_EXTRA_DATA
if (direction == PCILIB_DMA_BIDIRECTIONAL) {
res = memcmp(buf, cmp, size * sizeof(uint32_t));
if (res) {
@@ -171,7 +220,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
if (buf[i] != cmp[i]) break;
bytes = i;
- printf("Expected: *%lx, Written at position %lu:", 0x13 + iter, bytes);
+ printf("Expected: *0x%lx, Written at dword %lu:", 0x13 + iter, bytes);
for (; (i < size)&&(i < (bytes + 16)); i++) {
if (((i - bytes)%8)==0) printf("\n");
printf("% 10lx", buf[i]);
@@ -182,41 +231,12 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
break;
}
}
-
-#ifdef DEBUG_HARDWARE
- puts("====================================");
-
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", &regval);
- printf("Status1: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", &regval);
- printf("Start address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", &regval);
- printf("End address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", &regval);
- printf("Status2: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", &regval);
- printf("Status3: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", &regval);
- printf("Add_rd_ddr: %i 0x%lx\n", err, regval);
-#endif /* DEBUG_HARDWARE */
-
+#endif
}
-#ifdef DEBUG_HARDWARE
- puts("------------------------------------------------");
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", &regval);
- printf("Status1: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", &regval);
- printf("Start address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", &regval);
- printf("End address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", &regval);
- printf("Status2: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", &regval);
- printf("Status3: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", &regval);
- printf("Add_rd_ddr: %i 0x%lx\n", err, regval);
-#endif /* DEBUG_HARDWARE */
+ if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
+ pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
+ }
if (error) {
pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, iter, err, bytes);
@@ -238,5 +258,5 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
free(cmp);
free(buf);
- return error?-1:(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us);
+ return /*error?-1:*/(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us);
}
diff --git a/dma/nwl_register.c b/dma/nwl_register.c
index 5bb6e16..95b981a 100644
--- a/dma/nwl_register.c
+++ b/dma/nwl_register.c
@@ -26,8 +26,10 @@ int nwl_add_registers(nwl_dma_t *ctx) {
err = pcilib_add_registers(ctx->pcilib, 0, nwl_dma_registers);
if (err) return err;
- err = pcilib_add_registers(ctx->pcilib, 0, nwl_xrawdata_registers);
- if (err) return err;
+ if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) {
+ err = pcilib_add_registers(ctx->pcilib, 0, nwl_xrawdata_registers);
+ if (err) return err;
+ }
for (n = 0; nwl_dma_engine_registers[n].bits; n++) {
diff --git a/dma/nwl_register.h b/dma/nwl_register.h
index 89a8632..2f465bd 100644
--- a/dma/nwl_register.h
+++ b/dma/nwl_register.h
@@ -86,14 +86,6 @@ static pcilib_register_description_t nwl_xrawdata_registers[] = {
{0x9108, 0, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_checker", ""},
{0x9108, 1, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_loopback", ""},
{0x910C, 0, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_data_mistmatch", ""},
-#ifdef DEBUG_HARDWARE
- {0x9050, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9050", ""},
- {0x9080, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9080", ""},
- {0x9090, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9090", ""},
- {0x9100, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9100", ""},
- {0x9110, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9110", ""},
- {0x9160, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9160", ""},
-#endif /* DEBUG_HARDWARE */
{0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL}
};
diff --git a/error.h b/error.h
index 568ef18..5b46ae5 100644
--- a/error.h
+++ b/error.h
@@ -16,7 +16,8 @@ enum {
PCILIB_ERROR_NOTFOUND,
PCILIB_ERROR_OUTOFRANGE,
PCILIB_ERROR_NOTAVAILABLE,
- PCILIB_ERROR_NOTINITIALIZED
+ PCILIB_ERROR_NOTINITIALIZED,
+ PCILIB_ERROR_TOOBIG
} pcilib_errot_t;
diff --git a/pcilib.h b/pcilib.h
index a38fcc9..ee5323e 100644
--- a/pcilib.h
+++ b/pcilib.h
@@ -11,7 +11,8 @@
typedef struct pcilib_s pcilib_t;
typedef void pcilib_context_t;
-typedef void pcilib_dma_context_t;
+typedef struct pcilib_dma_context_s pcilib_dma_context_t;
+
typedef struct pcilib_dma_api_description_s pcilib_dma_api_description_t;
typedef struct pcilib_event_api_description_s pcilib_event_api_description_t;
@@ -63,9 +64,11 @@ typedef enum {
typedef enum {
PCILIB_DMA_FLAGS_DEFAULT = 0,
- PCILIB_DMA_FLAG_EOP = 1,
- PCILIB_DMA_FLAG_WAIT = 2,
- PCILIB_DMA_FLAG_PERSISTENT = 4
+ PCILIB_DMA_FLAG_EOP = 1, /**< last buffer of the packet */
+ PCILIB_DMA_FLAG_WAIT = 2, /**< wait completion of write operation / wait for data during read operation */
+ PCILIB_DMA_FLAG_MULTIPACKET = 4, /**< read multiple packets */
+ PCILIB_DMA_FLAG_PERSISTENT = 8, /**< do not stop DMA engine on application termination / permanently close DMA engine on dma_stop */
+ PCILIB_DMA_FLAG_IGNORE_ERRORS = 16 /**< do not crash on errors, but return appropriate error codes */
} pcilib_dma_flags_t;
typedef enum {
@@ -102,7 +105,20 @@ typedef enum {
#define PCILIB_TIMEOUT_TRIGGER 0
#define PCILIB_IRQ_SOURCE_DEFAULT 0
-typedef int (*pcilib_dma_callback_t)(void *ctx, pcilib_dma_flags_t flags, size_t bufsize, void *buf);
+/**<
+ * Callback function called when new data is read by DMA streaming function
+ * @ctx - DMA Engine context
+ * @flags - DMA Flags
+ * @bufsize - size of data in bytes
+ * @buf - data
+ * @returns
+ * <0 - error, stop streaming (the value is negative error code)
+ * 0 - stop streaming
+ * 1 - wait & read next buffer, fail if no data
+ * 2 - wait & read next buffer, but don't fail if timeout expired
+ * 3 - read next buffer if available (don't wait), don't fail
+ */
+typedef int (*pcilib_dma_callback_t)(void *ctx, pcilib_dma_flags_t flags, size_t bufsize, void *buf);
typedef int (*pcilib_event_callback_t)(pcilib_event_t event, pcilib_event_id_t event_id, void *user);
typedef struct {
@@ -237,6 +253,7 @@ int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma);
int pcilib_stream_dma(pcilib_t *ctx, 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 pcilib_push_dma(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 *written_bytes);
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 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 pcilib_write_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf, size_t *written_bytes);
double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction);