summaryrefslogtreecommitdiffstats
path: root/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli.c')
-rw-r--r--cli.c443
1 files changed, 384 insertions, 59 deletions
diff --git a/cli.c b/cli.c
index e273384..cb1d333 100644
--- a/cli.c
+++ b/cli.c
@@ -16,6 +16,7 @@
#include <alloca.h>
#include <arpa/inet.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
@@ -76,7 +77,11 @@ typedef enum {
MODE_LIST_DMA,
MODE_LIST_DMA_BUFFERS,
MODE_READ_DMA_BUFFER,
+ MODE_ENABLE_IRQ,
+ MODE_DISABLE_IRQ,
+ MODE_ACK_IRQ,
MODE_WAIT_IRQ,
+ MODE_ALLOC_KMEM,
MODE_LIST_KMEM,
MODE_READ_KMEM,
MODE_FREE_KMEM
@@ -85,7 +90,8 @@ typedef enum {
typedef enum {
ACCESS_BAR,
ACCESS_DMA,
- ACCESS_FIFO
+ ACCESS_FIFO,
+ ACCESS_CONFIG
} ACCESS_MODE;
typedef enum {
@@ -140,12 +146,20 @@ typedef enum {
OPT_READ_DMA_BUFFER,
OPT_START_DMA,
OPT_STOP_DMA,
+ OPT_ENABLE_IRQ,
+ OPT_DISABLE_IRQ,
+ OPT_ACK_IRQ,
OPT_WAIT_IRQ,
OPT_ITERATIONS,
+ OPT_ALLOC_KMEM,
OPT_LIST_KMEM,
OPT_FREE_KMEM,
OPT_READ_KMEM,
+ OPT_BLOCK_SIZE,
+ OPT_ALIGNMENT,
+ OPT_TYPE,
OPT_FORCE,
+ OPT_VERIFY,
OPT_WAIT,
OPT_MULTIPACKET,
OPT_VERBOSE
@@ -182,13 +196,21 @@ static struct option long_options[] = {
{"list-dma-engines", no_argument, 0, OPT_LIST_DMA },
{"list-dma-buffers", required_argument, 0, OPT_LIST_DMA_BUFFERS },
{"read-dma-buffer", required_argument, 0, OPT_READ_DMA_BUFFER },
+ {"enable-irq", optional_argument, 0, OPT_ENABLE_IRQ },
+ {"disable-irq", optional_argument, 0, OPT_DISABLE_IRQ },
+ {"acknowledge-irq", optional_argument, 0, OPT_ACK_IRQ },
{"wait-irq", optional_argument, 0, OPT_WAIT_IRQ },
- {"list-kernel-memory", no_argument, 0, OPT_LIST_KMEM },
+ {"list-kernel-memory", optional_argument, 0, OPT_LIST_KMEM },
{"read-kernel-memory", required_argument, 0, OPT_READ_KMEM },
+ {"alloc-kernel-memory", required_argument, 0, OPT_ALLOC_KMEM },
{"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM },
+ {"type", required_argument, 0, OPT_TYPE },
+ {"block-size", required_argument, 0, OPT_BLOCK_SIZE },
+ {"alignment", required_argument, 0, OPT_ALIGNMENT },
{"quiete", no_argument, 0, OPT_QUIETE },
{"verbose", optional_argument, 0, OPT_VERBOSE },
{"force", no_argument, 0, OPT_FORCE },
+ {"verify", no_argument, 0, OPT_VERIFY },
{"multipacket", no_argument, 0, OPT_MULTIPACKET },
{"wait", no_argument, 0, OPT_WAIT },
{"help", no_argument, 0, OPT_HELP },
@@ -226,18 +248,24 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" --trigger [event] - Trigger Events\n"
" -g [event] - Grab Events\n"
"\n"
+" IRQ Modes:\n"
+" --enable-irq [type] - Enable IRQs\n"
+" --disable-irq [type] - Disable IRQs\n"
+" --acknowledge-irq <source> - Clean IRQ queue\n"
+" --wait-irq <source> - Wait for IRQ\n"
+
" DMA Modes:\n"
" --start-dma <num>[r|w] - Start specified DMA engine\n"
" --stop-dma [num[r|w]] - Stop specified engine or DMA subsystem\n"
" --list-dma-engines - List active DMA engines\n"
" --list-dma-buffers <dma> - List buffers for specified DMA engine\n"
" --read-dma-buffer <dma:buf> - Read the specified buffer\n"
-" --wait-irq <source> - Wait for IRQ\n"
"\n"
" Kernel Modes:\n"
-" --list-kernel-memory - List kernel buffers\n"
+" --list-kernel-memory [use] - List kernel buffers\n"
" --read-kernel-memory <blk> - Read the specified block of the kernel memory\n"
" block is specified as: use:block_number\n"
+" --alloc-kernel-memory <use> - Allocate kernel buffers (DANGEROUS)\n"
" --free-kernel-memory <use> - Cleans lost kernel space buffers (DANGEROUS)\n"
" dma - Remove all buffers allocated by DMA subsystem\n"
" #number - Remove all buffers with the specified use id\n"
@@ -251,10 +279,11 @@ void Usage(int argc, char *argv[], const char *format, ...) {
"\n"
" Options:\n"
" -s <size> - Number of words (default: 1)\n"
-" -a [fifo|dma]<bits> - Access type and bits per word (default: 32)\n"
+" -a [fifo|dma|config]<bits> - Access type and bits per word (default: 32)\n"
" -e <l|b> - Endianess Little/Big (default: host)\n"
" -o <file> - Append output to file (default: stdout)\n"
" -t <timeout|unlimited> - Timeout in microseconds\n"
+" --check - Verify write operations\n"
"\n"
" Event Options:\n"
" --event <evt> - Specifies event for trigger and grab modes\n"
@@ -277,6 +306,15 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" --multipacket - Read multiple packets\n"
" --wait - Wait until data arrives\n"
"\n"
+" Kernel Options:\n"
+" --type <type> - Type of kernel memory to allocate\n"
+" consistent - Consistent memory\n"
+" s2c - DMA S2C (write) memory\n"
+" c2s - DMA C2S (read) memory\n"
+" --page-size <size> - Size of kernel buffer in bytes (default: page)\n"
+" -s <size> - Number of buffers to allocate (default: 1)\n"
+" --allignment <alignment> - Buffer alignment (default: page)\n"
+"\n"
" Information:\n"
" --verbose [level] - Announce details of ongoing operations\n"
" -q - Quiete mode (suppress warnings)\n"
@@ -471,7 +509,8 @@ void List(pcilib_t *handle, pcilib_model_description_t *model_info, const char *
void Info(pcilib_t *handle, pcilib_model_description_t *model_info) {
const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
- printf("Vendor: %x, Device: %x, Interrupt Pin: %i, Interrupt Line: %i\n", board_info->vendor_id, board_info->device_id, board_info->interrupt_pin, board_info->interrupt_line);
+ printf("Vendor: %x, Device: %x, Bus: %x, Slot: %x, Function: %x\n", board_info->vendor_id, board_info->device_id, board_info->bus, board_info->slot, board_info->func);
+ printf(" Interrupt - Pin: %i, Line: %i\n", board_info->interrupt_pin, board_info->interrupt_line);
List(handle, model_info, (char*)-1, 0);
}
@@ -491,6 +530,9 @@ int Benchmark(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
size_t irqs;
const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
+
+ if (mode == ACCESS_CONFIG)
+ Error("No benchmarking of configuration space acess is allowed");
if (mode == ACCESS_DMA) {
if (n) {
@@ -721,7 +763,12 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_
int numbers_per_block, numbers_per_line;
pcilib_dma_engine_t dmaid;
pcilib_dma_flags_t dma_flags = 0;
-
+
+ int fd;
+ char stmp[256];
+ struct stat st;
+ const pcilib_board_info_t *board_info;
+
numbers_per_block = BLOCK_SIZE / access;
block_width = numbers_per_block * ((access * 2) + SEPARATOR_WIDTH);
@@ -782,6 +829,33 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_
pcilib_read_fifo(handle, bar, addr, access, n, buf);
addr = 0;
break;
+ case ACCESS_CONFIG:
+ board_info = pcilib_get_board_info(handle);
+ sprintf(stmp, "/sys/bus/pci/devices/0000:%02x:%02x.%1x/config", board_info->bus, board_info->slot, board_info->func);
+ fd = open(stmp, O_RDONLY);
+
+ if ((!fd)||(fstat(fd, &st))) Error("Can't open %s", stmp);
+
+ if (st.st_size < addr)
+ Error("Access beyond the end of PCI configuration space");
+
+ if (st.st_size < (addr + size)) {
+ n = (st.st_size - addr) / abs(access);
+ size = n * abs(access);
+ if (!n) Error("Access beyond the end of PCI configuration space");
+ }
+
+ lseek(fd, addr, SEEK_SET);
+ ret = read(fd, buf, size);
+ if (ret == (size_t)-1) Error("Error reading %s", stmp);
+
+ if (ret < size) {
+ size = ret;
+ n = ret / abs(access);
+ }
+
+ close(fd);
+ break;
default:
pcilib_read(handle, bar, addr, size, buf);
}
@@ -949,7 +1023,7 @@ int ReadRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info,
return 0;
}
-int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data) {
+int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data, int verify) {
int read_back = 0;
void *buf, *check;
int res = 0, i, err;
@@ -957,6 +1031,9 @@ int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
size_t ret;
pcilib_dma_engine_t dmaid;
+ if (mode == ACCESS_CONFIG)
+ Error("Writting to PCI configuration space is not supported");
+
err = posix_memalign( (void**)&buf, 256, size );
if (!err) err = posix_memalign( (void**)&check, 256, size );
if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
@@ -991,8 +1068,10 @@ int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma,
break;
default:
pcilib_write(handle, bar, addr, size, buf);
- pcilib_read(handle, bar, addr, size, check);
- read_back = 1;
+ if (verify) {
+ pcilib_read(handle, bar, addr, size, check);
+ read_back = 1;
+ }
}
if ((read_back)&&(memcmp(buf, check, size))) {
@@ -1731,7 +1810,7 @@ int StartStopDMA(pcilib_t *handle, pcilib_model_description_t *model_info, pcil
typedef struct {
- unsigned long use;
+ pcilib_kmem_use_t use;
int referenced;
int hw_lock;
@@ -1745,7 +1824,23 @@ typedef struct {
#define MAX_USES 64
-size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, unsigned long use) {
+pcilib_kmem_use_t ParseUse(const char *use) {
+ unsigned long utmp;
+
+ if (use) {
+ if ((!isxnumber(use))||(sscanf(use, "%lx", &utmp) != 1)) Error("Invalid use (%s) is specified", use);
+
+ if (strlen(use) < 5)
+ return PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER,utmp);
+ else
+ return utmp;
+ }
+
+ Error("Kernel memory use is not specified");
+ return 0;
+}
+
+size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) {
size_t i, n = *n_uses;
if (uses[n - 1].use == use) return n - 1;
@@ -1760,17 +1855,28 @@ size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, unsigned long use) {
return (*n_uses)++;
}
-int ListKMEM(pcilib_t *handle, const char *device) {
+
+kmem_use_info_t *GetUse(size_t n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) {
+ size_t i;
+ for (i = 0; i < n_uses; i++) {
+ if (uses[i].use == use) {
+ if (uses[i].count) return uses + i;
+ else return NULL;
+ }
+ }
+ return NULL;
+}
+
+
+int ParseKMEM(pcilib_t *handle, const char *device, size_t *uses_number, kmem_use_info_t *uses) {
DIR *dir;
struct dirent *entry;
const char *pos;
char sysdir[256];
char fname[256];
char info[256];
- char stmp[256];
-
- size_t useid, i, n_uses = 1; // Use 0 is for others
- kmem_use_info_t uses[MAX_USES];
+
+ size_t useid, n_uses = 1; // Use 0 is for others
memset(uses, 0, sizeof(uses));
@@ -1819,6 +1925,21 @@ int ListKMEM(pcilib_t *handle, const char *device) {
}
closedir(dir);
+ *uses_number = n_uses;
+
+ return 0;
+}
+
+int ListKMEM(pcilib_t *handle, const char *device) {
+ int err;
+ char stmp[256];
+
+ size_t i, useid, n_uses;
+ kmem_use_info_t uses[MAX_USES];
+
+ err = ParseKMEM(handle, device, &n_uses, uses);
+ if (err) Error("Failed to parse kernel memory information provided through sysfs");
+
if ((n_uses == 1)&&(uses[0].count == 0)) {
printf("No kernel memory is allocated\n");
return 0;
@@ -1832,10 +1953,11 @@ int ListKMEM(pcilib_t *handle, const char *device) {
i = 0;
} else i = useid + 1;
- printf("%08lx ", uses[i].use);
+ printf("%08x ", uses[i].use);
if (!i) printf("All Others ");
- else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%lu %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
- else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%lu %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
+ else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
+ else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
+ else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_USER) printf("User %04x ", uses[i].use&0xFFFF);
else printf (" ");
printf(" ");
printf("% 6lu", uses[i].count);
@@ -1860,13 +1982,60 @@ int ListKMEM(pcilib_t *handle, const char *device) {
return 0;
}
-int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t use, size_t block, size_t max_size, FILE *o) {
+int DetailKMEM(pcilib_t *handle, const char *device, const char *use, size_t block) {
+ int err;
+ size_t i, n;
+ pcilib_kmem_handle_t *kbuf;
+ pcilib_kmem_use_t useid = ParseUse(use);
+
+ size_t n_uses;
+ kmem_use_info_t uses[MAX_USES];
+ kmem_use_info_t *use_info;
+
+ if (block == (size_t)-1) {
+ err = ParseKMEM(handle, device, &n_uses, uses);
+ if (err) Error("Failed to parse kernel memory information provided through sysfs");
+ use_info = GetUse(n_uses, uses, useid);
+ if (!use_info) Error("No kernel buffers is allocated for the specified use (%lx)", useid);
+
+ i = 0;
+ n = use_info->count;
+ } else {
+ i = block;
+ n = block + 1;
+ }
+
+ kbuf = pcilib_alloc_kernel_memory(handle, 0, n, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
+ if (!kbuf) {
+ Error("Allocation of kernel buffer (use %lx, count %lu) is failed\n", useid, n);
+ return 0;
+ }
+
+ printf("Buffer Address Hardware Address Bus Address\n");
+ printf("--------------------------------------------------------------------------------\n");
+ for (; i < n; i++) {
+ void *data = pcilib_kmem_get_block_ua(handle, kbuf, i);
+ uintptr_t pa = pcilib_kmem_get_block_pa(handle, kbuf, i);
+ uintptr_t ba = pcilib_kmem_get_block_ba(handle, kbuf, i);
+ printf("%6lu %16p %16lx %16lx\n", i, data, pa, ba);
+ }
+ printf("\n");
+
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
+
+ return 0;
+}
+
+
+int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t useid, size_t block, size_t max_size, FILE *o) {
int err;
void *data;
size_t size;
pcilib_kmem_handle_t *kbuf;
- kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, use, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
+ if (block == (size_t)-1) block = 0;
+
+ kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
if (!kbuf) {
Error("The specified kernel buffer is not allocated\n");
return 0;
@@ -1896,11 +2065,37 @@ int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t use, size_t
return 0;
}
+int AllocKMEM(pcilib_t *handle, const char *device, const char *use, const char *type, size_t size, size_t block_size, size_t alignment) {
+ pcilib_kmem_type_t ktype = PCILIB_KMEM_TYPE_PAGE;
+ pcilib_kmem_flags_t flags = KMEM_FLAG_REUSE;
+ pcilib_kmem_handle_t *kbuf;
+ pcilib_kmem_use_t useid = ParseUse(use);
+
+ long page_size = sysconf(_SC_PAGESIZE);
+
+ if (type) {
+ if (!strcmp(type, "consistent")) ktype = PCILIB_KMEM_TYPE_CONSISTENT;
+ else if (!strcmp(type, "c2s")) ktype = PCILIB_KMEM_TYPE_DMA_C2S_PAGE;
+ else if (!strcmp(type, "s2c")) ktype = PCILIB_KMEM_TYPE_DMA_S2C_PAGE;
+ else Error("Invalid memory type (%s) is specified", type);
+ }
+
+ if ((block_size)&&(ktype != PCILIB_KMEM_TYPE_CONSISTENT))
+ Error("Selected memory type does not allow custom size");
+
+ kbuf = pcilib_alloc_kernel_memory(handle, ktype, size, (block_size?block_size:page_size), (alignment?alignment:page_size), useid, flags|KMEM_FLAG_PERSISTENT);
+ if (!kbuf) Error("Allocation of kernel memory has failed");
+
+ pcilib_free_kernel_memory(handle, kbuf, flags);
+
+ return 0;
+}
+
int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
int err;
int i;
- unsigned long useid;
+ pcilib_kmem_use_t useid;
pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE;
if (force) flags |= PCILIB_KMEM_FLAG_FORCE; // this will ignore mmap locks as well.
@@ -1920,8 +2115,7 @@ int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
return 0;
}
- if ((!isxnumber(use))||(sscanf(use, "%lx", &useid) != 1)) Error("Invalid use (%s) is specified", use);
-
+ useid = ParseUse(use);
err = pcilib_clean_kernel_memory(handle, useid, flags);
if (err) Error("Error cleaning kernel buffers for use (0x%lx)", useid);
@@ -1956,10 +2150,10 @@ int ListDMA(pcilib_t *handle, const char *device, pcilib_model_description_t *mo
while ((entry = readdir(dir)) != NULL) {
FILE *f;
unsigned long use = 0;
- unsigned long size = 0;
- unsigned long refs = 0;
+// unsigned long size = 0;
+// unsigned long refs = 0;
unsigned long mode = 0;
- unsigned long hwref = 0;
+// unsigned long hwref = 0;
if (strncmp(entry->d_name, "kbuf", 4)) continue;
if (!isnumber(entry->d_name+4)) continue;
@@ -1971,10 +2165,10 @@ int ListDMA(pcilib_t *handle, const char *device, pcilib_model_description_t *mo
while(!feof(f)) {
fgets(info, 256, f);
if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16);
- if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
- if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
+// if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
+// if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16);
- if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
+// if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
}
fclose(f);
@@ -2109,13 +2303,38 @@ int ReadBuffer(pcilib_t *handle, const char *device, pcilib_model_description_t
}
+int EnableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) {
+ int err;
+
+ err = pcilib_enable_irq(handle, irq_type, 0);
+ if (err) {
+ if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE))
+ Error("Error enabling IRQs");
+ }
+
+ return err;
+}
+
+int DisableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) {
+ int err;
+
+ err = pcilib_disable_irq(handle, 0);
+ if (err) {
+ if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE))
+ Error("Error disabling IRQs");
+ }
+
+ return err;
+}
+
+int AckIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source) {
+ pcilib_clear_irq(handle, irq_source);
+ return 0;
+}
int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source, pcilib_timeout_t timeout) {
int err;
size_t count;
-
- err = pcilib_enable_irq(handle, PCILIB_EVENT_IRQ, 0);
- if (err) Error("Error enabling IRQs");
err = pcilib_wait_irq(handle, irq_source, timeout, &count);
if (err) {
@@ -2130,7 +2349,6 @@ int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq
int main(int argc, char **argv) {
int i;
long itmp;
- unsigned long utmp;
size_t ztmp;
unsigned char c;
@@ -2141,6 +2359,7 @@ int main(int argc, char **argv) {
int verbose = 0;
int quiete = 0;
int force = 0;
+ int verify = 0;
pcilib_model_t model = PCILIB_MODEL_DETECT;
pcilib_model_description_t *model_info;
@@ -2153,6 +2372,7 @@ int main(int argc, char **argv) {
FORMAT format = FORMAT_DEFAULT;
PARTITION partition = PARTITION_UNKNOWN;
FLAGS flags = 0;
+ const char *atype = NULL;
const char *type = NULL;
ACCESS_MODE amode = ACCESS_BAR;
const char *fpga_device = DEFAULT_FPGA_DEVICE;
@@ -2165,19 +2385,22 @@ int main(int argc, char **argv) {
const char *data_type = NULL;
const char *dma_channel = NULL;
const char *use = NULL;
- pcilib_kmem_use_t use_id = 0;
- size_t block = 0;
+ size_t block = (size_t)-1;
+ pcilib_irq_type_t irq_type = PCILIB_IRQ_TYPE_ALL;
pcilib_irq_hw_source_t irq_source = PCILIB_IRQ_SOURCE_DEFAULT;
pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
+ pcilib_kmem_use_t useid = 0;
pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID;
long addr_shift = 0;
uintptr_t start = -1;
+ size_t block_size = 0;
size_t size = 1;
access_t access = 4;
// int skip = 0;
int endianess = 0;
size_t timeout = 0;
+ size_t alignment = 0;
const char *output = NULL;
FILE *ofile = NULL;
size_t iterations = BENCHMARK_ITERATIONS;
@@ -2186,8 +2409,8 @@ int main(int argc, char **argv) {
int size_set = 0;
int timeout_set = 0;
- int run_time_set = 0;
-
+// int run_time_set = 0;
+
while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) {
extern int optind;
switch (c) {
@@ -2303,6 +2526,51 @@ int main(int argc, char **argv) {
if (optarg) dma_channel = optarg;
else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
break;
+ case OPT_ENABLE_IRQ:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_ENABLE_IRQ;
+ if (optarg) num_offset = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
+ else num_offset = NULL;
+
+ if (num_offset) {
+ if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
+ Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
+
+ irq_type = itmp;
+ }
+ break;
+ case OPT_DISABLE_IRQ:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_DISABLE_IRQ;
+ if (optarg) num_offset = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
+ else num_offset = NULL;
+
+ if (num_offset) {
+ if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
+ Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
+
+ irq_type = itmp;
+ }
+ break;
+ case OPT_ACK_IRQ:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_ACK_IRQ;
+ if (optarg) num_offset = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
+ else num_offset = NULL;
+
+ if (num_offset) {
+ 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_WAIT_IRQ:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
@@ -2321,6 +2589,21 @@ int main(int argc, char **argv) {
case OPT_LIST_KMEM:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
mode = MODE_LIST_KMEM;
+
+ if (optarg) use = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++];
+ else use = NULL;
+
+ if (use) {
+ num_offset = strchr(use, ':');
+
+ if (num_offset) {
+ if (sscanf(num_offset + 1, "%zu", &block) != 1)
+ Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
+
+ *(char*)num_offset = 0;
+ }
+ }
break;
case OPT_READ_KMEM:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
@@ -2335,13 +2618,15 @@ int main(int argc, char **argv) {
*(char*)num_offset = 0;
}
- if (sscanf(optarg, "%lx", &utmp) != 1)
- Usage(argc, argv, "Invalid USE number is specified (%s)", optarg);
-
- if (!utmp)
- Usage(argc, argv, "Can't read buffer with the unspecific use (use number is 0)");
-
- use_id = utmp;
+ use = optarg;
+ useid = ParseUse(use);
+ break;
+ case OPT_ALLOC_KMEM:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+ mode = MODE_ALLOC_KMEM;
+
+ if (optarg) use = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++];
break;
case OPT_FREE_KMEM:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
@@ -2363,21 +2648,30 @@ int main(int argc, char **argv) {
// if ((sscanf(optarg,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
// else bar = itmp;
break;
+ case OPT_ALIGNMENT:
+ if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &alignment) != 1)) {
+ Usage(argc, argv, "Invalid alignment is specified (%s)", optarg);
+ }
+ break;
case OPT_ACCESS:
if (!strncasecmp(optarg, "fifo", 4)) {
- type = "fifo";
+ atype = "fifo";
num_offset = optarg + 4;
amode = ACCESS_FIFO;
} else if (!strncasecmp(optarg, "dma", 3)) {
- type = "dma";
+ atype = "dma";
num_offset = optarg + 3;
amode = ACCESS_DMA;
} else if (!strncasecmp(optarg, "bar", 3)) {
- type = "plain";
+ atype = "plain";
num_offset = optarg + 3;
amode = ACCESS_BAR;
+ } else if (!strncasecmp(optarg, "config", 6)) {
+ atype = "config";
+ num_offset = optarg + 6;
+ amode = ACCESS_CONFIG;
} else if (!strncasecmp(optarg, "plain", 5)) {
- type = "plain";
+ atype = "plain";
num_offset = optarg + 5;
amode = ACCESS_BAR;
} else {
@@ -2407,6 +2701,11 @@ int main(int argc, char **argv) {
size_set = 1;
break;
+ case OPT_BLOCK_SIZE:
+ if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &block_size) != 1)) {
+ Usage(argc, argv, "Invalid size is specified (%s)", optarg);
+ }
+ break;
case OPT_ENDIANESS:
if ((*optarg == 'b')||(*optarg == 'B')) {
if (ntohs(1) == 1) endianess = 0;
@@ -2436,6 +2735,9 @@ int main(int argc, char **argv) {
case OPT_EVENT:
event = optarg;
break;
+ case OPT_TYPE:
+ type = optarg;
+ break;
case OPT_DATA_TYPE:
data_type = optarg;
break;
@@ -2446,7 +2748,7 @@ int main(int argc, char **argv) {
else
run_time = 0;
}
- run_time_set = 1;
+// run_time_set = 1;
break;
case OPT_TRIGGER_TIME:
if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1))
@@ -2511,6 +2813,9 @@ int main(int argc, char **argv) {
case OPT_FORCE:
force = 1;
break;
+ case OPT_VERIFY:
+ verify = 1;
+ break;
case OPT_MULTIPACKET:
flags |= FLAG_MULTIPACKET;
break;
@@ -2537,7 +2842,6 @@ int main(int argc, char **argv) {
switch (mode) {
case MODE_WRITE:
- if (!addr) Usage(argc, argv, "The address is not specified");
if (((argc - optind) == 1)&&(*argv[optind] == '*')) {
int vallen = strlen(argv[optind]);
if (vallen > 1) {
@@ -2559,11 +2863,11 @@ int main(int argc, char **argv) {
}
} else if ((argc - optind) == size) data = argv + optind;
else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size);
- break;
case MODE_READ:
if (!addr) {
if (model == PCILIB_MODEL_PCI) {
- Usage(argc, argv, "The address is not specified");
+ if ((amode != ACCESS_DMA)&&(amode != ACCESS_CONFIG))
+ Usage(argc, argv, "The address is not specified");
} else ++mode;
}
break;
@@ -2601,7 +2905,7 @@ int main(int argc, char **argv) {
if (addr) {
if ((!strncmp(addr, "dma", 3))&&((addr[3]==0)||isnumber(addr+3))) {
- if ((type)&&(amode != ACCESS_DMA)) Usage(argc, argv, "Conflicting access modes, the DMA read is requested, but access type is (%s)", type);
+ if ((atype)&&(amode != ACCESS_DMA)) Usage(argc, argv, "Conflicting access modes, the DMA read is requested, but access type is (%s)", type);
if (bank) {
if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting DMA channels are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank);
} else {
@@ -2609,11 +2913,17 @@ int main(int argc, char **argv) {
}
dma = atoi(addr + 3);
amode = ACCESS_DMA;
+ addr = NULL;
} else if ((!strncmp(addr, "bar", 3))&&((addr[3]==0)||isnumber(addr+3))) {
- if ((type)&&(amode != ACCESS_BAR)) Usage(argc, argv, "Conflicting access modes, the plain PCI read is requested, but access type is (%s)", type);
+ if ((atype)&&(amode != ACCESS_BAR)) Usage(argc, argv, "Conflicting access modes, the plain PCI read is requested, but access type is (%s)", type);
if ((addr[3] != 0)&&(strcmp(addr + 3, bank))) Usage(argc, argv, "Conflicting PCI bars are specified in read parameter (%s) and bank parameter (%s)", addr + 3, bank);
bar = atoi(addr + 3);
amode = ACCESS_BAR;
+ addr = NULL;
+ } else if (!strcmp(addr, "config")) {
+ if ((atype)&&(amode != ACCESS_CONFIG)) Usage(argc, argv, "Conflicting access modes, the read of PCI configurataion space is requested, but access type is (%s)", type);
+ amode = ACCESS_CONFIG;
+ addr = NULL;
} else if ((isxnumber(addr))&&(sscanf(addr, "%lx", &start) == 1)) {
// check if the address in the register range
pcilib_register_range_t *ranges = model_info->ranges;
@@ -2712,6 +3022,8 @@ int main(int argc, char **argv) {
case MODE_READ:
if (amode == ACCESS_DMA) {
ReadData(handle, amode, flags, dma, bar, start, size_set?size:0, access, endianess, timeout_set?timeout:(size_t)-1, ofile);
+ } else if (amode == ACCESS_CONFIG) {
+ ReadData(handle, amode, flags, dma, bar, addr?start:0, (addr||size_set)?size:(256/abs(access)), access, endianess, (size_t)-1, ofile);
} else if (addr) {
ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile);
} else {
@@ -2723,7 +3035,7 @@ int main(int argc, char **argv) {
else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile);
break;
case MODE_WRITE:
- WriteData(handle, amode, dma, bar, start, size, access, endianess, data);
+ WriteData(handle, amode, dma, bar, start, size, access, endianess, data, verify);
break;
case MODE_WRITE_REGISTER:
if (reg) WriteRegister(handle, model_info, bank, reg, data);
@@ -2750,14 +3062,27 @@ int main(int argc, char **argv) {
case MODE_STOP_DMA:
StartStopDMA(handle, model_info, dma, dma_direction, 0);
break;
+ case MODE_ENABLE_IRQ:
+ EnableIRQ(handle, model_info, irq_type);
+ break;
+ case MODE_DISABLE_IRQ:
+ DisableIRQ(handle, model_info, irq_type);
+ break;
+ case MODE_ACK_IRQ:
+ AckIRQ(handle, model_info, irq_source);
+ break;
case MODE_WAIT_IRQ:
WaitIRQ(handle, model_info, irq_source, timeout);
break;
case MODE_LIST_KMEM:
- ListKMEM(handle, fpga_device);
+ if (use) DetailKMEM(handle, fpga_device, use, block);
+ else ListKMEM(handle, fpga_device);
break;
case MODE_READ_KMEM:
- ReadKMEM(handle, fpga_device, use_id, block, 0, ofile);
+ ReadKMEM(handle, fpga_device, useid, block, 0, ofile);
+ break;
+ case MODE_ALLOC_KMEM:
+ AllocKMEM(handle, fpga_device, use, type, size, block_size, alignment);
break;
case MODE_FREE_KMEM:
FreeKMEM(handle, fpga_device, use, force);