diff options
Diffstat (limited to 'cli.c')
-rw-r--r-- | cli.c | 443 |
1 files changed, 384 insertions, 59 deletions
@@ -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); |