summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--dma.c46
-rw-r--r--dma/nwl.c108
-rw-r--r--dma/nwl.h6
-rw-r--r--dma/nwl_dma.h7
-rw-r--r--dma/nwl_engine.c15
-rw-r--r--dma/nwl_engine.h3
-rw-r--r--dma/nwl_irq.c14
-rw-r--r--dma/nwl_loopback.c53
-rw-r--r--dma/nwl_loopback.h7
-rw-r--r--pcilib.h2
11 files changed, 181 insertions, 82 deletions
diff --git a/Makefile b/Makefile
index f02a658..0640194 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ include common.mk
###############################################################
# Target definitions
-OBJECTS = pci.o register.o kmem.o irq.o dma.o event.o default.o tools.o dma/nwl.o dma/nwl_register.o dma/nwl_irq.o dma/nwl_engine.o ipecamera/model.o ipecamera/image.o
+OBJECTS = pci.o register.o kmem.o irq.o dma.o event.o default.o tools.o dma/nwl.o dma/nwl_register.o dma/nwl_irq.o dma/nwl_engine.o dma/nwl_loopback.o ipecamera/model.o ipecamera/image.o
libpcilib.so: $(OBJECTS)
echo -e "LD \t$@"
diff --git a/dma.c b/dma.c
index 0619a45..3cba0da 100644
--- a/dma.c
+++ b/dma.c
@@ -55,9 +55,47 @@ int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine,
}
int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+ int err;
+
+ const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx);
+ if (!info) {
+ pcilib_error("DMA is not supported by the device");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (!ctx->model_info.dma_api) {
+ pcilib_error("DMA Engine is not configured in the current model");
+ return PCILIB_ERROR_NOTAVAILABLE;
+ }
+
+ if (!ctx->model_info.dma_api->start_dma) {
+ //pcilib_error("The IRQs are not supported by configured DMA engine");
+ return 0;
+ }
+
+ return ctx->model_info.dma_api->start_dma(ctx->dma_ctx, dma, flags);
}
int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+ int err;
+
+ const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx);
+ if (!info) {
+ pcilib_error("DMA is not supported by the device");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (!ctx->model_info.dma_api) {
+ pcilib_error("DMA Engine is not configured in the current model");
+ return PCILIB_ERROR_NOTAVAILABLE;
+ }
+
+ if (!ctx->model_info.dma_api->stop_dma) {
+ //pcilib_error("The IRQs are not supported by configured DMA engine");
+ return 0;
+ }
+
+ return ctx->model_info.dma_api->stop_dma(ctx->dma_ctx, dma, flags);
}
int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags) {
@@ -75,8 +113,8 @@ int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flag
}
if (!ctx->model_info.dma_api->enable_irq) {
- pcilib_error("The IRQs are not supported by configured DMA engine");
- return PCILIB_ERROR_NOTSUPPORTED;
+ //pcilib_error("The IRQs are not supported by configured DMA engine");
+ return 0;
}
return ctx->model_info.dma_api->enable_irq(ctx->dma_ctx, irq_type, flags);
@@ -97,8 +135,8 @@ int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
}
if (!ctx->model_info.dma_api->disable_irq) {
- pcilib_error("The IRQs are not supported by configured DMA engine");
- return PCILIB_ERROR_NOTSUPPORTED;
+ //pcilib_error("The IRQs are not supported by configured DMA engine");
+ return 0;
}
return ctx->model_info.dma_api->disable_irq(ctx->dma_ctx, flags);
diff --git a/dma/nwl.c b/dma/nwl.c
index ea31e01..c5240f0 100644
--- a/dma/nwl.c
+++ b/dma/nwl.c
@@ -15,73 +15,62 @@
#include "nwl_defines.h"
+int dma_nwl_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+ nwl_dma_t *ctx = (nwl_dma_t*)vctx;
-
-int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) {
- uint32_t val;
-
- val = packet_size;
- nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS);
-
- switch (direction) {
- case PCILIB_DMA_BIDIRECTIONAL:
- val = LOOPBACK;
- break;
- case PCILIB_DMA_TO_DEVICE:
- return -1;
- case PCILIB_DMA_FROM_DEVICE:
- val = PKTGENR;
- break;
+ if (!ctx->started) {
+ // global initialization, should we do anything?
+ ctx->started = 1;
}
- nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
- nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
- return 0;
-}
-
-int dma_nwl_stop_loopback(nwl_dma_t *ctx) {
- uint32_t val;
-
- val = 0;
- nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
- nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
- return 0;
-}
-
-
-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, 0);
-#endif /* NWL_GENERATE_DMA_IRQ */
-
- ctx->started = 1;
+ if (dma == PCILIB_DMA_ENGINE_INVALID) return 0;
+ else if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK;
- return 0;
+ if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->engines[dma].preserve = 1;
+ return dma_nwl_start_engine(ctx, dma);
}
-int dma_nwl_stop(nwl_dma_t *ctx) {
+int dma_nwl_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
int err;
+ int preserving = 0;
- pcilib_dma_engine_t i;
+ nwl_dma_t *ctx = (nwl_dma_t*)vctx;
- ctx->started = 0;
+ if (!ctx->started) return 0;
- err = dma_nwl_free_irq(ctx);
- if (err) return err;
+ // stop everything
+ if (dma == PCILIB_DMA_ENGINE_INVALID) {
+ for (dma = 0; dma < ctx->n_engines; dma++) {
+ if (flags&PCILIB_DMA_FLAG_PERMANENT) {
+ ctx->engines[dma].preserve = 0;
+ }
+
+ if (ctx->engines[dma].preserve) preserving = 1;
+ else {
+ err = dma_nwl_stop_engine(ctx, dma);
+ if (err) return err;
+ }
+ }
+
+ // global cleanup, should we do anything?
+ if (!preserving) {
+ ctx->started = 0;
+ }
+
+ return 0;
+ }
- err = dma_nwl_stop_loopback(ctx);
- if (err) return err;
+ if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK;
- for (i = 0; i < ctx->n_engines; i++) {
- err = dma_nwl_stop_engine(ctx, i);
- if (err) return err;
+ // ignorign previous setting if flag specified
+ if (flags&PCILIB_DMA_FLAG_PERMANENT) {
+ ctx->engines[dma].preserve = 0;
}
- return 0;
+ // Do not close DMA if preservation mode is set
+ if (ctx->engines[dma].preserve) return 0;
+
+ return dma_nwl_stop_engine(ctx, dma);
}
@@ -134,13 +123,16 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
}
void dma_nwl_free(pcilib_dma_context_t *vctx) {
+ int err;
+
pcilib_dma_engine_t i;
nwl_dma_t *ctx = (nwl_dma_t*)vctx;
- if (ctx) {
- for (i = 0; i < ctx->n_engines; i++) dma_nwl_stop_engine(ctx, i);
- dma_nwl_stop(ctx);
- free(ctx);
- }
+
+ dma_nwl_stop_loopback(ctx);
+ dma_nwl_free_irq(ctx);
+ dma_nwl_stop(ctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT);
+
+ free(ctx);
}
diff --git a/dma/nwl.h b/dma/nwl.h
index 481dca4..6d86e86 100644
--- a/dma/nwl.h
+++ b/dma/nwl.h
@@ -19,6 +19,7 @@ typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t;
#include "nwl_irq.h"
#include "nwl_register.h"
#include "nwl_engine.h"
+#include "nwl_loopback.h"
#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess)
#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess)
@@ -44,11 +45,12 @@ 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 */
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 */
-
+ int irq_started; /**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */
+ int loopback_started; /**< indicates that benchmarking subsystem is initialized */
+
pcilib_dma_engine_t n_engines;
pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1];
};
diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h
index 0ed8158..883dc29 100644
--- a/dma/nwl_dma.h
+++ b/dma/nwl_dma.h
@@ -10,6 +10,9 @@ 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_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+int dma_nwl_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, 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);
@@ -21,8 +24,8 @@ pcilib_dma_api_description_t nwl_dma_api = {
dma_nwl_free,
dma_nwl_enable_irq,
dma_nwl_disable_irq,
- NULL,
- NULL,
+ dma_nwl_start,
+ dma_nwl_stop,
dma_nwl_write_fragment,
dma_nwl_stream_read,
dma_nwl_benchmark
diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c
index 3258da6..11137b9 100644
--- a/dma/nwl_engine.c
+++ b/dma/nwl_engine.c
@@ -1,3 +1,5 @@
+#define _BSD_SOURCE
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,6 +14,8 @@
#include "nwl_defines.h"
+#include "nwl_buffers.h"
+
int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
uint32_t val;
@@ -58,7 +62,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
pcilib_nwl_engine_description_t *info = ctx->engines + dma;
char *base = ctx->engines[dma].base_addr;
-
+
if (info->started) return 0;
// Disable IRQs
@@ -100,9 +104,6 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
}
- err = dma_nwl_start(ctx);
- if (err) return err;
-
err = dma_nwl_allocate_engine_buffers(ctx, info);
if (err) return err;
@@ -182,8 +183,6 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
return 0;
}
-#include "nwl_buffers.h"
-
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 err;
size_t pos;
@@ -192,7 +191,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_engine(ctx, dma);
+ err = dma_nwl_start(ctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
if (err) return err;
if (data) {
@@ -238,7 +237,7 @@ 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_engine(ctx, dma);
+ err = dma_nwl_start(ctx, dma, PCILIB_DMA_FLAGS_DEFAULT);
if (err) return err;
do {
diff --git a/dma/nwl_engine.h b/dma/nwl_engine.h
index 778dc8a..176eaeb 100644
--- a/dma/nwl_engine.h
+++ b/dma/nwl_engine.h
@@ -2,6 +2,9 @@
#define _PCILIB_DMA_NWL_ENGINE_H
int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base);
+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);
+
#endif /* _PCILIB_DMA_NWL_ENGINE_H */
diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c
index 04ac908..3a9d9a2 100644
--- a/dma/nwl_irq.c
+++ b/dma/nwl_irq.c
@@ -19,16 +19,16 @@ int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val) {
if (val&DMA_USER_INT_ENABLE) ctx->irq_preserve |= PCILIB_EVENT_IRQ;
}
- ctx->irq_init = 1;
+ ctx->irq_started = 1;
return 0;
}
int dma_nwl_free_irq(nwl_dma_t *ctx) {
- if (ctx->irq_init) {
+ if (ctx->irq_started) {
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;
+ ctx->irq_started = 0;
}
return 0;
}
@@ -39,12 +39,12 @@ int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcili
if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->irq_preserve |= type;
- if (ctx->irq_enabled == type) return 0;
+ if ((ctx->irq_enabled&type) == 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);
+ if (!ctx->irq_started) 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);
@@ -68,7 +68,7 @@ int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags) {
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);
+ if (!ctx->irq_started) 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);
@@ -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, ctx->irq_enabled|PCILIB_DMA_IRQ, 0);
+ dma_nwl_enable_irq(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
new file mode 100644
index 0000000..9c74b14
--- /dev/null
+++ b/dma/nwl_loopback.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "pci.h"
+#include "pcilib.h"
+#include "error.h"
+#include "tools.h"
+#include "nwl.h"
+
+#include "nwl_defines.h"
+
+
+int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) {
+ uint32_t val;
+
+ // Re-initializing always
+
+ val = packet_size;
+ nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS);
+
+ switch (direction) {
+ case PCILIB_DMA_BIDIRECTIONAL:
+ val = LOOPBACK;
+ break;
+ case PCILIB_DMA_TO_DEVICE:
+ return -1;
+ case PCILIB_DMA_FROM_DEVICE:
+ val = PKTGENR;
+ break;
+ }
+
+ nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
+ nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
+
+ ctx->loopback_started = 1;
+
+ return 0;
+}
+
+int dma_nwl_stop_loopback(nwl_dma_t *ctx) {
+ uint32_t val = 0;
+
+ if (ctx->loopback_started) {
+ nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
+ nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
+ ctx->loopback_started = 0;
+ }
+
+ return 0;
+}
diff --git a/dma/nwl_loopback.h b/dma/nwl_loopback.h
new file mode 100644
index 0000000..63c8446
--- /dev/null
+++ b/dma/nwl_loopback.h
@@ -0,0 +1,7 @@
+#ifndef _PCILIB_NWL_LOOPBACK_H
+#define _PCILIB_NWL_LOOPBACK_H
+
+int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size);
+int dma_nwl_stop_loopback(nwl_dma_t *ctx);
+
+#endif /* _PCILIB_NWL_LOOPBACK_H */
diff --git a/pcilib.h b/pcilib.h
index 3e82c99..42be921 100644
--- a/pcilib.h
+++ b/pcilib.h
@@ -86,6 +86,8 @@ typedef enum {
#define PCILIB_BAR0 0
#define PCILIB_BAR1 1
#define PCILIB_DMA_ENGINE_INVALID ((pcilib_dma_engine_t)-1)
+#define PCILIB_DMA_ENGINE_ALL ((pcilib_dma_engine_t)-1)
+#define PCILIB_DMA_FLAGS_DEFAULT ((pcilib_dma_flags_t)0)
#define PCILIB_DMA_ENGINE_ADDR_INVALID ((pcilib_dma_engine_addr_t)-1)
#define PCILIB_REGISTER_INVALID ((pcilib_register_t)-1)
#define PCILIB_ADDRESS_INVALID ((uintptr_t)-1)