summaryrefslogtreecommitdiffstats
path: root/cli.c
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 /cli.c
parent5b4fbcc62d4544aee7adf0a92a2db31197bae305 (diff)
downloadpcitool-de984f8b9706cfac79f7658e5b3863e78b052458.tar.gz
pcitool-de984f8b9706cfac79f7658e5b3863e78b052458.tar.bz2
pcitool-de984f8b9706cfac79f7658e5b3863e78b052458.tar.xz
pcitool-de984f8b9706cfac79f7658e5b3863e78b052458.zip
Suppport DMA modes in console application (not functional yet)
Diffstat (limited to 'cli.c')
-rw-r--r--cli.c160
1 files changed, 151 insertions, 9 deletions
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);