From de984f8b9706cfac79f7658e5b3863e78b052458 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Tue, 12 Jul 2011 09:53:45 +0200 Subject: Suppport DMA modes in console application (not functional yet) --- ToDo | 6 ++ cli.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++--- dma.c | 19 ++++++- dma.h | 10 +++- dma/nwl.c | 4 +- dma/nwl.h | 11 ++-- dma/nwl_buffers.h | 6 +- dma/nwl_dma.h | 8 ++- irq.c | 2 +- pcilib.h | 20 +++++-- tools.c | 18 ++++++ tools.h | 2 + 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 = on = 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 - Start specified DMA engine\n" -" --stop-dma [num] - Stop specified engine or DMA subsystem\n" +" --start-dma [r|w] - Start specified DMA engine\n" +" --stop-dma [num][r|w] - Stop specified engine or DMA subsystem\n" " --wait-irq - Wait for IRQ\n" "\n" " Addressing:\n" @@ -144,7 +157,7 @@ void Usage(int argc, char *argv[], const char *format, ...) { " -a [fifo|dma] - Access type and bits per word (default: 32)\n" " -e - Endianess Little/Big (default: host)\n" " -o - Output to file (default: stdout)\n" -//" -t - Timeout in microseconds\n" +" -t - 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); -- cgit v1.2.3