summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-12 09:53:45 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-12 09:53:45 +0200
commitde984f8b9706cfac79f7658e5b3863e78b052458 (patch)
treef989701212bb2de4d224387344929853e4055d27
parent5b4fbcc62d4544aee7adf0a92a2db31197bae305 (diff)
downloadipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.gz
ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.bz2
ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.xz
ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.zip
Suppport DMA modes in console application (not functional yet)
-rw-r--r--ToDo6
-rw-r--r--cli.c160
-rw-r--r--dma.c19
-rw-r--r--dma.h10
-rw-r--r--dma/nwl.c4
-rw-r--r--dma/nwl.h11
-rw-r--r--dma/nwl_buffers.h6
-rw-r--r--dma/nwl_dma.h8
-rw-r--r--irq.c2
-rw-r--r--pcilib.h20
-rw-r--r--tools.c18
-rw-r--r--tools.h2
12 files changed, 233 insertions, 33 deletions
diff --git a/ToDo b/ToDo
index e61ca28..1f3129c 100644
--- a/ToDo
+++ b/ToDo
@@ -1,3 +1,9 @@
+1. Read registers from XML description. It also makes sense to provide
+ formal XML-based language for DMA implementation.
+ a) Writting/Reading register values
+ b) Wait until <register1>=<value> on <register2>=<value> report error
+ c) ... ?
2. Hint for register value representation in the bank (hex, decimal)
3. Implement software registers
4. Support FIFO reads/writes from/to registers
+5. Provide OR and AND operations on registers in cli
diff --git a/cli.c b/cli.c
index 2e0765f..102c004 100644
--- a/cli.c
+++ b/cli.c
@@ -20,6 +20,7 @@
//#include "pci.h"
#include "tools.h"
#include "kernel.h"
+#include "error.h"
/* defines */
#define MAX_KBUF 14
@@ -37,7 +38,8 @@
#define isnumber pcilib_isnumber
#define isxnumber pcilib_isxnumber
-
+#define isnumber_n pcilib_isnumber_n
+#define isxnumber_n pcilib_isxnumber_n
typedef uint8_t access_t;
@@ -51,7 +53,10 @@ typedef enum {
MODE_WRITE,
MODE_WRITE_REGISTER,
MODE_RESET,
- MODE_GRAB
+ MODE_GRAB,
+ MODE_START_DMA,
+ MODE_STOP_DMA,
+ MODE_WAIT_IRQ
} MODE;
typedef enum {
@@ -68,6 +73,7 @@ typedef enum {
OPT_ENDIANESS = 'e',
OPT_SIZE = 's',
OPT_OUTPUT = 'o',
+ OPT_TIMEOUT = 't',
OPT_INFO = 'i',
OPT_BENCHMARK = 'p',
OPT_LIST = 'l',
@@ -76,6 +82,9 @@ typedef enum {
OPT_GRAB = 'g',
OPT_QUIETE = 'q',
OPT_RESET = 128,
+ OPT_START_DMA = 129,
+ OPT_STOP_DMA = 130,
+ OPT_WAIT_IRQ = 131,
OPT_HELP = 'h',
} OPTIONS;
@@ -87,6 +96,7 @@ static struct option long_options[] = {
{"endianess", required_argument, 0, OPT_ENDIANESS },
{"size", required_argument, 0, OPT_SIZE },
{"output", required_argument, 0, OPT_OUTPUT },
+ {"timeout", required_argument, 0, OPT_TIMEOUT },
{"info", no_argument, 0, OPT_INFO },
{"list", no_argument, 0, OPT_LIST },
{"reset", no_argument, 0, OPT_RESET },
@@ -94,6 +104,9 @@ static struct option long_options[] = {
{"read", optional_argument, 0, OPT_READ },
{"write", optional_argument, 0, OPT_WRITE },
{"grab", optional_argument, 0, OPT_GRAB },
+ {"start-dma", required_argument, 0, OPT_START_DMA },
+ {"stop-dma", optional_argument, 0, OPT_STOP_DMA },
+ {"wait-irq", optional_argument, 0, OPT_WAIT_IRQ },
{"quiete", no_argument, 0, OPT_QUIETE },
{"help", no_argument, 0, OPT_HELP },
{ 0, 0, 0, 0 }
@@ -128,8 +141,8 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" --help - Help message\n"
"\n"
" DMA Modes:\n"
-" --start-dma <num> - Start specified DMA engine\n"
-" --stop-dma [num] - Stop specified engine or DMA subsystem\n"
+" --start-dma <num>[r|w] - Start specified DMA engine\n"
+" --stop-dma [num][r|w] - Stop specified engine or DMA subsystem\n"
" --wait-irq <source> - Wait for IRQ\n"
"\n"
" Addressing:\n"
@@ -144,7 +157,7 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" -a [fifo|dma]<bits> - Access type and bits per word (default: 32)\n"
" -e <l|b> - Endianess Little/Big (default: host)\n"
" -o <file> - Output to file (default: stdout)\n"
-//" -t <timeout> - Timeout in microseconds\n"
+" -t <timeout> - Timeout in microseconds\n"
"\n"
" Information:\n"
" -q - Quiete mode (suppress warnings)\n"
@@ -547,7 +560,7 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, p
switch (mode) {
case ACCESS_DMA:
dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
- if (dmaid == PCILIB_DMA_INVALID) Error("Invalid DMA engine (%lu) is specified", 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;
@@ -722,7 +735,7 @@ int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
switch (mode) {
case ACCESS_DMA:
dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
- if (dmaid == PCILIB_DMA_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
+ if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
err = pcilib_write_dma(handle, dmaid, addr, size, buf, &ret);
if ((err)||(ret != size)) {
if (!ret) Error("No data is written by DMA engine");
@@ -845,12 +858,73 @@ int Grab(pcilib_t *handle, const char *event, const char *output) {
return 0;
}
+
+int StartStopDMA(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, int start) {
+ int err;
+ pcilib_dma_engine_t dmaid;
+
+ if (dma_direction&PCILIB_DMA_FROM_DEVICE) {
+ if (dma == PCILIB_DMA_ENGINE_ADDR_INVALID) {
+ if (start) Error("DMA engine should be specified");
+ dmaid = PCILIB_DMA_ENGINE_INVALID;
+ } else {
+ dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
+ if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (C2S %lu) is specified", dma);
+ }
+
+ if (start) {
+ err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERMANENT);
+ if (err) Error("Error starting DMA engine (C2S %lu)", dma);
+ } else {
+ err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERMANENT);
+ if (err) Error("Error stopping DMA engine (C2S %lu)", dma);
+ }
+ }
+
+ if (dma_direction&PCILIB_DMA_TO_DEVICE) {
+ if (dma == PCILIB_DMA_ENGINE_ADDR_INVALID) {
+ if (start) Error("DMA engine should be specified");
+ dmaid = PCILIB_DMA_ENGINE_INVALID;
+ } else {
+ dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
+ if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (S2C %lu) is specified", dma);
+ }
+
+ if (start) {
+ err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERMANENT);
+ if (err) Error("Error starting DMA engine (S2C %lu)", dma);
+ } else {
+ err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERMANENT);
+ if (err) Error("Error stopping DMA engine (S2C %lu)", dma);
+ }
+ }
+
+ return 0;
+}
+
+int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_source_t irq_source, pcilib_timeout_t timeout) {
+ int err;
+ size_t count;
+
+ err = pcilib_enable_irq(handle, 0);
+ if (err) Error("Error enabling IRQs");
+
+ err = pcilib_wait_irq(handle, irq_source, timeout, &count);
+ if (err) {
+ if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout waiting for IRQ");
+ else Error("Error waiting for IRQ");
+ }
+
+ return 0;
+}
+
+
int main(int argc, char **argv) {
int i;
long itmp;
unsigned char c;
- char *num_offset;
+ const char *num_offset;
int details = 0;
int quiete = 0;
@@ -867,13 +941,17 @@ int main(int argc, char **argv) {
const char *bank = NULL;
char **data = NULL;
const char *event = NULL;
+ const char *dma_channel = NULL;
+ pcilib_irq_source_t irq_source;
+ pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
- pcilib_dma_engine_addr_t dma;
+ pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID;
uintptr_t start = -1;
size_t size = 1;
access_t access = 4;
int skip = 0;
int endianess = 0;
+ size_t timeout = 0;
const char *output = NULL;
pcilib_t *handle;
@@ -932,6 +1010,32 @@ int main(int argc, char **argv) {
if (optarg) event = optarg;
else if ((optind < argc)&&(argv[optind][0] != '-')) event = argv[optind++];
break;
+ case OPT_START_DMA:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_START_DMA;
+ if (optarg) dma_channel = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
+ break;
+ case OPT_STOP_DMA:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_STOP_DMA;
+ if (optarg) dma_channel = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
+ break;
+ case OPT_WAIT_IRQ:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_WAIT_IRQ;
+ if (optarg) num_offset = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
+
+ if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
+ Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
+
+ irq_source = itmp;
+ break;
case OPT_DEVICE:
fpga_device = optarg;
break;
@@ -994,6 +1098,10 @@ int main(int argc, char **argv) {
} else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);
break;
+ case OPT_TIMEOUT:
+ if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1))
+ Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
+ break;
case OPT_OUTPUT:
output = optarg;
break;
@@ -1050,6 +1158,31 @@ int main(int argc, char **argv) {
} else ++mode;
}
break;
+ case MODE_START_DMA:
+ case MODE_STOP_DMA:
+ if ((dma_channel)&&(*dma_channel)) {
+ itmp = strlen(dma_channel) - 1;
+ if (dma_channel[itmp] == 'r') dma_direction = PCILIB_DMA_FROM_DEVICE;
+ else if (dma_channel[itmp] == 'w') dma_direction = PCILIB_DMA_TO_DEVICE;
+
+ if (dma_direction != PCILIB_DMA_BIDIRECTIONAL) itmp--;
+
+ if (strncmp(dma_channel, "dma", 3)) num_offset = dma_channel;
+ else {
+ num_offset = dma_channel + 3;
+ itmp -= 3;
+ }
+
+ if (bank) {
+ if (strncmp(num_offset, bank, itmp)) Usage(argc, argv, "Conflicting DMA channels are specified in mode parameter (%s) and bank parameter (%s)", dma_channel, bank);
+ }
+
+ if (!isnumber_n(num_offset, itmp))
+ Usage(argc, argv, "Invalid DMA channel (%s) is specified", dma_channel);
+
+ dma = atoi(num_offset);
+ }
+ break;
default:
if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
}
@@ -1146,6 +1279,15 @@ int main(int argc, char **argv) {
case MODE_GRAB:
Grab(handle, event, output);
break;
+ case MODE_START_DMA:
+ StartStopDMA(handle, model_info, dma, dma_direction, 1);
+ break;
+ case MODE_STOP_DMA:
+ StartStopDMA(handle, model_info, dma, dma_direction, 0);
+ break;
+ case MODE_WAIT_IRQ:
+ WaitIRQ(handle, model_info, irq_source, timeout);
+ break;
}
pcilib_close(handle);
diff --git a/dma.c b/dma.c
index fecc0a0..42b14cc 100644
--- a/dma.c
+++ b/dma.c
@@ -47,13 +47,26 @@ pcilib_dma_engine_t pcilib_find_dma_by_addr(pcilib_t *ctx, pcilib_dma_direction_
}
if (info->engines[i]) return i;
- return PCILIB_DMA_INVALID;
+ return PCILIB_DMA_ENGINE_INVALID;
}
int pcilib_set_dma_engine_description(pcilib_t *ctx, pcilib_dma_engine_t engine, pcilib_dma_engine_description_t *desc) {
ctx->dma_info.engines[engine] = desc;
}
+int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+}
+
+int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+}
+
+int pcilib_enable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
+}
+
+int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
+}
+
+
typedef struct {
size_t size;
void *data;
@@ -79,7 +92,7 @@ static int pcilib_dma_skip_callback(void *arg, pcilib_dma_flags_t flags, size_t
return 1;
}
-int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, pcilib_dma_callback_t cb, void *cbattr) {
+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 err;
const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx);
@@ -135,7 +148,7 @@ int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) {
}
-int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, void *buf, size_t *written) {
+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) {
int err;
const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx);
diff --git a/dma.h b/dma.h
index 38c921b..e3db838 100644
--- a/dma.h
+++ b/dma.h
@@ -7,8 +7,14 @@ struct pcilib_dma_api_description_s {
pcilib_dma_context_t *(*init)(pcilib_t *ctx);
void (*free)(pcilib_dma_context_t *ctx);
- int (*push)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, void *buf, size_t *written);
- int (*stream)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_t timeout, pcilib_dma_callback_t cb, void *cbattr);
+ int (*pcilib_start_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+ int (*pcilib_stop_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+
+ int (*pcilib_enable_irq)(pcilib_dma_context_t *ctx, pcilib_dma_flags_t flags);
+ int (*pcilib_disable_irq)(pcilib_dma_context_t *ctx, pcilib_dma_flags_t flags);
+
+ int (*push)(pcilib_dma_context_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);
+ int (*stream)(pcilib_dma_context_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);
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);
};
diff --git a/dma/nwl.c b/dma/nwl.c
index e433997..6c3079a 100644
--- a/dma/nwl.c
+++ b/dma/nwl.c
@@ -341,7 +341,7 @@ int dma_nwl_sync_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info,
#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, size_t timeout, void *data, size_t *written) {
+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;
size_t bufnum;
@@ -383,7 +383,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
return 0;
}
-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, size_t timeout, pcilib_dma_callback_t cb, void *cbattr) {
+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;
size_t res = 0;
size_t bufnum;
diff --git a/dma/nwl.h b/dma/nwl.h
index cb162de..1ee6f5d 100644
--- a/dma/nwl.h
+++ b/dma/nwl.h
@@ -17,8 +17,9 @@ typedef struct {
pcilib_kmem_handle_t *ring;
pcilib_kmem_handle_t *pages;
- int started; // indicates if DMA buffers are initialized and reading is allowed
- int writting; // indicates if we are in middle of writting packet
+ int started; /**< indicates that DMA buffers are initialized and reading is allowed */
+ int writting; /**< indicates that we are in middle of writting packet */
+ int preserve; /**< indicates that DMA should not be stopped during clean-up */
} pcilib_nwl_engine_description_t;
@@ -28,9 +29,9 @@ struct nwl_dma_s {
pcilib_register_bank_description_t *dma_bank;
char *base_addr;
- pcilib_irq_type_t irq_enabled;
-
- int started;
+ pcilib_irq_type_t irq_enabled; /**< indicates that IRQs are enabled */
+ int 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;
pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1];
diff --git a/dma/nwl_buffers.h b/dma/nwl_buffers.h
index fe4b0a3..e059b97 100644
--- a/dma/nwl_buffers.h
+++ b/dma/nwl_buffers.h
@@ -102,7 +102,7 @@ next_buffer:
}
-static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info, size_t n_buffers, size_t timeout) {
+static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info, size_t n_buffers, pcilib_timeout_t timeout) {
struct timeval start, cur;
size_t res, n = 0;
@@ -139,7 +139,7 @@ static size_t dma_nwl_get_next_buffer(nwl_dma_t * ctx, pcilib_nwl_engine_descrip
return info->head;
}
-static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t size, int eop, size_t timeout) {
+static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t size, int eop, pcilib_timeout_t timeout) {
int flags;
uint32_t val;
@@ -178,7 +178,7 @@ static int dma_nwl_push_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *
}
-static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t *size, int *eop, size_t timeout) {
+static size_t dma_nwl_wait_buffer(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, size_t *size, int *eop, pcilib_timeout_t timeout) {
uint32_t val;
struct timeval start, cur;
uint32_t status_size, status, control;
diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h
index b8d6cce..5ba9b18 100644
--- a/dma/nwl_dma.h
+++ b/dma/nwl_dma.h
@@ -11,8 +11,8 @@ 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_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, size_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, size_t timeout, pcilib_dma_callback_t cb, void *cbattr);
+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,6 +20,10 @@ 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,
+ NULL,
+ NULL,
dma_nwl_write_fragment,
dma_nwl_stream_read,
dma_nwl_benchmark
diff --git a/irq.c b/irq.c
index 0154511..6b2164c 100644
--- a/irq.c
+++ b/irq.c
@@ -17,7 +17,7 @@
#include "tools.h"
#include "error.h"
-int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, size_t timeout, size_t *count) {
+int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, pcilib_timeout_t timeout, size_t *count) {
int err;
interrupt_wait_t arg = { 0 };
diff --git a/pcilib.h b/pcilib.h
index 353a4b9..d6b4bda 100644
--- a/pcilib.h
+++ b/pcilib.h
@@ -37,6 +37,7 @@ typedef uint8_t pcilib_dma_engine_addr_t;
typedef uint8_t pcilib_dma_engine_t;
typedef uint64_t pcilib_event_id_t;
typedef uint32_t pcilib_event_t;
+typedef uint64_t pcilib_timeout_t;
typedef enum {
PCILIB_HOST_ENDIAN = 0,
@@ -70,7 +71,8 @@ typedef enum {
typedef enum {
PCILIB_DMA_FLAGS_DEFAULT = 0,
PCILIB_DMA_FLAG_EOP = 1,
- PCILIB_DMA_FLAG_WAIT = 2
+ PCILIB_DMA_FLAG_WAIT = 2,
+ PCILIB_DMA_FLAG_PERMANENT = 4
} pcilib_dma_flags_t;
typedef enum {
@@ -83,7 +85,8 @@ typedef enum {
#define PCILIB_BAR_INVALID ((pcilib_bar_t)-1)
#define PCILIB_BAR0 0
#define PCILIB_BAR1 1
-#define PCILIB_DMA_INVALID ((pcilib_dma_engine_t)-1)
+#define PCILIB_DMA_ENGINE_INVALID ((pcilib_dma_engine_t)-1)
+#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)
#define PCILIB_REGISTER_BANK_INVALID ((pcilib_register_bank_t)-1)
@@ -99,7 +102,7 @@ typedef enum {
#define PCILIB_EVENTS_ALL ((pcilib_event_t)-1)
#define PCILIB_EVENT_INVALID ((pcilib_event_t)-1)
#define PCILIB_EVENT_ID_INVALID 0
-#define PCILIB_TIMEOUT_INFINITE ((size_t)-1)
+#define PCILIB_TIMEOUT_INFINITE ((pcilib_timeout_t)-1)
#define PCILIB_TIMEOUT_IMMEDIATE 0
typedef int (*pcilib_dma_callback_t)(void *ctx, pcilib_dma_flags_t flags, size_t bufsize, void *buf);
@@ -199,8 +202,13 @@ pcilib_context_t *pcilib_get_implementation_context(pcilib_t *ctx);
pcilib_t *pcilib_open(const char *device, pcilib_model_t model);
void pcilib_close(pcilib_t *ctx);
+int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+int pcilib_enable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags);
+int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags);
+
int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_source_t source);
-int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, size_t timeout, size_t *count);
+int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, pcilib_timeout_t timeout, size_t *count);
void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar);
void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data);
@@ -220,8 +228,8 @@ int pcilib_write_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t f
int pcilib_read_fifo(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, uint8_t fifo_size, size_t n, void *buf);
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, size_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, size_t timeout, void *buf, size_t *written_bytes);
+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_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);
diff --git a/tools.c b/tools.c
index 1ff3177..8b39669 100644
--- a/tools.c
+++ b/tools.c
@@ -26,6 +26,24 @@ int pcilib_isxnumber(const char *str) {
return 1;
}
+int pcilib_isnumber_n(const char *str, size_t len) {
+ int i = 0;
+ for (i = 0; (str[i])&&(i < len); i++)
+ if (!isdigit(str[i])) return 0;
+ return 1;
+}
+
+int pcilib_isxnumber_n(const char *str, size_t len) {
+ int i = 0;
+
+ if ((len > 1)&&(str[0] == '0')&&((str[1] == 'x')||(str[1] == 'X'))) i += 2;
+
+ for (; (str[i])&&(i < len); i++)
+ if (!isxdigit(str[i])) return 0;
+
+ return 1;
+}
+
uint16_t pcilib_swap16(uint16_t x) {
return (((x<<8)&0xFFFF) | ((x>>8)&0xFFFF));
diff --git a/tools.h b/tools.h
index 3bd1b20..121f1a6 100644
--- a/tools.h
+++ b/tools.h
@@ -12,6 +12,8 @@
int pcilib_isnumber(const char *str);
int pcilib_isxnumber(const char *str);
+int pcilib_isnumber_n(const char *str, size_t len);
+int pcilib_isxnumber_n(const char *str, size_t len);
uint16_t pcilib_swap16(uint16_t x);
uint32_t pcilib_swap32(uint32_t x);