diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-12 09:53:45 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-12 09:53:45 +0200 |
commit | de984f8b9706cfac79f7658e5b3863e78b052458 (patch) | |
tree | f989701212bb2de4d224387344929853e4055d27 /cli.c | |
parent | 5b4fbcc62d4544aee7adf0a92a2db31197bae305 (diff) | |
download | ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.gz ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.bz2 ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.tar.xz ipecamera-de984f8b9706cfac79f7658e5b3863e78b052458.zip |
Suppport DMA modes in console application (not functional yet)
Diffstat (limited to 'cli.c')
-rw-r--r-- | cli.c | 160 |
1 files changed, 151 insertions, 9 deletions
@@ -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); |