/alps/ipecamera

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/ipecamera

« back to all changes in this revision

Viewing changes to cli.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-27 00:28:57 UTC
  • Revision ID: csa@suren.me-20150427002857-82fk6r3e8rfgy4wr
First stand-alone ipecamera implementation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define _POSIX_C_SOURCE 200112L
2
 
#define _BSD_SOURCE
3
 
 
4
 
#include <stdio.h>
5
 
#include <stdlib.h>
6
 
#include <string.h>
7
 
#include <strings.h>
8
 
#include <stdint.h>
9
 
#include <stdarg.h>
10
 
#include <fcntl.h>
11
 
#include <unistd.h>
12
 
#include <sys/time.h>
13
 
#include <sys/ioctl.h>
14
 
#include <sys/mman.h>
15
 
#include <errno.h>
16
 
#include <alloca.h>
17
 
#include <arpa/inet.h>
18
 
#include <sys/types.h>
19
 
#include <sys/stat.h>
20
 
#include <dirent.h>
21
 
#include <pthread.h>
22
 
#include <signal.h>
23
 
 
24
 
#include <getopt.h>
25
 
 
26
 
#include <fastwriter.h>
27
 
 
28
 
#include "pcitool/sysinfo.h"
29
 
#include "pcitool/formaters.h"
30
 
 
31
 
//#include "pci.h"
32
 
#include "tools.h"
33
 
#include "kernel.h"
34
 
#include "error.h"
35
 
 
36
 
/* defines */
37
 
#define MAX_KBUF 14
38
 
//#define BIGBUFSIZE (512*1024*1024)
39
 
#define BIGBUFSIZE (1024*1024)
40
 
 
41
 
 
42
 
#define DEFAULT_FPGA_DEVICE "/dev/fpga0"
43
 
 
44
 
#define LINE_WIDTH 80
45
 
#define SEPARATOR_WIDTH 2
46
 
#define BLOCK_SEPARATOR_WIDTH 2
47
 
#define BLOCK_SIZE 8
48
 
#define BENCHMARK_ITERATIONS 128
49
 
#define STATUS_MESSAGE_INTERVAL 5       /* seconds */
50
 
 
51
 
 
52
 
#define isnumber pcilib_isnumber
53
 
#define isxnumber pcilib_isxnumber
54
 
#define isnumber_n pcilib_isnumber_n
55
 
#define isxnumber_n pcilib_isxnumber_n
56
 
 
57
 
typedef uint8_t access_t;
58
 
 
59
 
typedef enum {
60
 
    GRAB_MODE_GRAB = 1,
61
 
    GRAB_MODE_TRIGGER = 2
62
 
} GRAB_MODE;
63
 
 
64
 
typedef enum {
65
 
    MODE_INVALID,
66
 
    MODE_INFO,
67
 
    MODE_LIST,
68
 
    MODE_BENCHMARK,
69
 
    MODE_READ,
70
 
    MODE_READ_REGISTER,
71
 
    MODE_WRITE,
72
 
    MODE_WRITE_REGISTER,
73
 
    MODE_RESET,
74
 
    MODE_GRAB,
75
 
    MODE_START_DMA,
76
 
    MODE_STOP_DMA,
77
 
    MODE_LIST_DMA,
78
 
    MODE_LIST_DMA_BUFFERS,
79
 
    MODE_READ_DMA_BUFFER,
80
 
    MODE_ENABLE_IRQ,
81
 
    MODE_DISABLE_IRQ,
82
 
    MODE_ACK_IRQ,
83
 
    MODE_WAIT_IRQ,
84
 
    MODE_ALLOC_KMEM,
85
 
    MODE_LIST_KMEM,
86
 
    MODE_READ_KMEM,
87
 
    MODE_FREE_KMEM
88
 
} MODE;
89
 
 
90
 
typedef enum {
91
 
    ACCESS_BAR,
92
 
    ACCESS_DMA,
93
 
    ACCESS_FIFO, 
94
 
    ACCESS_CONFIG
95
 
} ACCESS_MODE;
96
 
 
97
 
typedef enum {
98
 
    FLAG_MULTIPACKET = 1,
99
 
    FLAG_WAIT = 2
100
 
} FLAGS;
101
 
 
102
 
 
103
 
typedef enum {
104
 
    FORMAT_DEFAULT = 0,
105
 
    FORMAT_RAW,
106
 
    FORMAT_HEADER,
107
 
    FORMAT_RINGFS
108
 
} FORMAT;
109
 
 
110
 
typedef enum {
111
 
    PARTITION_UNKNOWN,
112
 
    PARTITION_RAW,
113
 
    PARTITION_EXT4,
114
 
    PARTITION_NULL
115
 
} PARTITION;
116
 
 
117
 
typedef enum {
118
 
    OPT_DEVICE = 'd',
119
 
    OPT_MODEL = 'm',
120
 
    OPT_BAR = 'b',
121
 
    OPT_ACCESS = 'a',
122
 
    OPT_ENDIANESS = 'e',
123
 
    OPT_SIZE = 's',
124
 
    OPT_OUTPUT = 'o',
125
 
    OPT_TIMEOUT = 't',
126
 
    OPT_INFO = 'i',
127
 
    OPT_LIST = 'l',
128
 
    OPT_READ = 'r',
129
 
    OPT_WRITE = 'w',
130
 
    OPT_GRAB = 'g',
131
 
    OPT_QUIETE = 'q',
132
 
    OPT_HELP = 'h',
133
 
    OPT_RESET = 128,
134
 
    OPT_BENCHMARK,
135
 
    OPT_TRIGGER,
136
 
    OPT_DATA_TYPE,
137
 
    OPT_EVENT,
138
 
    OPT_TRIGGER_RATE,
139
 
    OPT_TRIGGER_TIME,
140
 
    OPT_RUN_TIME,
141
 
    OPT_FORMAT,
142
 
    OPT_BUFFER,
143
 
    OPT_THREADS,
144
 
    OPT_LIST_DMA,
145
 
    OPT_LIST_DMA_BUFFERS,
146
 
    OPT_READ_DMA_BUFFER,
147
 
    OPT_START_DMA,
148
 
    OPT_STOP_DMA,
149
 
    OPT_ENABLE_IRQ,
150
 
    OPT_DISABLE_IRQ,
151
 
    OPT_ACK_IRQ,
152
 
    OPT_WAIT_IRQ,
153
 
    OPT_ITERATIONS,
154
 
    OPT_ALLOC_KMEM,
155
 
    OPT_LIST_KMEM,
156
 
    OPT_FREE_KMEM,
157
 
    OPT_READ_KMEM,
158
 
    OPT_BLOCK_SIZE,
159
 
    OPT_ALIGNMENT,
160
 
    OPT_TYPE,
161
 
    OPT_FORCE,
162
 
    OPT_VERIFY,
163
 
    OPT_WAIT,
164
 
    OPT_MULTIPACKET,
165
 
    OPT_VERBOSE
166
 
} OPTIONS;
167
 
 
168
 
static struct option long_options[] = {
169
 
    {"device",                  required_argument, 0, OPT_DEVICE },
170
 
    {"model",                   required_argument, 0, OPT_MODEL },
171
 
    {"bar",                     required_argument, 0, OPT_BAR },
172
 
    {"access",                  required_argument, 0, OPT_ACCESS },
173
 
    {"endianess",               required_argument, 0, OPT_ENDIANESS },
174
 
    {"size",                    required_argument, 0, OPT_SIZE },
175
 
    {"output",                  required_argument, 0, OPT_OUTPUT },
176
 
    {"timeout",                 required_argument, 0, OPT_TIMEOUT },
177
 
    {"iterations",              required_argument, 0, OPT_ITERATIONS },
178
 
    {"info",                    no_argument, 0, OPT_INFO },
179
 
    {"list",                    no_argument, 0, OPT_LIST },
180
 
    {"reset",                   no_argument, 0, OPT_RESET },
181
 
    {"benchmark",               optional_argument, 0, OPT_BENCHMARK },
182
 
    {"read",                    optional_argument, 0, OPT_READ },
183
 
    {"write",                   optional_argument, 0, OPT_WRITE },
184
 
    {"grab",                    optional_argument, 0, OPT_GRAB },
185
 
    {"trigger",                 optional_argument, 0, OPT_TRIGGER },
186
 
    {"data",                    required_argument, 0, OPT_DATA_TYPE },
187
 
    {"event",                   required_argument, 0, OPT_EVENT },
188
 
    {"run-time",                required_argument, 0, OPT_RUN_TIME },
189
 
    {"trigger-rate",            required_argument, 0, OPT_TRIGGER_RATE },
190
 
    {"trigger-time",            required_argument, 0, OPT_TRIGGER_TIME },
191
 
    {"format",                  required_argument, 0, OPT_FORMAT },
192
 
    {"buffer",                  optional_argument, 0, OPT_BUFFER },
193
 
    {"threads",                 optional_argument, 0, OPT_THREADS },
194
 
    {"start-dma",               required_argument, 0, OPT_START_DMA },
195
 
    {"stop-dma",                optional_argument, 0, OPT_STOP_DMA },
196
 
    {"list-dma-engines",        no_argument, 0, OPT_LIST_DMA },
197
 
    {"list-dma-buffers",        required_argument, 0, OPT_LIST_DMA_BUFFERS },
198
 
    {"read-dma-buffer",         required_argument, 0, OPT_READ_DMA_BUFFER },
199
 
    {"enable-irq",              optional_argument, 0, OPT_ENABLE_IRQ },
200
 
    {"disable-irq",             optional_argument, 0, OPT_DISABLE_IRQ },
201
 
    {"acknowledge-irq",         optional_argument, 0, OPT_ACK_IRQ },
202
 
    {"wait-irq",                optional_argument, 0, OPT_WAIT_IRQ },
203
 
    {"list-kernel-memory",      optional_argument, 0, OPT_LIST_KMEM },
204
 
    {"read-kernel-memory",      required_argument, 0, OPT_READ_KMEM },
205
 
    {"alloc-kernel-memory",     required_argument, 0, OPT_ALLOC_KMEM },
206
 
    {"free-kernel-memory",      required_argument, 0, OPT_FREE_KMEM },
207
 
    {"type",                    required_argument, 0, OPT_TYPE },
208
 
    {"block-size",              required_argument, 0, OPT_BLOCK_SIZE },
209
 
    {"alignment",               required_argument, 0, OPT_ALIGNMENT },
210
 
    {"quiete",                  no_argument, 0, OPT_QUIETE },
211
 
    {"verbose",                 optional_argument, 0, OPT_VERBOSE },
212
 
    {"force",                   no_argument, 0, OPT_FORCE },
213
 
    {"verify",                  no_argument, 0, OPT_VERIFY },
214
 
    {"multipacket",             no_argument, 0, OPT_MULTIPACKET },
215
 
    {"wait",                    no_argument, 0, OPT_WAIT },
216
 
    {"help",                    no_argument, 0, OPT_HELP },
217
 
    { 0, 0, 0, 0 }
218
 
};
219
 
 
220
 
 
221
 
void Usage(int argc, char *argv[], const char *format, ...) {
222
 
    if (format) {
223
 
        va_list ap;
224
 
    
225
 
        va_start(ap, format);
226
 
        printf("Error %i: ", errno);
227
 
        vprintf(format, ap);
228
 
        printf("\n");
229
 
        va_end(ap);
230
 
    
231
 
        printf("\n");
232
 
    }
233
 
 
234
 
 
235
 
    printf(
236
 
"Usage:\n"
237
 
" %s <mode> [options] [hex data]\n"
238
 
"  Modes:\n"
239
 
"   -i                          - Device Info\n"
240
 
"   -l[l]                       - List (detailed) Data Banks & Registers\n"
241
 
"   -r <addr|reg|dmaX>          - Read Data/Register\n"
242
 
"   -w <addr|reg|dmaX>          - Write Data/Register\n"
243
 
"   --benchmark <barX|dmaX>     - Performance Evaluation\n"
244
 
"   --reset                     - Reset board\n"
245
 
"   --help                      - Help message\n"
246
 
"\n"
247
 
"  Event Modes:\n"
248
 
"   --trigger [event]           - Trigger Events\n"
249
 
"   -g [event]                  - Grab Events\n"
250
 
"\n"
251
 
"  IRQ Modes:\n"
252
 
"   --enable-irq [type]         - Enable IRQs\n"
253
 
"   --disable-irq [type]        - Disable IRQs\n"
254
 
"   --acknowledge-irq <source>  - Clean IRQ queue\n"
255
 
"   --wait-irq <source>         - Wait for IRQ\n"
256
 
 
257
 
"  DMA Modes:\n"
258
 
"   --start-dma <num>[r|w]      - Start specified DMA engine\n"
259
 
"   --stop-dma [num[r|w]]       - Stop specified engine or DMA subsystem\n"
260
 
"   --list-dma-engines          - List active DMA engines\n"
261
 
"   --list-dma-buffers <dma>    - List buffers for specified DMA engine\n"
262
 
"   --read-dma-buffer <dma:buf> - Read the specified buffer\n"
263
 
"\n"
264
 
"  Kernel Modes:\n"
265
 
"   --list-kernel-memory [use]  - List kernel buffers\n"
266
 
"   --read-kernel-memory <blk>  - Read the specified block of the kernel memory\n"
267
 
"                                 block is specified as: use:block_number\n"
268
 
"   --alloc-kernel-memory <use> - Allocate kernel buffers (DANGEROUS)\n"
269
 
"   --free-kernel-memory <use>  - Cleans lost kernel space buffers (DANGEROUS)\n"
270
 
"       dma                     - Remove all buffers allocated by DMA subsystem\n"
271
 
"       #number                 - Remove all buffers with the specified use id\n"
272
 
"\n"
273
 
"  Addressing:\n"
274
 
"   -d <device>                 - FPGA device (/dev/fpga0)\n"
275
 
"   -m <model>                  - Memory model (autodetected)\n"
276
 
"       pci                     - Plain\n"
277
 
"       ipecamera               - IPE Camera\n"
278
 
"   -b <bank>                   - PCI bar, Register bank, or DMA channel\n"
279
 
"\n"
280
 
"  Options:\n"
281
 
"   -s <size>                   - Number of words (default: 1)\n"
282
 
"   -a [fifo|dma|config]<bits>  - Access type and bits per word (default: 32)\n"
283
 
"   -e <l|b>                    - Endianess Little/Big (default: host)\n"
284
 
"   -o <file>                   - Append output to file (default: stdout)\n"
285
 
"   -t <timeout|unlimited>      - Timeout in microseconds\n"
286
 
"   --check                     - Verify write operations\n"
287
 
"\n"
288
 
"  Event Options:\n"
289
 
"   --event <evt>               - Specifies event for trigger and grab modes\n"
290
 
"   --data <type>               - Data type to request for the events\n"
291
 
"   --run-time <us>             - Limit time to grab/trigger events\n"
292
 
"   -t <timeout|unlimited>      - Timeout to stop if no events triggered\n"
293
 
"   --trigger-rate <tps>                - Generate tps triggers per second\n"
294
 
"   --trigger-time <us>         - Specifies delay between triggers (us)\n"
295
 
"   -s <num|unlimited>          - Number of events to grab and trigger\n"
296
 
"   --format [type]             - Specifies how event data should be stored\n"
297
 
"       raw                     - Just write all events sequentially\n"
298
 
"       add_header              - Prefix events with 512 bit header:\n"
299
 
"                                 event(64), data(64), nope(64), size(64)\n"
300
 
"                                 seqnum(64), offset(64), timestamp(128)\n"
301
 
//"     ringfs                  - Write to RingFS\n"
302
 
"   --buffer [size]             - Request data buffering, size in MB\n"
303
 
"   --threads [num]             - Allow multithreaded processing\n"
304
 
"\n"
305
 
"  DMA Options:\n"
306
 
"   --multipacket               - Read multiple packets\n"
307
 
"   --wait                      - Wait until data arrives\n"
308
 
"\n"
309
 
"  Kernel Options:\n"
310
 
"   --type <type>               - Type of kernel memory to allocate\n"
311
 
"       consistent              - Consistent memory\n"
312
 
"       s2c                     - DMA S2C (write) memory\n"
313
 
"       c2s                     - DMA C2S (read) memory\n"
314
 
"   --page-size <size>          - Size of kernel buffer in bytes (default: page)\n"
315
 
"   -s <size>                   - Number of buffers to allocate (default: 1)\n"
316
 
"   --allignment <alignment>    - Buffer alignment (default: page)\n"
317
 
"\n"
318
 
"  Information:\n"
319
 
"   --verbose [level]           - Announce details of ongoing operations\n"
320
 
"   -q                          - Quiete mode (suppress warnings)\n"
321
 
"\n"
322
 
"  Data:\n"
323
 
"       Data can be specified as sequence of hexdecimal number or\n"
324
 
"       a single value prefixed with '*'. In this case it will be\n"
325
 
"       replicated the specified amount of times\n"
326
 
"\n\n",
327
 
argv[0]);
328
 
 
329
 
    exit(0);
330
 
}
331
 
 
332
 
static int StopFlag = 0;
333
 
 
334
 
static void signal_exit_handler(int signo) { 
335
 
    if (++StopFlag > 2)
336
 
        exit(-1);
337
 
}
338
 
 
339
 
 
340
 
void Error(const char *format, ...) {
341
 
    va_list ap;
342
 
    
343
 
    va_start(ap, format);
344
 
    printf("Error %i: ", errno);
345
 
    vprintf(format, ap);
346
 
    if (errno) printf("\n errno: %s", strerror(errno));
347
 
    printf("\n\n");
348
 
    va_end(ap);
349
 
    
350
 
    exit(-1);
351
 
}
352
 
 
353
 
void Silence(const char *format, ...) {
354
 
}
355
 
 
356
 
void List(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, int details) {
357
 
    int i,j;
358
 
    pcilib_register_bank_description_t *banks;
359
 
    pcilib_register_description_t *registers;
360
 
    pcilib_event_description_t *events;
361
 
    pcilib_event_data_type_description_t *types;
362
 
 
363
 
    const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
364
 
    const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle);
365
 
    
366
 
    for (i = 0; i < PCILIB_MAX_BANKS; i++) {
367
 
        if (board_info->bar_length[i] > 0) {
368
 
            printf(" BAR %d - ", i);
369
 
 
370
 
            switch ( board_info->bar_flags[i]&IORESOURCE_TYPE_BITS) {
371
 
                case IORESOURCE_IO:  printf(" IO"); break;
372
 
                case IORESOURCE_MEM: printf("MEM"); break;
373
 
                case IORESOURCE_IRQ: printf("IRQ"); break;
374
 
                case IORESOURCE_DMA: printf("DMA"); break;
375
 
            }
376
 
            
377
 
            if (board_info->bar_flags[i]&IORESOURCE_MEM_64) printf("64");
378
 
            else printf("32");
379
 
            
380
 
            printf(", Start: 0x%08lx, Length: 0x%8lx, Flags: 0x%08lx\n", board_info->bar_start[i], board_info->bar_length[i], board_info->bar_flags[i] );
381
 
        }
382
 
    }
383
 
    printf("\n");
384
 
    
385
 
    if ((dma_info)&&(dma_info->engines)) {
386
 
        printf("DMA Engines: \n");
387
 
        for (i = 0; dma_info->engines[i]; i++) {
388
 
            pcilib_dma_engine_description_t *engine = dma_info->engines[i];
389
 
            printf(" DMA %2d ", engine->addr);
390
 
            switch (engine->direction) {
391
 
                case PCILIB_DMA_FROM_DEVICE:
392
 
                    printf("C2S");
393
 
                break;
394
 
                case PCILIB_DMA_TO_DEVICE:
395
 
                    printf("S2C");
396
 
                break;
397
 
                case PCILIB_DMA_BIDIRECTIONAL:
398
 
                    printf("BI ");
399
 
                break;
400
 
            }
401
 
            printf(" - Type: ");
402
 
            switch (engine->type) {
403
 
                case PCILIB_DMA_TYPE_BLOCK:
404
 
                    printf("Block");
405
 
                break;
406
 
                case PCILIB_DMA_TYPE_PACKET:
407
 
                    printf("Packet");
408
 
                break;
409
 
                default:
410
 
                    printf("Unknown");
411
 
            }
412
 
            
413
 
            printf(", Address Width: %02lu bits\n", engine->addr_bits);
414
 
        }
415
 
        printf("\n");
416
 
    }
417
 
 
418
 
    if ((bank)&&(bank != (char*)-1)) banks = NULL;
419
 
    else banks = model_info->banks;
420
 
    
421
 
    if (banks) {
422
 
        printf("Banks: \n");
423
 
        for (i = 0; banks[i].access; i++) {
424
 
            printf(" 0x%02x %s", banks[i].addr, banks[i].name);
425
 
            if ((banks[i].description)&&(banks[i].description[0])) {
426
 
                printf(": %s", banks[i].description);
427
 
            }
428
 
            printf("\n");
429
 
        }
430
 
        printf("\n");
431
 
    }
432
 
    
433
 
    if (bank == (char*)-1) registers = NULL;
434
 
    else registers = model_info->registers;
435
 
    
436
 
    if (registers) {
437
 
        pcilib_register_bank_addr_t bank_addr = 0;
438
 
        if (bank) {
439
 
            pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank);
440
 
            pcilib_register_bank_description_t *b = model_info->banks + bank_id;
441
 
 
442
 
            bank_addr = b->addr;
443
 
            if (b->description) printf("%s:\n", b->description);
444
 
            else if (b->name) printf("Registers of bank %s:\n", b->name);
445
 
            else printf("Registers of bank 0x%x:\n", b->addr);
446
 
        } else {
447
 
            printf("Registers: \n");
448
 
        }
449
 
        for (i = 0; registers[i].bits; i++) {
450
 
            const char *mode;
451
 
            
452
 
            if ((bank)&&(registers[i].bank != bank_addr)) continue;
453
 
            if (registers[i].type == PCILIB_REGISTER_BITS) {
454
 
                if (!details) continue;
455
 
                
456
 
                if (registers[i].bits > 1) {
457
 
                    printf("    [%2u:%2u] - %s\n", registers[i].offset, registers[i].offset + registers[i].bits, registers[i].name);
458
 
                } else {
459
 
                    printf("    [   %2u] - %s\n", registers[i].offset, registers[i].name);
460
 
                }
461
 
                
462
 
                continue;
463
 
            }
464
 
 
465
 
            if (registers[i].mode == PCILIB_REGISTER_RW) mode = "RW";
466
 
            else if (registers[i].mode == PCILIB_REGISTER_R) mode = "R ";
467
 
            else if (registers[i].mode == PCILIB_REGISTER_W) mode = " W";
468
 
            else mode = "  ";
469
 
            
470
 
            printf(" 0x%02x (%2i %s) %s", registers[i].addr, registers[i].bits, mode, registers[i].name);
471
 
            if ((details > 0)&&(registers[i].description)&&(registers[i].description[0])) {
472
 
                printf(": %s", registers[i].description);
473
 
            }
474
 
            printf("\n");
475
 
 
476
 
        }
477
 
        printf("\n");
478
 
    }
479
 
 
480
 
    if (bank == (char*)-1) events = NULL;
481
 
    else {
482
 
        events = model_info->events;
483
 
        types = model_info->data_types;
484
 
    }
485
 
 
486
 
    if (events) {
487
 
        printf("Events: \n");
488
 
        for (i = 0; events[i].name; i++) {
489
 
            printf(" %s", events[i].name);
490
 
            if ((events[i].description)&&(events[i].description[0])) {
491
 
                printf(": %s", events[i].description);
492
 
            }
493
 
            
494
 
            if (types) {
495
 
                for (j = 0; types[j].name; j++) {
496
 
                    if (types[j].evid & events[i].evid) {
497
 
                        printf("\n    %s", types[j].name);
498
 
                        if ((types[j].description)&&(types[j].description[0])) {
499
 
                            printf(": %s", types[j].description);
500
 
                        }
501
 
                    }
502
 
                }
503
 
            }
504
 
        }
505
 
        printf("\n");
506
 
    }
507
 
}
508
 
 
509
 
void Info(pcilib_t *handle, pcilib_model_description_t *model_info) {
510
 
    const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
511
 
 
512
 
    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);
513
 
    printf(" Interrupt - Pin: %i, Line: %i\n", board_info->interrupt_pin, board_info->interrupt_line);
514
 
    List(handle, model_info, (char*)-1, 0);
515
 
}
516
 
 
517
 
 
518
 
#define BENCH_MAX_DMA_SIZE 4 * 1024 * 1024
519
 
#define BENCH_MAX_FIFO_SIZE 1024 * 1024
520
 
 
521
 
int Benchmark(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, size_t iterations) {
522
 
    int err;
523
 
    int i, j, errors;
524
 
    void *data, *buf, *check;
525
 
    void *fifo = NULL;
526
 
    struct timeval start, end;
527
 
    unsigned long time;
528
 
    size_t size, min_size, max_size;
529
 
    double mbs_in, mbs_out, mbs;
530
 
    size_t irqs;
531
 
    
532
 
    const pcilib_board_info_t *board_info = pcilib_get_board_info(handle);
533
 
    
534
 
    if (mode == ACCESS_CONFIG)
535
 
        Error("No benchmarking of configuration space acess is allowed");
536
 
 
537
 
    if (mode == ACCESS_DMA) {
538
 
        if (n) {
539
 
            min_size = n * access;
540
 
            max_size = n * access;
541
 
        } else {
542
 
            min_size = 1024;
543
 
            max_size = BENCH_MAX_DMA_SIZE;
544
 
        }
545
 
        
546
 
        for (size = min_size; size <= max_size; size *= 4) {
547
 
            mbs_in = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_FROM_DEVICE);
548
 
            mbs_out = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_TO_DEVICE);
549
 
            mbs = pcilib_benchmark_dma(handle, dma, addr, size, iterations, PCILIB_DMA_BIDIRECTIONAL);
550
 
            err = pcilib_wait_irq(handle, 0, 0, &irqs);
551
 
            if (err) irqs = 0;
552
 
            
553
 
            printf("%8zu KB - ", size / 1024);
554
 
            
555
 
            printf("RW: ");
556
 
            if (mbs < 0) printf("failed ...   ");
557
 
            else printf("%8.2lf MB/s", mbs);
558
 
 
559
 
            printf(", R: ");
560
 
            if (mbs_in < 0) printf("failed ...   ");
561
 
            else printf("%8.2lf MB/s", mbs_in);
562
 
 
563
 
            printf(", W: ");
564
 
            if (mbs_out < 0) printf("failed ...   ");
565
 
            else printf("%8.2lf MB/s", mbs_out);
566
 
            
567
 
            if (irqs) {
568
 
                printf(", IRQs: %lu", irqs);
569
 
            }
570
 
 
571
 
            printf("\n");
572
 
        }
573
 
        
574
 
        return 0;
575
 
    }
576
 
 
577
 
    if (bar == PCILIB_BAR_INVALID) {
578
 
        unsigned long maxlength = 0;
579
 
        
580
 
 
581
 
        for (i = 0; i < PCILIB_MAX_BANKS; i++) {
582
 
            if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + access))) {
583
 
                bar = i;
584
 
                break;
585
 
            }
586
 
 
587
 
            if (board_info->bar_length[i] > maxlength) {
588
 
                maxlength = board_info->bar_length[i];
589
 
                bar = i;
590
 
            }
591
 
        }
592
 
        
593
 
        if (bar < 0) Error("Data banks are not available");
594
 
    }
595
 
    
596
 
    if (n) {
597
 
        if ((mode == ACCESS_BAR)&&(n * access > board_info->bar_length[bar])) Error("The specified size (%i) exceeds the size of bar (%i)", n * access, board_info->bar_length[bar]);
598
 
 
599
 
        min_size = n * access;
600
 
        max_size = n * access;
601
 
    } else {
602
 
        min_size = access;
603
 
        if (mode == ACCESS_BAR) max_size = board_info->bar_length[bar];
604
 
        else max_size = BENCH_MAX_FIFO_SIZE;
605
 
    }
606
 
    
607
 
    err = posix_memalign( (void**)&buf, 256, max_size );
608
 
    if (!err) err = posix_memalign( (void**)&check, 256, max_size );
609
 
    if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", max_size);
610
 
 
611
 
    data = pcilib_map_bar(handle, bar);
612
 
    if (!data) Error("Can't map bar %i", bar);
613
 
 
614
 
    if (mode == ACCESS_FIFO) {
615
 
        fifo = data + (addr - board_info->bar_start[bar]) + (board_info->bar_start[bar] & pcilib_get_page_mask());
616
 
//      pcilib_resolve_register_address(handle, bar, addr);
617
 
        if (!fifo) Error("Can't resolve address (%lx) in bar (%u)", addr, bar);
618
 
    }
619
 
 
620
 
    if (mode == ACCESS_FIFO)
621
 
        printf("Transfer time (Bank: %i, Fifo: %lx):\n", bar, addr);
622
 
    else
623
 
        printf("Transfer time (Bank: %i):\n", bar);
624
 
        
625
 
    for (size = min_size ; size < max_size; size *= 8) {
626
 
        gettimeofday(&start,NULL);
627
 
        if (mode == ACCESS_BAR) {
628
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
629
 
                pcilib_memcpy(buf, data, size);
630
 
            }
631
 
        } else {
632
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
633
 
                for (j = 0; j < (size/access); j++) {
634
 
                    pcilib_memcpy(buf + j * access, fifo, access);
635
 
                }
636
 
            }
637
 
        }
638
 
        gettimeofday(&end,NULL);
639
 
 
640
 
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
641
 
        printf("%8zu bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
642
 
        
643
 
        fflush(0);
644
 
 
645
 
        gettimeofday(&start,NULL);
646
 
        if (mode == ACCESS_BAR) {
647
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
648
 
                pcilib_memcpy(data, buf, size);
649
 
            }
650
 
        } else {
651
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
652
 
                for (j = 0; j < (size/access); j++) {
653
 
                    pcilib_memcpy(fifo, buf + j * access, access);
654
 
                }
655
 
            }
656
 
        }
657
 
        gettimeofday(&end,NULL);
658
 
 
659
 
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
660
 
        printf(", write: %8.2lf MB/s\n", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
661
 
    }
662
 
    
663
 
    pcilib_unmap_bar(handle, bar, data);
664
 
 
665
 
    printf("\n\nOpen-Transfer-Close time: \n");
666
 
    
667
 
    for (size = 4 ; size < max_size; size *= 8) {
668
 
        gettimeofday(&start,NULL);
669
 
        if (mode == ACCESS_BAR) {
670
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
671
 
                pcilib_read(handle, bar, 0, size, buf);
672
 
            }
673
 
        } else {
674
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
675
 
                pcilib_read_fifo(handle, bar, addr, access, size / access, buf);
676
 
            }
677
 
        }
678
 
        gettimeofday(&end,NULL);
679
 
 
680
 
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
681
 
        printf("%8zu bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
682
 
        
683
 
        fflush(0);
684
 
 
685
 
        gettimeofday(&start,NULL);
686
 
        if (mode == ACCESS_BAR) {
687
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
688
 
                pcilib_write(handle, bar, 0, size, buf);
689
 
            }
690
 
        } else {
691
 
            for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
692
 
                pcilib_write_fifo(handle, bar, addr, access, size / access, buf);
693
 
            }
694
 
        }
695
 
        
696
 
        gettimeofday(&end,NULL);
697
 
 
698
 
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
699
 
        printf(", write: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
700
 
 
701
 
        if (mode == ACCESS_BAR) {
702
 
            gettimeofday(&start,NULL);
703
 
            for (i = 0, errors = 0; i < BENCHMARK_ITERATIONS; i++) {
704
 
                pcilib_write(handle, bar, 0, size, buf);
705
 
                pcilib_read(handle, bar, 0, size, check);
706
 
                if (memcmp(buf, check, size)) ++errors;
707
 
            }
708
 
            gettimeofday(&end,NULL);
709
 
 
710
 
            time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
711
 
            printf(", write-verify: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024. * 1024.));
712
 
            if (errors) printf(", errors: %u of %u", errors, BENCHMARK_ITERATIONS);
713
 
        }
714
 
        printf("\n");
715
 
    }
716
 
    
717
 
    printf("\n\n");
718
 
 
719
 
    free(check);
720
 
    free(buf);
721
 
    
722
 
    return 0;
723
 
}
724
 
 
725
 
#define pci2host16(endianess, value) endianess?
726
 
 
727
 
/*
728
 
typedef struct {
729
 
    size_t size;
730
 
    void *data;
731
 
    size_t pos;
732
 
 
733
 
    int multi_mode;
734
 
} DMACallbackContext;
735
 
 
736
 
static int DMACallback(void *arg, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
737
 
    DMACallbackContext *ctx = (DMACallbackContext*)arg;
738
 
    
739
 
    if ((ctx->pos + bufsize > ctx->size)||(!ctx->data)) {
740
 
        ctx->size *= 2;
741
 
        ctx->data = realloc(ctx->data, ctx->size);
742
 
        if (!ctx->data) {
743
 
            Error("Allocation of %i bytes of memory have failed", ctx->size);
744
 
            return 0;
745
 
        }
746
 
    }
747
 
    
748
 
    memcpy(ctx->data + ctx->pos, buf, bufsize);
749
 
    ctx->pos += bufsize;
750
 
 
751
 
    if (flags & PCILIB_DMA_FLAG_EOP) return 0;
752
 
    return 1;
753
 
}
754
 
*/
755
 
 
756
 
 
757
 
int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_addr_t dma, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, size_t timeout, FILE *o) {
758
 
    void *buf;
759
 
    int i, err;
760
 
    size_t ret, bytes;
761
 
    size_t size = n * abs(access);
762
 
    int block_width, blocks_per_line;
763
 
    int numbers_per_block, numbers_per_line; 
764
 
    pcilib_dma_engine_t dmaid;
765
 
    pcilib_dma_flags_t dma_flags = 0;
766
 
 
767
 
    int fd;
768
 
    char stmp[256];
769
 
    struct stat st;
770
 
    const pcilib_board_info_t *board_info;
771
 
 
772
 
    numbers_per_block = BLOCK_SIZE / access;
773
 
 
774
 
    block_width = numbers_per_block * ((access * 2) +  SEPARATOR_WIDTH);
775
 
    blocks_per_line = (LINE_WIDTH - 10) / (block_width +  BLOCK_SEPARATOR_WIDTH);
776
 
    if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
777
 
    numbers_per_line = blocks_per_line * numbers_per_block;
778
 
 
779
 
    if (size) {
780
 
        buf = malloc(size);
781
 
        if (!buf) Error("Allocation of %zu bytes of memory has failed", size);
782
 
    } else {
783
 
        buf = NULL;
784
 
    }
785
 
    
786
 
    switch (mode) {
787
 
      case ACCESS_DMA:
788
 
        if (timeout == (size_t)-1) timeout = PCILIB_DMA_TIMEOUT;
789
 
    
790
 
        dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
791
 
        if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
792
 
        
793
 
        if (flags&FLAG_MULTIPACKET) dma_flags |= PCILIB_DMA_FLAG_MULTIPACKET;
794
 
        if (flags&FLAG_WAIT) dma_flags |= PCILIB_DMA_FLAG_WAIT;
795
 
        
796
 
        if (size) {
797
 
            err = pcilib_read_dma_custom(handle, dmaid, addr, size, dma_flags, timeout, buf, &bytes);
798
 
            if (err) Error("Error (%i) is reported by DMA engine", err);
799
 
        } else {
800
 
            dma_flags |= PCILIB_DMA_FLAG_IGNORE_ERRORS;
801
 
            
802
 
            size = 2048; bytes = 0;
803
 
            do {
804
 
                size *= 2;
805
 
                buf = realloc(buf, size);
806
 
                if (!buf) Error("Allocation of %zu bytes of memory has failed", size);
807
 
                err = pcilib_read_dma_custom(handle, dmaid, addr, size - bytes, dma_flags, timeout, buf + bytes, &ret);
808
 
                bytes += ret;
809
 
                
810
 
                if ((!err)&&(flags&FLAG_MULTIPACKET)) {
811
 
                    err = PCILIB_ERROR_TOOBIG;
812
 
                    if ((flags&FLAG_WAIT)==0) timeout = 0;
813
 
                }
814
 
            } while (err == PCILIB_ERROR_TOOBIG);
815
 
        }
816
 
 
817
 
        if ((err)&&(err != PCILIB_ERROR_TIMEOUT)) {
818
 
            Error("Error (%i) during DMA read", err);
819
 
        }
820
 
        if (bytes <= 0) {
821
 
            pcilib_warning("No data is returned by DMA engine");
822
 
            return 0;
823
 
        }
824
 
        size = bytes;
825
 
        n = bytes / abs(access);
826
 
        addr = 0;
827
 
      break;
828
 
      case ACCESS_FIFO:
829
 
        pcilib_read_fifo(handle, bar, addr, access, n, buf);
830
 
        addr = 0;
831
 
      break;
832
 
      case ACCESS_CONFIG:
833
 
        board_info = pcilib_get_board_info(handle);
834
 
        sprintf(stmp, "/sys/bus/pci/devices/0000:%02x:%02x.%1x/config", board_info->bus, board_info->slot, board_info->func);
835
 
        fd = open(stmp, O_RDONLY);
836
 
 
837
 
        if ((!fd)||(fstat(fd, &st))) Error("Can't open %s", stmp);
838
 
        
839
 
        if (st.st_size < addr) 
840
 
            Error("Access beyond the end of PCI configuration space");
841
 
        
842
 
        if (st.st_size < (addr + size)) {
843
 
            n = (st.st_size - addr) / abs(access);
844
 
            size = n * abs(access);
845
 
            if (!n) Error("Access beyond the end of PCI configuration space");
846
 
        }
847
 
        
848
 
        lseek(fd, addr, SEEK_SET);
849
 
        ret = read(fd, buf, size);
850
 
        if (ret == (size_t)-1) Error("Error reading %s", stmp);
851
 
        
852
 
        if (ret < size) {
853
 
            size = ret;
854
 
            n = ret / abs(access);
855
 
        }
856
 
        
857
 
        close(fd);
858
 
      break;
859
 
      default:
860
 
        pcilib_read(handle, bar, addr, size, buf);
861
 
    }
862
 
    
863
 
    if (endianess) pcilib_swap(buf, buf, abs(access), n);
864
 
 
865
 
    if (o) {
866
 
        printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access));
867
 
        fwrite(buf, abs(access), n, o);
868
 
    } else {
869
 
        for (i = 0; i < n; i++) {
870
 
            if (i) {
871
 
                if (i%numbers_per_line == 0) printf("\n");
872
 
                else {
873
 
                    printf("%*s", SEPARATOR_WIDTH, "");
874
 
                    if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, "");
875
 
                }
876
 
            }
877
 
            
878
 
            if (i%numbers_per_line == 0) printf("%8lx:  ", addr + i * abs(access));
879
 
 
880
 
            switch (access) {
881
 
                case 1: printf("%0*hhx", access * 2, ((uint8_t*)buf)[i]); break;
882
 
                case 2: printf("%0*hx", access * 2, ((uint16_t*)buf)[i]); break;
883
 
                case 4: printf("%0*x", access * 2, ((uint32_t*)buf)[i]); break;
884
 
                case 8: printf("%0*lx", access * 2, ((uint64_t*)buf)[i]); break;
885
 
            }
886
 
        }
887
 
        printf("\n\n");
888
 
    }
889
 
 
890
 
    
891
 
    free(buf);
892
 
    return 0;
893
 
}
894
 
 
895
 
 
896
 
 
897
 
 
898
 
int ReadRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg) {
899
 
    int i;
900
 
    int err;
901
 
    const char *format;
902
 
 
903
 
    pcilib_register_bank_t bank_id;
904
 
    pcilib_register_bank_addr_t bank_addr = 0;
905
 
 
906
 
    pcilib_register_value_t value;
907
 
    
908
 
    if (reg) {
909
 
        pcilib_register_t regid = pcilib_find_register(handle, bank, reg);
910
 
        bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank);
911
 
        format = model_info->banks[bank_id].format;
912
 
        if (!format) format = "%lu";
913
 
 
914
 
        err = pcilib_read_register_by_id(handle, regid, &value);
915
 
    //    err = pcilib_read_register(handle, bank, reg, &value);
916
 
        if (err) printf("Error reading register %s\n", reg);
917
 
        else {
918
 
            printf("%s = ", reg);
919
 
            printf(format, value);
920
 
            printf("\n");
921
 
        }
922
 
    } else {
923
 
            // Adding DMA registers
924
 
        pcilib_get_dma_info(handle);    
925
 
    
926
 
        if (model_info->registers) {
927
 
            if (bank) {
928
 
                bank_id = pcilib_find_bank(handle, bank);
929
 
                bank_addr = model_info->banks[bank_id].addr;
930
 
            }
931
 
            
932
 
            printf("Registers:\n");
933
 
            for (i = 0; model_info->registers[i].bits; i++) {
934
 
                if ((model_info->registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(model_info->registers[i].bank == bank_addr))&&(model_info->registers[i].type != PCILIB_REGISTER_BITS)) { 
935
 
                    bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[i].bank);
936
 
                    format = model_info->banks[bank_id].format;
937
 
                    if (!format) format = "%lu";
938
 
 
939
 
                    err = pcilib_read_register_by_id(handle, i, &value);
940
 
                    if (err) printf(" %s = error reading value", model_info->registers[i].name);
941
 
                    else {
942
 
                        printf(" %s = ", model_info->registers[i].name);
943
 
                        printf(format, value);
944
 
                    }
945
 
 
946
 
                    printf(" [");
947
 
                    printf(format, model_info->registers[i].defvalue);
948
 
                    printf("]");
949
 
                    printf("\n");
950
 
                }
951
 
            }
952
 
        } else {
953
 
            printf("No registers");
954
 
        }
955
 
        printf("\n");
956
 
    }
957
 
    
958
 
    return 0;
959
 
}
960
 
 
961
 
#define WRITE_REGVAL(buf, n, access, o) {\
962
 
    uint##access##_t tbuf[n]; \
963
 
    for (i = 0; i < n; i++) { \
964
 
        tbuf[i] = (uint##access##_t)buf[i]; \
965
 
    } \
966
 
    fwrite(tbuf, access/8, n, o); \
967
 
}
968
 
 
969
 
int ReadRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, long addr_shift, size_t n, FILE *o) {
970
 
    int err;
971
 
    int i;
972
 
 
973
 
    pcilib_register_bank_description_t *banks = model_info->banks;
974
 
    pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank);
975
 
 
976
 
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
977
 
        if (bank) Error("Invalid register bank is specified (%s)", bank);
978
 
        else Error("Register bank should be specified");
979
 
    }
980
 
 
981
 
    int access = banks[bank_id].access / 8;
982
 
//    int size = n * abs(access);
983
 
    int block_width, blocks_per_line;
984
 
    int numbers_per_block, numbers_per_line; 
985
 
    
986
 
    numbers_per_block = BLOCK_SIZE / access;
987
 
 
988
 
    block_width = numbers_per_block * ((access * 2) +  SEPARATOR_WIDTH);
989
 
    blocks_per_line = (LINE_WIDTH - 6) / (block_width +  BLOCK_SEPARATOR_WIDTH);
990
 
    if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
991
 
    numbers_per_line = blocks_per_line * numbers_per_block;
992
 
 
993
 
 
994
 
    pcilib_register_value_t buf[n];
995
 
    err = pcilib_read_register_space(handle, bank, addr, n, buf);
996
 
    if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
997
 
 
998
 
 
999
 
    if (o) {
1000
 
        printf("Writting output (%zu bytes) to file (append to the end)...\n", n * abs(access));
1001
 
        switch (access) {
1002
 
            case 1: WRITE_REGVAL(buf, n, 8, o) break;
1003
 
            case 2: WRITE_REGVAL(buf, n, 16, o) break;
1004
 
            case 4: WRITE_REGVAL(buf, n, 32, o) break;
1005
 
            case 8: WRITE_REGVAL(buf, n, 64, o) break;
1006
 
        }
1007
 
    } else {
1008
 
        for (i = 0; i < n; i++) {
1009
 
            if (i) {
1010
 
                if (i%numbers_per_line == 0) printf("\n");
1011
 
                else {
1012
 
                    printf("%*s", SEPARATOR_WIDTH, "");
1013
 
                    if (i%numbers_per_block == 0) printf("%*s", BLOCK_SEPARATOR_WIDTH, "");
1014
 
                }
1015
 
            }
1016
 
            
1017
 
            if (i%numbers_per_line == 0) printf("%4lx:  ", addr + 4 * i - addr_shift);
1018
 
            printf("%0*lx", access * 2, (unsigned long)buf[i]);
1019
 
        }
1020
 
        printf("\n\n");
1021
 
    }
1022
 
    
1023
 
    return 0;
1024
 
}
1025
 
 
1026
 
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) {
1027
 
    int read_back = 0;
1028
 
    void *buf, *check;
1029
 
    int res = 0, i, err;
1030
 
    int size = n * abs(access);
1031
 
    size_t ret;
1032
 
    pcilib_dma_engine_t dmaid;
1033
 
 
1034
 
    if (mode == ACCESS_CONFIG)
1035
 
        Error("Writting to PCI configuration space is not supported");
1036
 
 
1037
 
    err = posix_memalign( (void**)&buf, 256, size );
1038
 
    if (!err) err = posix_memalign( (void**)&check, 256, size );
1039
 
    if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
1040
 
 
1041
 
    for (i = 0; i < n; i++) {
1042
 
        switch (access) {
1043
 
            case 1: res = sscanf(data[i], "%hhx", ((uint8_t*)buf)+i); break;
1044
 
            case 2: res = sscanf(data[i], "%hx", ((uint16_t*)buf)+i); break;
1045
 
            case 4: res = sscanf(data[i], "%x", ((uint32_t*)buf)+i); break;
1046
 
            case 8: res = sscanf(data[i], "%lx", ((uint64_t*)buf)+i); break;
1047
 
            default: Error("Unexpected data size (%lu)", access);
1048
 
        }
1049
 
        if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
1050
 
    }
1051
 
 
1052
 
    if (endianess) pcilib_swap(buf, buf, abs(access), n);
1053
 
 
1054
 
    switch (mode) {
1055
 
      case ACCESS_DMA:
1056
 
        dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
1057
 
        if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (%lu) is specified", dma);
1058
 
        err = pcilib_write_dma(handle, dmaid, addr, size, buf, &ret);
1059
 
        if ((err)||(ret != size)) {
1060
 
            if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout writting the data to DMA"); 
1061
 
            else if (err) Error("DMA engine returned a error while writing the data");
1062
 
            else if (!ret) Error("No data is written by DMA engine");
1063
 
            else Error("Only %lu bytes of %lu is written by DMA engine", ret, size);
1064
 
        }
1065
 
      break;
1066
 
      case ACCESS_FIFO:
1067
 
        pcilib_write_fifo(handle, bar, addr, access, n, buf);
1068
 
      break;
1069
 
      default:
1070
 
        pcilib_write(handle, bar, addr, size, buf);
1071
 
        if (verify) {
1072
 
            pcilib_read(handle, bar, addr, size, check);
1073
 
            read_back = 1;
1074
 
        }
1075
 
    }
1076
 
 
1077
 
    if ((read_back)&&(memcmp(buf, check, size))) {
1078
 
        printf("Write failed: the data written and read differ, the foolowing is read back:\n");
1079
 
        if (endianess) pcilib_swap(check, check, abs(access), n);
1080
 
        ReadData(handle, mode, 0, dma, bar, addr, n, access, endianess, (size_t)-1, NULL);
1081
 
        exit(-1);
1082
 
    }
1083
 
 
1084
 
    free(check);
1085
 
    free(buf);
1086
 
    
1087
 
    return 0;
1088
 
}
1089
 
 
1090
 
int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, long addr_shift, size_t n, char ** data) {
1091
 
    pcilib_register_value_t *buf, *check;
1092
 
    int res, i, err;
1093
 
    unsigned long value;
1094
 
    int size = n * sizeof(pcilib_register_value_t);
1095
 
 
1096
 
    err = posix_memalign( (void**)&buf, 256, size );
1097
 
    if (!err) err = posix_memalign( (void**)&check, 256, size );
1098
 
    if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
1099
 
 
1100
 
    for (i = 0; i < n; i++) {
1101
 
        res = sscanf(data[i], "%lx", &value);
1102
 
        if ((res != 1)||(!isxnumber(data[i]))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
1103
 
        buf[i] = value;
1104
 
    }
1105
 
 
1106
 
    err = pcilib_write_register_space(handle, bank, addr, n, buf);
1107
 
    if (err) Error("Error writting register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
1108
 
    
1109
 
    err = pcilib_read_register_space(handle, bank, addr, n, check);
1110
 
    if (err) Error("Error reading register space for bank \"%s\" at address %lx, size %lu", bank?bank:"default", addr, n);
1111
 
 
1112
 
    if (memcmp(buf, check, size)) {
1113
 
        printf("Write failed: the data written and read differ, the foolowing is read back:\n");
1114
 
        ReadRegisterRange(handle, model_info, bank, addr, addr_shift, n, NULL);
1115
 
        exit(-1);
1116
 
    }
1117
 
 
1118
 
    free(check);
1119
 
    free(buf);
1120
 
    
1121
 
    return 0;
1122
 
 
1123
 
}
1124
 
 
1125
 
int WriteRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg, char ** data) {
1126
 
    int err;
1127
 
 
1128
 
    unsigned long val;
1129
 
    pcilib_register_value_t value;
1130
 
 
1131
 
    const char *format = NULL;
1132
 
 
1133
 
    pcilib_register_t regid = pcilib_find_register(handle, bank, reg);
1134
 
    if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected");
1135
 
 
1136
 
/*
1137
 
    pcilib_register_bank_t bank_id;
1138
 
    pcilib_register_bank_addr_t bank_addr;
1139
 
 
1140
 
    bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank);
1141
 
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) Error("Can't find bank of the register (%s)", reg);
1142
 
    format = model_info->banks[bank_id].format;
1143
 
    if (!format) format = "%lu";
1144
 
*/
1145
 
 
1146
 
    if (isnumber(*data)) {
1147
 
        if (sscanf(*data, "%li", &val) != 1) {
1148
 
            Error("Can't parse data value (%s) is not valid decimal number", *data);
1149
 
        }
1150
 
 
1151
 
        format = "%li";
1152
 
    } else if (isxnumber(*data)) {
1153
 
        if (sscanf(*data, "%lx", &val) != 1) {
1154
 
            Error("Can't parse data value (%s) is not valid decimal number", *data);
1155
 
        }
1156
 
        
1157
 
        format = "0x%lx";
1158
 
    } else {
1159
 
            Error("Can't parse data value (%s) is not valid decimal number", *data);
1160
 
    }
1161
 
 
1162
 
    value = val;
1163
 
    
1164
 
    err = pcilib_write_register(handle, bank, reg, value);
1165
 
    if (err) Error("Error writting register %s\n", reg);
1166
 
 
1167
 
    if ((model_info->registers[regid].mode&PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) {
1168
 
        err = pcilib_read_register(handle, bank, reg, &value);
1169
 
        if (err) Error("Error reading back register %s for verification\n", reg);
1170
 
    
1171
 
        if (val != value) {
1172
 
            Error("Failed to write register %s: %lu is written and %lu is read back", reg, val, value);
1173
 
        } else {
1174
 
            printf("%s = ", reg);
1175
 
            printf(format, value);
1176
 
            printf("\n");
1177
 
        }
1178
 
    } else {
1179
 
        printf("%s is written\n ", reg);
1180
 
    }
1181
 
    
1182
 
    return 0;
1183
 
}
1184
 
 
1185
 
typedef struct {
1186
 
    pcilib_t *handle;
1187
 
    pcilib_event_t event;
1188
 
    pcilib_event_data_type_t data;
1189
 
 
1190
 
    fastwriter_t *writer;
1191
 
 
1192
 
    int verbose;
1193
 
    pcilib_timeout_t timeout;
1194
 
    size_t run_time;
1195
 
    size_t trigger_time;    
1196
 
    size_t max_triggers;
1197
 
    pcilib_event_flags_t flags;
1198
 
    FORMAT format;
1199
 
    
1200
 
    volatile int event_pending;                 /**< Used to detect that we have read previously triggered event */
1201
 
    volatile int trigger_thread_started;        /**< Indicates that trigger thread is ready and we can't procced to start event recording */
1202
 
    volatile int started;                       /**< Indicates that recording is started */
1203
 
    
1204
 
    volatile int run_flag;
1205
 
    volatile int writing_flag;
1206
 
 
1207
 
    struct timeval first_frame;    
1208
 
    struct timeval last_frame;
1209
 
    size_t last_num;
1210
 
    
1211
 
    size_t trigger_failed;
1212
 
    size_t trigger_count;
1213
 
    size_t event_count;
1214
 
    size_t incomplete_count;
1215
 
    size_t broken_count;
1216
 
    size_t missing_count;
1217
 
    size_t storage_count;
1218
 
    
1219
 
    struct timeval start_time;
1220
 
    struct timeval stop_time;
1221
 
} GRABContext;
1222
 
 
1223
 
int GrabCallback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) {
1224
 
    int err = 0;
1225
 
    void *data;
1226
 
    size_t size;
1227
 
    
1228
 
    GRABContext *ctx = (GRABContext*)user;
1229
 
    pcilib_t *handle = ctx->handle;
1230
 
 
1231
 
    gettimeofday(&ctx->last_frame, NULL);
1232
 
 
1233
 
    if (!ctx->event_count) {
1234
 
        memcpy(&ctx->first_frame, &ctx->last_frame, sizeof(struct timeval));
1235
 
    }
1236
 
 
1237
 
    ctx->event_pending = 0;
1238
 
    ctx->event_count++;
1239
 
    
1240
 
    if (ctx->last_num)
1241
 
        ctx->missing_count += (info->seqnum - ctx->last_num) - 1;
1242
 
    ctx->last_num = info->seqnum;
1243
 
    
1244
 
    if (info->flags&PCILIB_EVENT_INFO_FLAG_BROKEN) {
1245
 
        ctx->incomplete_count++;
1246
 
        return PCILIB_STREAMING_CONTINUE;
1247
 
    }
1248
 
    
1249
 
    switch (ctx->format) {
1250
 
     case FORMAT_DEFAULT:
1251
 
        data = pcilib_get_data(handle, event_id, PCILIB_EVENT_DATA, &size);
1252
 
        break;
1253
 
     default:
1254
 
        data = pcilib_get_data(handle, event_id, PCILIB_EVENT_RAW_DATA, &size);
1255
 
    }
1256
 
        
1257
 
    if (!data) {
1258
 
        ctx->broken_count++;
1259
 
        return PCILIB_STREAMING_CONTINUE;
1260
 
    }
1261
 
 
1262
 
    if (ctx->format == FORMAT_HEADER) {
1263
 
        uint64_t header[8];
1264
 
        header[0] = info->type;
1265
 
        header[1] = ctx->data;
1266
 
        header[2] = 0;
1267
 
        header[3] = size;
1268
 
        header[4] = info->seqnum;
1269
 
        header[5] = info->offset;
1270
 
        memcpy(header + 6, &info->timestamp, 16);
1271
 
        
1272
 
        err = fastwriter_push(ctx->writer, 64, header);
1273
 
    }
1274
 
 
1275
 
    if (!err) 
1276
 
        err = fastwriter_push(ctx->writer, size, data);
1277
 
 
1278
 
    if (err) {
1279
 
        fastwriter_cancel(ctx->writer);
1280
 
 
1281
 
        if (err != EWOULDBLOCK)
1282
 
            Error("Storage error %i", err);
1283
 
 
1284
 
        ctx->storage_count++;
1285
 
        pcilib_return_data(handle, event_id, ctx->data, data);
1286
 
        return PCILIB_STREAMING_CONTINUE;
1287
 
    }
1288
 
 
1289
 
    err = pcilib_return_data(handle, event_id, ctx->data, data);
1290
 
    if (err) {
1291
 
        ctx->missing_count++;
1292
 
        fastwriter_cancel(ctx->writer);
1293
 
        return PCILIB_STREAMING_CONTINUE;
1294
 
    }
1295
 
 
1296
 
    err = fastwriter_commit(ctx->writer);
1297
 
    if (err) Error("Error commiting data to storage, Error: %i", err);
1298
 
    
1299
 
    return PCILIB_STREAMING_CONTINUE;
1300
 
}
1301
 
 
1302
 
int raw_data(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event_flags_t flags, size_t size, void *data, void *user) {
1303
 
    int err;
1304
 
 
1305
 
    GRABContext *ctx = (GRABContext*)user;
1306
 
//    pcilib_t *handle = ctx->handle;
1307
 
 
1308
 
 
1309
 
    if ((info)&&(info->seqnum != ctx->last_num)) {
1310
 
        gettimeofday(&ctx->last_frame, NULL);
1311
 
        if (!ctx->event_count) {
1312
 
            memcpy(&ctx->first_frame, &ctx->last_frame, sizeof(struct timeval));
1313
 
        }
1314
 
 
1315
 
        ctx->event_count++;
1316
 
        ctx->missing_count += (info->seqnum - ctx->last_num) - 1;
1317
 
        ctx->last_num = info->seqnum;
1318
 
    }
1319
 
 
1320
 
    err = fastwriter_push_data(ctx->writer, size, data);
1321
 
    if (err) {
1322
 
        if (err == EWOULDBLOCK) Error("Storage is not able to handle the data stream, buffer overrun");
1323
 
        Error("Storage error %i", err);
1324
 
    }
1325
 
    
1326
 
    return PCILIB_STREAMING_CONTINUE;
1327
 
}
1328
 
 
1329
 
 
1330
 
void *Trigger(void *user) {
1331
 
    int err;
1332
 
    struct timeval start;
1333
 
 
1334
 
    GRABContext *ctx = (GRABContext*)user;
1335
 
    size_t trigger_time = ctx->trigger_time;
1336
 
    size_t max_triggers = ctx->max_triggers;
1337
 
    
1338
 
    ctx->trigger_thread_started = 1;
1339
 
    ctx->event_pending = 1;
1340
 
 
1341
 
    while (!ctx->started) ;
1342
 
 
1343
 
    gettimeofday(&start, NULL);
1344
 
    do {
1345
 
        err = pcilib_trigger(ctx->handle, ctx->event, 0, NULL);
1346
 
        if (err) ctx->trigger_failed++;
1347
 
        if ((++ctx->trigger_count == max_triggers)&&(max_triggers)) break;
1348
 
        
1349
 
        if (trigger_time) {
1350
 
            pcilib_add_timeout(&start, trigger_time);
1351
 
            if ((ctx->stop_time.tv_sec)&&(pcilib_timecmp(&start, &ctx->stop_time)>0)) break;
1352
 
            pcilib_sleep_until_deadline(&start);
1353
 
        }  else {
1354
 
            while ((ctx->event_pending)&&(ctx->run_flag)) usleep(10);
1355
 
            ctx->event_pending = 1;
1356
 
        }
1357
 
    } while (ctx->run_flag);
1358
 
 
1359
 
    ctx->trigger_thread_started = 0;
1360
 
 
1361
 
    return NULL;
1362
 
}
1363
 
 
1364
 
void GrabStats(GRABContext *ctx, struct timeval *end_time) {
1365
 
    int verbose;
1366
 
    pcilib_timeout_t duration, fps_duration;
1367
 
    struct timeval cur;
1368
 
    double fps = 0, good_fps = 0;
1369
 
    size_t total, good, pending = 0;
1370
 
 
1371
 
    verbose = ctx->verbose;
1372
 
    
1373
 
    if (end_time) {
1374
 
        if (verbose++) {
1375
 
            printf("-------------------------------------------------------------------------------\n");
1376
 
        }
1377
 
    } else {
1378
 
        gettimeofday(&cur, NULL);
1379
 
        end_time = &cur;
1380
 
    }
1381
 
 
1382
 
//    if ((ctx->event_count + ctx->missing_count) == 0) 
1383
 
//      return;
1384
 
    
1385
 
    duration = pcilib_timediff(&ctx->start_time, end_time);
1386
 
    fps_duration = pcilib_timediff(&ctx->first_frame, &ctx->last_frame);
1387
 
    
1388
 
    if (ctx->trigger_count) {
1389
 
        total = ctx->trigger_count;
1390
 
        pending = ctx->trigger_count - ctx->event_count - ctx->missing_count - ctx->trigger_failed;
1391
 
    } else {
1392
 
        total = ctx->event_count + ctx->missing_count;
1393
 
    }
1394
 
    
1395
 
    good = ctx->event_count - ctx->broken_count - ctx->incomplete_count - ctx->storage_count;
1396
 
 
1397
 
    if (ctx->event_count > 1) {
1398
 
        fps = (ctx->event_count - 1) / (1.*fps_duration/1000000);
1399
 
    }
1400
 
    
1401
 
    if (good > 1) {
1402
 
        good_fps = (good - 1) / (1.*fps_duration/1000000);
1403
 
    }
1404
 
 
1405
 
    printf("Run: ");
1406
 
    PrintTime(duration);    
1407
 
    
1408
 
    if (ctx->trigger_count) {
1409
 
        printf(", Triggers: ");
1410
 
        PrintNumber(ctx->trigger_count);
1411
 
    }
1412
 
    
1413
 
    printf(", Captured: ");
1414
 
    PrintNumber(ctx->event_count);
1415
 
    printf(" FPS %5.0lf", fps);
1416
 
 
1417
 
    if ((ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) == 0) {
1418
 
        printf(", Stored: ");
1419
 
        PrintNumber(good);
1420
 
        printf(" FPS %5.0lf", good_fps);
1421
 
    }
1422
 
 
1423
 
    printf("\n");    
1424
 
 
1425
 
    if (verbose > 2) {
1426
 
        if (ctx->trigger_count) {
1427
 
            printf("Trig: ");
1428
 
            PrintNumber(ctx->trigger_count);
1429
 
            printf(" Issued: ");
1430
 
            PrintNumber(ctx->trigger_count - ctx->trigger_failed);
1431
 
            printf(" (");
1432
 
            PrintPercent(ctx->trigger_count - ctx->trigger_failed, ctx->trigger_count);
1433
 
            printf("%%) Failed: ");
1434
 
            PrintNumber(ctx->trigger_failed);
1435
 
            printf( " (");
1436
 
            PrintPercent(ctx->trigger_failed, ctx->trigger_count);
1437
 
            printf( "%%); Pending: ");
1438
 
            PrintNumber(pending);
1439
 
            printf( " (");
1440
 
            PrintPercent(pending, ctx->trigger_count);
1441
 
            printf( "%%)\n");
1442
 
        }
1443
 
        
1444
 
        if (ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) {
1445
 
            printf("Captured: ");
1446
 
            PrintNumber(good);
1447
 
        } else {
1448
 
            printf("Good: ");
1449
 
            PrintNumber(good);
1450
 
            printf(", Dropped: ");
1451
 
            PrintNumber(ctx->storage_count);
1452
 
            printf(", Bad: ");
1453
 
            PrintNumber(ctx->incomplete_count);
1454
 
            printf(", Empty: ");
1455
 
            PrintNumber(ctx->broken_count);
1456
 
        }
1457
 
        printf(", Lost: ");
1458
 
        PrintNumber(ctx->missing_count);
1459
 
        printf("\n");
1460
 
    }
1461
 
 
1462
 
    if (verbose > 1) {
1463
 
        if (ctx->flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) {
1464
 
            printf("Captured: ");
1465
 
            PrintPercent(good, total);
1466
 
        } else {
1467
 
            printf("Good: ");
1468
 
            PrintPercent(good, total);
1469
 
            printf("%% Dropped: ");
1470
 
            PrintPercent(ctx->storage_count, total);
1471
 
            printf("%% Bad: ");
1472
 
            PrintPercent(ctx->incomplete_count, total);
1473
 
            printf("%% Empty: ");
1474
 
            PrintPercent(ctx->broken_count, total);
1475
 
        }
1476
 
 
1477
 
        printf("%% Lost: ");
1478
 
        PrintPercent(ctx->missing_count, total);
1479
 
        printf("%%");
1480
 
        printf("\n");
1481
 
    }
1482
 
}
1483
 
 
1484
 
void StorageStats(GRABContext *ctx) {
1485
 
    int err;
1486
 
    fastwriter_stats_t st;
1487
 
 
1488
 
    pcilib_timeout_t duration;
1489
 
    struct timeval cur;
1490
 
 
1491
 
    gettimeofday(&cur, NULL);
1492
 
    duration = pcilib_timediff(&ctx->start_time, &cur);
1493
 
 
1494
 
    
1495
 
    err = fastwriter_get_stats(ctx->writer, &st);
1496
 
    if (err) return;
1497
 
 
1498
 
    printf("Wrote ");
1499
 
    PrintSize(st.written);
1500
 
    printf(" of ");
1501
 
    PrintSize(st.commited);
1502
 
    printf(" at ");
1503
 
    PrintSize(1000000.*st.written / duration);
1504
 
    printf("/s, %6.2lf%% ", 100.*st.buffer_used / st.buffer_size);
1505
 
    printf(" of ");
1506
 
    PrintSize(st.buffer_size);
1507
 
    printf(" buffer (%6.2lf%% max)\n", 100.*st.buffer_max / st.buffer_size);
1508
 
}
1509
 
 
1510
 
void *Monitor(void *user) {
1511
 
    struct timeval deadline;
1512
 
    struct timeval nextinfo;
1513
 
    
1514
 
    GRABContext *ctx = (GRABContext*)user;
1515
 
    int verbose = ctx->verbose;
1516
 
    pcilib_timeout_t timeout = ctx->timeout;
1517
 
    
1518
 
    
1519
 
    if (timeout == PCILIB_TIMEOUT_INFINITE) timeout = 0;
1520
 
 
1521
 
//    while (!ctx->started);
1522
 
    
1523
 
    if (timeout) {
1524
 
        memcpy(&deadline, (struct timeval*)&ctx->last_frame, sizeof(struct timeval));
1525
 
        pcilib_add_timeout(&deadline, timeout);
1526
 
    }
1527
 
    
1528
 
    if (verbose > 0) {
1529
 
        pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000);
1530
 
    }
1531
 
    
1532
 
    while (ctx->run_flag) {
1533
 
        if (StopFlag) {
1534
 
            pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY);
1535
 
            break;
1536
 
        }
1537
 
        
1538
 
        if (timeout) {
1539
 
            if (pcilib_calc_time_to_deadline(&deadline) == 0) {
1540
 
                memcpy(&deadline, (struct timeval*)&ctx->last_frame, sizeof(struct timeval));
1541
 
                pcilib_add_timeout(&deadline, timeout);
1542
 
                
1543
 
                if (pcilib_calc_time_to_deadline(&deadline) == 0) {
1544
 
                    pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY);
1545
 
                    break;
1546
 
                }
1547
 
            }
1548
 
        }
1549
 
        
1550
 
        if (verbose > 0) {
1551
 
            if (pcilib_calc_time_to_deadline(&nextinfo) == 0) {
1552
 
                GrabStats(ctx, NULL);
1553
 
                StorageStats(ctx);
1554
 
                pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000);
1555
 
            }
1556
 
        }
1557
 
        
1558
 
        usleep(100000);
1559
 
    }
1560
 
    
1561
 
    pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000);
1562
 
    while (ctx->writing_flag) {
1563
 
        if (pcilib_calc_time_to_deadline(&nextinfo) == 0) {
1564
 
            if (verbose >= 0) StorageStats(ctx);
1565
 
            pcilib_calc_deadline(&nextinfo, STATUS_MESSAGE_INTERVAL*1000000);
1566
 
        }
1567
 
    
1568
 
        usleep(100000);
1569
 
    }
1570
 
    
1571
 
    return NULL;
1572
 
}
1573
 
 
1574
 
int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *evname, const char *data_type, size_t num, size_t run_time, size_t trigger_time, pcilib_timeout_t timeout, PARTITION partition, FORMAT format, size_t buffer_size, size_t threads, int verbose, const char *output) {
1575
 
    int err;
1576
 
    GRABContext ctx;
1577
 
//    void *data = NULL;
1578
 
//    size_t size, written;
1579
 
 
1580
 
    pcilib_event_t event;
1581
 
    pcilib_event_t listen_events;
1582
 
    pcilib_event_data_type_t data;
1583
 
 
1584
 
    pthread_t monitor_thread;
1585
 
    pthread_t trigger_thread;
1586
 
    pthread_attr_t attr;
1587
 
    struct sched_param sched;
1588
 
 
1589
 
    struct timeval end_time;
1590
 
    pcilib_event_flags_t flags;
1591
 
 
1592
 
    if (evname) {
1593
 
        event = pcilib_find_event(handle, evname);
1594
 
        if (event == PCILIB_EVENT_INVALID) 
1595
 
            Error("Can't find event (%s)", evname);
1596
 
 
1597
 
        listen_events = event;
1598
 
    } else {
1599
 
        listen_events = PCILIB_EVENTS_ALL;
1600
 
        event = PCILIB_EVENT0;
1601
 
    }
1602
 
    
1603
 
    if (data_type) {
1604
 
        data = pcilib_find_event_data_type(handle, event, data_type);
1605
 
        if (data == PCILIB_EVENT_DATA_TYPE_INVALID)
1606
 
            Error("Can't find data type (%s)", data_type);
1607
 
    } else {
1608
 
        data = PCILIB_EVENT_DATA;
1609
 
    }
1610
 
    
1611
 
    memset(&ctx, 0, sizeof(GRABContext));
1612
 
    
1613
 
    ctx.handle = handle;
1614
 
    ctx.event = event;
1615
 
    ctx.data = data;
1616
 
    ctx.run_time = run_time;
1617
 
    ctx.timeout = timeout;
1618
 
    ctx.format = format;
1619
 
 
1620
 
    if (grab_mode&GRAB_MODE_GRAB) ctx.verbose = verbose;
1621
 
    else ctx.verbose = 0;
1622
 
    
1623
 
    if (grab_mode&GRAB_MODE_GRAB) {
1624
 
        ctx.writer =  fastwriter_init(output, 0);
1625
 
        if (!ctx.writer)
1626
 
            Error("Can't initialize fastwritter library");
1627
 
 
1628
 
        fastwriter_set_buffer_size(ctx.writer, buffer_size);
1629
 
        
1630
 
        err = fastwriter_open(ctx.writer, output, 0);
1631
 
        if (err)
1632
 
            Error("Error opening file (%s), Error: %i\n", output, err);
1633
 
 
1634
 
        ctx.writing_flag = 1;
1635
 
    }
1636
 
 
1637
 
    ctx.run_flag = 1;
1638
 
 
1639
 
    flags = PCILIB_EVENT_FLAGS_DEFAULT;
1640
 
    
1641
 
    if (data == PCILIB_EVENT_RAW_DATA) {
1642
 
        if (format == FORMAT_RAW) {
1643
 
            flags |= PCILIB_EVENT_FLAG_RAW_DATA_ONLY;
1644
 
        }
1645
 
    } else {
1646
 
        flags |= PCILIB_EVENT_FLAG_PREPROCESS;
1647
 
    }
1648
 
    
1649
 
    ctx.flags = flags;
1650
 
 
1651
 
//    printf("Limits: %lu %lu %lu\n", num, run_time, timeout);
1652
 
    pcilib_configure_autostop(handle, num, run_time);
1653
 
    
1654
 
    if (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY) {
1655
 
        pcilib_configure_rawdata_callback(handle, &raw_data, &ctx);
1656
 
    }
1657
 
    
1658
 
    if (flags&PCILIB_EVENT_FLAG_PREPROCESS) {
1659
 
        pcilib_configure_preprocessing_threads(handle, threads);
1660
 
    }
1661
 
    
1662
 
    if (grab_mode&GRAB_MODE_TRIGGER) {
1663
 
        if (trigger_time) {
1664
 
            if ((timeout)&&(trigger_time * 2 > timeout)) {
1665
 
                timeout = 2 * trigger_time;
1666
 
                ctx.timeout = timeout;
1667
 
            }
1668
 
        } else {
1669
 
                // Otherwise, we will trigger next event after previous one is read
1670
 
            if (((grab_mode&GRAB_MODE_GRAB) == 0)||(flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)) trigger_time = PCILIB_TRIGGER_TIMEOUT;
1671
 
        }
1672
 
        
1673
 
        ctx.max_triggers = num;
1674
 
        ctx.trigger_count = 0;
1675
 
        ctx.trigger_time = trigger_time;
1676
 
 
1677
 
            // We don't really care if RT priority is imposible
1678
 
        pthread_attr_init(&attr);
1679
 
        if (!pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
1680
 
            sched.sched_priority = sched_get_priority_min(SCHED_FIFO);
1681
 
            pthread_attr_setschedparam(&attr, &sched);
1682
 
        }
1683
 
    
1684
 
            // Start triggering thread and wait until it is schedulled
1685
 
        if (pthread_create(&trigger_thread, &attr, Trigger, (void*)&ctx))
1686
 
            Error("Error spawning trigger thread");
1687
 
 
1688
 
        while (!ctx.trigger_thread_started) usleep(10);
1689
 
    }
1690
 
 
1691
 
    gettimeofday(&ctx.start_time, NULL);
1692
 
 
1693
 
    if (grab_mode&GRAB_MODE_GRAB) {
1694
 
        err = pcilib_start(handle, listen_events, flags);
1695
 
        if (err) Error("Failed to start event engine, error %i", err);
1696
 
    }
1697
 
    
1698
 
    ctx.started = 1;
1699
 
    
1700
 
    if (run_time) {
1701
 
        ctx.stop_time.tv_usec = ctx.start_time.tv_usec + run_time%1000000;
1702
 
        if (ctx.stop_time.tv_usec > 999999) {
1703
 
            ctx.stop_time.tv_usec -= 1000000;
1704
 
            __sync_synchronize();
1705
 
            ctx.stop_time.tv_sec = ctx.start_time.tv_sec + 1 + run_time / 1000000;
1706
 
        } else {
1707
 
            __sync_synchronize();
1708
 
            ctx.stop_time.tv_sec = ctx.start_time.tv_sec + run_time / 1000000;
1709
 
        }
1710
 
    }
1711
 
    
1712
 
    memcpy(&ctx.last_frame, &ctx.start_time, sizeof(struct timeval));
1713
 
    if (pthread_create(&monitor_thread, NULL, Monitor, (void*)&ctx))
1714
 
        Error("Error spawning monitoring thread");
1715
 
 
1716
 
    if (grab_mode&GRAB_MODE_GRAB) {
1717
 
        err = pcilib_stream(handle, &GrabCallback, &ctx);
1718
 
        if (err) Error("Error streaming events, error %i", err);
1719
 
    }
1720
 
    
1721
 
    ctx.run_flag = 0;
1722
 
 
1723
 
    if (grab_mode&GRAB_MODE_TRIGGER) {
1724
 
        while (ctx.trigger_thread_started) usleep(10);
1725
 
    }
1726
 
    
1727
 
    if (grab_mode&GRAB_MODE_GRAB) {
1728
 
        pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT);
1729
 
    }
1730
 
 
1731
 
    gettimeofday(&end_time, NULL);
1732
 
 
1733
 
    if (grab_mode&GRAB_MODE_TRIGGER) {
1734
 
        pthread_join(trigger_thread, NULL);
1735
 
    }
1736
 
    
1737
 
 
1738
 
    if (grab_mode&GRAB_MODE_GRAB) {
1739
 
        if (verbose >= 0)
1740
 
            printf("Grabbing is finished, flushing results....\n");
1741
 
    
1742
 
        err = fastwriter_close(ctx.writer);
1743
 
        if (err) Error("Storage problems, error %i", err);
1744
 
    }
1745
 
 
1746
 
    ctx.writing_flag = 0;
1747
 
 
1748
 
    pthread_join(monitor_thread, NULL);
1749
 
 
1750
 
    if ((grab_mode&GRAB_MODE_GRAB)&&(verbose>=0)) {
1751
 
        GrabStats(&ctx, &end_time);
1752
 
        StorageStats(&ctx);
1753
 
    }
1754
 
 
1755
 
    fastwriter_destroy(ctx.writer);
1756
 
 
1757
 
    return 0;
1758
 
}
1759
 
 
1760
 
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) {
1761
 
    int err;
1762
 
    pcilib_dma_engine_t dmaid;
1763
 
    
1764
 
    if (dma == PCILIB_DMA_ENGINE_ADDR_INVALID) {
1765
 
        const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle);
1766
 
 
1767
 
        if (start) Error("DMA engine should be specified");
1768
 
 
1769
 
        for (dmaid = 0; dma_info->engines[dmaid]; dmaid++) {
1770
 
            err = pcilib_start_dma(handle, dmaid, 0);
1771
 
            if (err) Error("Error starting DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr);
1772
 
            err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
1773
 
            if (err) Error("Error stopping DMA Engine (%s %i)", ((dma_info->engines[dmaid]->direction == PCILIB_DMA_FROM_DEVICE)?"C2S":"S2C"), dma_info->engines[dmaid]->addr);
1774
 
        }
1775
 
        
1776
 
        return 0;
1777
 
    }
1778
 
    
1779
 
    if (dma_direction&PCILIB_DMA_FROM_DEVICE) {
1780
 
        dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, dma);
1781
 
        if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (C2S %lu) is specified", dma);
1782
 
        
1783
 
        if (start) {
1784
 
            err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
1785
 
            if (err) Error("Error starting DMA engine (C2S %lu)", dma);
1786
 
        } else {
1787
 
            err = pcilib_start_dma(handle, dmaid, 0);
1788
 
            if (err) Error("Error starting DMA engine (C2S %lu)", dma);
1789
 
            err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
1790
 
            if (err) Error("Error stopping DMA engine (C2S %lu)", dma);
1791
 
        }
1792
 
    }
1793
 
    
1794
 
    if (dma_direction&PCILIB_DMA_TO_DEVICE) {
1795
 
        dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, dma);
1796
 
        if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("Invalid DMA engine (S2C %lu) is specified", dma);
1797
 
        
1798
 
        if (start) {
1799
 
            err = pcilib_start_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
1800
 
            if (err) Error("Error starting DMA engine (S2C %lu)", dma);
1801
 
        } else {
1802
 
            err = pcilib_start_dma(handle, dmaid, 0);
1803
 
            if (err) Error("Error starting DMA engine (S2C %lu)", dma);
1804
 
            err = pcilib_stop_dma(handle, dmaid, PCILIB_DMA_FLAG_PERSISTENT);
1805
 
            if (err) Error("Error stopping DMA engine (S2C %lu)", dma);
1806
 
        }
1807
 
    }
1808
 
 
1809
 
    return 0;
1810
 
}
1811
 
 
1812
 
 
1813
 
typedef struct {
1814
 
    pcilib_kmem_use_t use;
1815
 
    
1816
 
    int referenced;
1817
 
    int hw_lock;
1818
 
    int reusable;
1819
 
    int persistent;
1820
 
    int open;
1821
 
    
1822
 
    size_t count;
1823
 
    size_t size;
1824
 
} kmem_use_info_t;
1825
 
 
1826
 
#define MAX_USES 64
1827
 
 
1828
 
pcilib_kmem_use_t ParseUse(const char *use) {
1829
 
    unsigned long utmp;
1830
 
 
1831
 
    if (use) {
1832
 
        if ((!isxnumber(use))||(sscanf(use, "%lx", &utmp) != 1)) Error("Invalid use (%s) is specified", use);
1833
 
 
1834
 
        if (strlen(use) < 5)
1835
 
            return PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER,utmp);
1836
 
        else
1837
 
            return utmp;
1838
 
    }
1839
 
 
1840
 
    Error("Kernel memory use is not specified");
1841
 
    return 0;
1842
 
}
1843
 
 
1844
 
size_t FindUse(size_t *n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) {
1845
 
    size_t i, n = *n_uses;
1846
 
    
1847
 
    if (uses[n - 1].use == use) return n - 1;
1848
 
 
1849
 
    for (i = 1; i < (n - 1); i++) {
1850
 
        if (uses[i].use == use) return i;
1851
 
    }
1852
 
    
1853
 
    if (n == MAX_USES) return 0;
1854
 
 
1855
 
    uses[n].use = use;
1856
 
    return (*n_uses)++;
1857
 
}
1858
 
 
1859
 
 
1860
 
kmem_use_info_t *GetUse(size_t n_uses, kmem_use_info_t *uses, pcilib_kmem_use_t use) {
1861
 
    size_t i;
1862
 
    for (i = 0; i < n_uses; i++) {
1863
 
        if (uses[i].use == use) {
1864
 
            if (uses[i].count) return uses + i;
1865
 
            else return NULL;
1866
 
        }
1867
 
    }
1868
 
    return NULL;
1869
 
}
1870
 
 
1871
 
 
1872
 
int ParseKMEM(pcilib_t *handle, const char *device, size_t *uses_number, kmem_use_info_t *uses) {
1873
 
    DIR *dir;
1874
 
    struct dirent *entry;
1875
 
    const char *pos;
1876
 
    char sysdir[256];
1877
 
    char fname[256];
1878
 
    char info[256];
1879
 
 
1880
 
    size_t useid, n_uses = 1;   // Use 0 is for others
1881
 
 
1882
 
    memset(uses, 0, sizeof(uses));
1883
 
    
1884
 
    pos = strrchr(device, '/');
1885
 
    if (pos) ++pos;
1886
 
    else pos = device;
1887
 
    
1888
 
    snprintf(sysdir, 255, "/sys/class/fpga/%s", pos);
1889
 
 
1890
 
    dir = opendir(sysdir);
1891
 
    if (!dir) Error("Can't open directory (%s)", sysdir);
1892
 
    
1893
 
    while ((entry = readdir(dir)) != NULL) {
1894
 
        FILE *f;
1895
 
        unsigned long use = 0;
1896
 
        unsigned long size = 0;
1897
 
        unsigned long refs = 0;
1898
 
        unsigned long mode = 0;
1899
 
        unsigned long hwref = 0;
1900
 
        
1901
 
        if (strncmp(entry->d_name, "kbuf", 4)) continue;
1902
 
        if (!isnumber(entry->d_name+4)) continue;
1903
 
        
1904
 
        snprintf(fname, 255, "%s/%s", sysdir, entry->d_name);
1905
 
        f = fopen(fname, "r");
1906
 
        if (!f) Error("Can't access file (%s)", fname);
1907
 
 
1908
 
        while(!feof(f)) {
1909
 
            fgets(info, 256, f);
1910
 
            if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16);
1911
 
            if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
1912
 
            if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
1913
 
            if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16);
1914
 
            if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
1915
 
        }
1916
 
        fclose(f);
1917
 
 
1918
 
        useid = FindUse(&n_uses, uses, use);
1919
 
        uses[useid].count++;
1920
 
        uses[useid].size += size;
1921
 
        if (refs) uses[useid].referenced = 1;
1922
 
        if (hwref) uses[useid].hw_lock = 1;
1923
 
        if (mode&KMEM_MODE_REUSABLE) uses[useid].reusable = 1;
1924
 
        if (mode&KMEM_MODE_PERSISTENT) uses[useid].persistent = 1;
1925
 
        if (mode&KMEM_MODE_COUNT) uses[useid].open = 1;
1926
 
    }
1927
 
    closedir(dir);
1928
 
 
1929
 
    *uses_number = n_uses;
1930
 
 
1931
 
    return 0;
1932
 
}
1933
 
 
1934
 
int ListKMEM(pcilib_t *handle, const char *device) {
1935
 
    int err;
1936
 
    char stmp[256];
1937
 
 
1938
 
    size_t i, useid, n_uses;    
1939
 
    kmem_use_info_t uses[MAX_USES];
1940
 
 
1941
 
    err = ParseKMEM(handle, device, &n_uses, uses);
1942
 
    if (err) Error("Failed to parse kernel memory information provided through sysfs");
1943
 
 
1944
 
    if ((n_uses == 1)&&(uses[0].count == 0)) {
1945
 
        printf("No kernel memory is allocated\n");
1946
 
        return 0;
1947
 
    }
1948
 
    
1949
 
    printf("Use      Type                  Count      Total Size       REF       Mode \n");
1950
 
    printf("--------------------------------------------------------------------------------\n");
1951
 
    for (useid = 0; useid < n_uses; useid++) {
1952
 
        if (useid + 1 == n_uses) {
1953
 
            if (!uses[0].count) continue;
1954
 
            i = 0;
1955
 
        } else i = useid + 1;
1956
 
        
1957
 
        printf("%08x  ", uses[i].use);
1958
 
        if (!i) printf("All Others         ");
1959
 
        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"));
1960
 
        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"));
1961
 
        else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_USER)   printf("User %04x         ", uses[i].use&0xFFFF);
1962
 
        else printf ("                   ");
1963
 
        printf("  ");
1964
 
        printf("% 6lu", uses[i].count);
1965
 
        printf("     ");
1966
 
        printf("% 10s", GetPrintSize(stmp, uses[i].size));
1967
 
        printf("      ");
1968
 
        if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW");
1969
 
        else if (uses[i].referenced) printf("   SW");
1970
 
        else if (uses[i].hw_lock) printf("HW   ");
1971
 
        else printf("  -  ");
1972
 
        printf("      ");
1973
 
        if (uses[i].persistent) printf("Persistent");
1974
 
        else if (uses[i].open) printf("Open      ");
1975
 
        else if (uses[i].reusable) printf("Reusable  ");
1976
 
        else printf("Closed    ");
1977
 
        printf("\n");
1978
 
    }
1979
 
    printf("--------------------------------------------------------------------------------\n");
1980
 
    printf("REF - Software/Hardware Reference, MODE - Reusable/Persistent/Open\n");
1981
 
 
1982
 
 
1983
 
    return 0;
1984
 
}
1985
 
 
1986
 
int DetailKMEM(pcilib_t *handle, const char *device, const char *use, size_t block) {
1987
 
    int err;
1988
 
    size_t i, n;
1989
 
    pcilib_kmem_handle_t *kbuf;
1990
 
    pcilib_kmem_use_t useid = ParseUse(use); 
1991
 
 
1992
 
    size_t n_uses;      
1993
 
    kmem_use_info_t uses[MAX_USES];
1994
 
    kmem_use_info_t *use_info;
1995
 
    
1996
 
    if (block == (size_t)-1) {
1997
 
        err = ParseKMEM(handle, device, &n_uses, uses);
1998
 
        if (err) Error("Failed to parse kernel memory information provided through sysfs");
1999
 
        use_info = GetUse(n_uses, uses, useid);
2000
 
        if (!use_info) Error("No kernel buffers is allocated for the specified use (%lx)", useid);
2001
 
 
2002
 
        i = 0;    
2003
 
        n = use_info->count;
2004
 
    } else {
2005
 
        i = block;
2006
 
        n = block + 1;
2007
 
    }
2008
 
    
2009
 
    kbuf = pcilib_alloc_kernel_memory(handle, 0, n, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
2010
 
    if (!kbuf) {
2011
 
        Error("Allocation of kernel buffer (use %lx, count %lu) is failed\n", useid, n);
2012
 
        return 0;
2013
 
    }
2014
 
 
2015
 
    printf("Buffer         Address          Hardware Address          Bus Address\n");
2016
 
    printf("--------------------------------------------------------------------------------\n");
2017
 
    for (; i < n; i++) {
2018
 
        void *data = pcilib_kmem_get_block_ua(handle, kbuf, i);
2019
 
        uintptr_t pa = pcilib_kmem_get_block_pa(handle, kbuf, i);
2020
 
        uintptr_t ba = pcilib_kmem_get_block_ba(handle, kbuf, i);
2021
 
        printf("%6lu     %16p     %16lx       %16lx\n", i, data, pa, ba);
2022
 
    }
2023
 
    printf("\n");
2024
 
 
2025
 
    pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
2026
 
 
2027
 
    return 0;
2028
 
}
2029
 
 
2030
 
 
2031
 
int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t useid, size_t block, size_t max_size, FILE *o) {
2032
 
    int err;
2033
 
    void *data;
2034
 
    size_t size;
2035
 
    pcilib_kmem_handle_t *kbuf;
2036
 
 
2037
 
    if (block == (size_t)-1) block = 0;
2038
 
 
2039
 
    kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
2040
 
    if (!kbuf) {
2041
 
        Error("The specified kernel buffer is not allocated\n");
2042
 
        return 0;
2043
 
    }
2044
 
 
2045
 
    err = pcilib_kmem_sync_block(handle, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, block);
2046
 
    if (err) {
2047
 
        pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
2048
 
        Error("The synchronization of kernel buffer has failed\n");
2049
 
        return 0;
2050
 
    }
2051
 
 
2052
 
    data = pcilib_kmem_get_block_ua(handle, kbuf, block);
2053
 
    if (data) {
2054
 
        size = pcilib_kmem_get_block_size(handle, kbuf, block);
2055
 
        if ((max_size)&&(size > max_size)) size = max_size;
2056
 
        
2057
 
        fwrite(data, 1, size, o?o:stdout);
2058
 
    } else {
2059
 
        pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
2060
 
        Error("The specified block is not existing\n");
2061
 
        return 0;
2062
 
    }
2063
 
 
2064
 
    pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
2065
 
 
2066
 
    return 0;
2067
 
}
2068
 
 
2069
 
int AllocKMEM(pcilib_t *handle, const char *device, const char *use, const char *type, size_t size, size_t block_size, size_t alignment) {
2070
 
    pcilib_kmem_type_t ktype = PCILIB_KMEM_TYPE_PAGE;
2071
 
    pcilib_kmem_flags_t flags = KMEM_FLAG_REUSE;
2072
 
    pcilib_kmem_handle_t *kbuf;
2073
 
    pcilib_kmem_use_t useid = ParseUse(use);
2074
 
 
2075
 
    long page_size = sysconf(_SC_PAGESIZE);
2076
 
 
2077
 
    if (type) {
2078
 
        if (!strcmp(type, "consistent")) ktype = PCILIB_KMEM_TYPE_CONSISTENT;
2079
 
        else if (!strcmp(type, "c2s")) ktype = PCILIB_KMEM_TYPE_DMA_C2S_PAGE;
2080
 
        else if (!strcmp(type, "s2c")) ktype = PCILIB_KMEM_TYPE_DMA_S2C_PAGE;
2081
 
        else Error("Invalid memory type (%s) is specified", type);
2082
 
    } 
2083
 
    
2084
 
    if ((block_size)&&(ktype != PCILIB_KMEM_TYPE_CONSISTENT))
2085
 
        Error("Selected memory type does not allow custom size");
2086
 
    
2087
 
    kbuf = pcilib_alloc_kernel_memory(handle, ktype, size, (block_size?block_size:page_size), (alignment?alignment:page_size), useid, flags|KMEM_FLAG_PERSISTENT);
2088
 
    if (!kbuf) Error("Allocation of kernel memory has failed");
2089
 
 
2090
 
    pcilib_free_kernel_memory(handle, kbuf, flags);
2091
 
 
2092
 
    return 0;
2093
 
}
2094
 
 
2095
 
int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
2096
 
    int err;
2097
 
    int i;
2098
 
 
2099
 
    pcilib_kmem_use_t useid;
2100
 
 
2101
 
    pcilib_kmem_flags_t flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE; 
2102
 
    if (force) flags |= PCILIB_KMEM_FLAG_FORCE; // this will ignore mmap locks as well.
2103
 
 
2104
 
    if (!strcasecmp(use, "dma")) {
2105
 
        for (i = 0; i < PCILIB_MAX_DMA_ENGINES; i++) {
2106
 
            err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, i), flags);
2107
 
            if (err) Error("Error cleaning DMA%i C2S Ring buffer", i);
2108
 
            err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x80|i), flags);
2109
 
            if (err) Error("Error cleaning DMA%i S2C Ring buffer", i);
2110
 
            err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, i), flags);
2111
 
            if (err) Error("Error cleaning DMA%i C2S Page buffers", i);
2112
 
            err = pcilib_clean_kernel_memory(handle, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x80|i), flags);
2113
 
            if (err) Error("Error cleaning DMA%i S2C Page buffers", i);
2114
 
        }
2115
 
        
2116
 
        return 0;
2117
 
    }
2118
 
 
2119
 
    useid = ParseUse(use);
2120
 
    err = pcilib_clean_kernel_memory(handle, useid, flags);
2121
 
    if (err) Error("Error cleaning kernel buffers for use (0x%lx)", useid);
2122
 
 
2123
 
    return 0;
2124
 
}
2125
 
 
2126
 
int ListDMA(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info) {
2127
 
    int err;
2128
 
    
2129
 
    DIR *dir;
2130
 
    struct dirent *entry;
2131
 
    const char *pos;
2132
 
    char sysdir[256];
2133
 
    char fname[256];
2134
 
    char info[256];
2135
 
    char stmp[256];
2136
 
 
2137
 
    pcilib_dma_engine_t dmaid;
2138
 
    pcilib_dma_engine_status_t status;
2139
 
    
2140
 
    pos = strrchr(device, '/');
2141
 
    if (pos) ++pos;
2142
 
    else pos = device;
2143
 
    
2144
 
    snprintf(sysdir, 255, "/sys/class/fpga/%s", pos);
2145
 
 
2146
 
    dir = opendir(sysdir);
2147
 
    if (!dir) Error("Can't open directory (%s)", sysdir);
2148
 
    
2149
 
    printf("DMA Engine     Status      Total Size         Buffer Ring (1st used - 1st free)\n");
2150
 
    printf("--------------------------------------------------------------------------------\n");
2151
 
    while ((entry = readdir(dir)) != NULL) {
2152
 
        FILE *f;
2153
 
        unsigned long use = 0;
2154
 
//      unsigned long size = 0;
2155
 
//      unsigned long refs = 0;
2156
 
        unsigned long mode = 0;
2157
 
//      unsigned long hwref = 0;
2158
 
        
2159
 
        if (strncmp(entry->d_name, "kbuf", 4)) continue;
2160
 
        if (!isnumber(entry->d_name+4)) continue;
2161
 
        
2162
 
        snprintf(fname, 255, "%s/%s", sysdir, entry->d_name);
2163
 
        f = fopen(fname, "r");
2164
 
        if (!f) Error("Can't access file (%s)", fname);
2165
 
 
2166
 
        while(!feof(f)) {
2167
 
            fgets(info, 256, f);
2168
 
            if (!strncmp(info, "use:", 4)) use = strtoul(info+4, NULL, 16);
2169
 
//          if (!strncmp(info, "size:", 5)) size = strtoul(info+5, NULL, 10);
2170
 
//          if (!strncmp(info, "refs:", 5)) refs = strtoul(info+5, NULL, 10);
2171
 
            if (!strncmp(info, "mode:", 5)) mode = strtoul(info+5, NULL, 16);
2172
 
//          if (!strncmp(info, "hw ref:", 7)) hwref = strtoul(info+7, NULL, 10);
2173
 
        }
2174
 
        fclose(f);
2175
 
        
2176
 
        if ((mode&(KMEM_MODE_REUSABLE|KMEM_MODE_PERSISTENT|KMEM_MODE_COUNT)) == 0) continue;    // closed
2177
 
        if ((use >> 16) != PCILIB_KMEM_USE_DMA_RING) continue;
2178
 
 
2179
 
        if (use&0x80) {
2180
 
            dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_TO_DEVICE, use&0x7F);
2181
 
        } else {
2182
 
            dmaid = pcilib_find_dma_by_addr(handle, PCILIB_DMA_FROM_DEVICE, use&0x7F);
2183
 
        }
2184
 
        
2185
 
        if (dmaid == PCILIB_DMA_ENGINE_INVALID) continue;
2186
 
        
2187
 
        
2188
 
        printf("DMA%lu %s         ", use&0x7F, (use&0x80)?"S2C":"C2S");
2189
 
        err = pcilib_start_dma(handle, dmaid, 0);
2190
 
        if (err) {
2191
 
            printf("-- Wrong state, start is failed\n");
2192
 
            continue;
2193
 
        }
2194
 
        
2195
 
        err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
2196
 
        if (err) {
2197
 
            printf("-- Wrong state, failed to obtain status\n");
2198
 
            pcilib_stop_dma(handle, dmaid, 0);
2199
 
            continue;
2200
 
        }
2201
 
 
2202
 
        pcilib_stop_dma(handle, dmaid, 0);
2203
 
        
2204
 
        if (status.started) printf("S");
2205
 
        else printf(" ");
2206
 
        
2207
 
        if (status.ring_head == status.ring_tail) printf(" ");
2208
 
        else printf("D");
2209
 
 
2210
 
        printf("        ");
2211
 
        printf("% 10s", GetPrintSize(stmp, status.ring_size * status.buffer_size));
2212
 
        
2213
 
        printf("         ");
2214
 
        printf("%zu - %zu (of %zu)", status.ring_tail, status.ring_head, status.ring_size);
2215
 
 
2216
 
        printf("\n");
2217
 
        
2218
 
    }
2219
 
    closedir(dir);
2220
 
 
2221
 
    printf("--------------------------------------------------------------------------------\n");
2222
 
    printf("S - Started, D - Data in buffers\n");
2223
 
 
2224
 
    return 0;
2225
 
}
2226
 
 
2227
 
int ListBuffers(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction) {
2228
 
    int err;
2229
 
    size_t i;
2230
 
    pcilib_dma_engine_t dmaid;
2231
 
    pcilib_dma_engine_status_t status;
2232
 
    pcilib_dma_buffer_status_t *buffer;
2233
 
    char stmp[256];
2234
 
 
2235
 
    dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma);
2236
 
    if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found");
2237
 
 
2238
 
    err = pcilib_start_dma(handle, dmaid, 0);
2239
 
    if (err) Error("Error starting the specified DMA engine");
2240
 
 
2241
 
    err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
2242
 
    if (err) Error("Failed to obtain status of the specified DMA engine");
2243
 
 
2244
 
    buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t));
2245
 
    if (!buffer) Error("Failed to allocate memory for status buffer");
2246
 
 
2247
 
    err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer);
2248
 
    if (err) Error("Failed to obtain extended status of the specified DMA engine");
2249
 
 
2250
 
 
2251
 
    printf("Buffer      Status      Total Size         \n");
2252
 
    printf("--------------------------------------------------------------------------------\n");
2253
 
 
2254
 
    for (i = 0; i < status.ring_size; i++) {
2255
 
        printf("%8zu    ", i);
2256
 
        printf("%c%c %c%c ", buffer[i].used?'U':' ',  buffer[i].error?'E':' ', buffer[i].first?'F':' ', buffer[i].last?'L':' ');
2257
 
        printf("% 10s", GetPrintSize(stmp, buffer[i].size));
2258
 
        printf("\n");
2259
 
    }
2260
 
 
2261
 
    printf("--------------------------------------------------------------------------------\n");
2262
 
    printf("U - Used, E - Error, F - First block, L - Last Block\n");
2263
 
 
2264
 
    free(buffer);
2265
 
 
2266
 
    pcilib_stop_dma(handle, dmaid, 0);
2267
 
 
2268
 
    return 0;
2269
 
}
2270
 
 
2271
 
int ReadBuffer(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, size_t block, FILE *o) {
2272
 
    int err;
2273
 
    pcilib_dma_engine_t dmaid;
2274
 
    pcilib_dma_engine_status_t status;
2275
 
    pcilib_dma_buffer_status_t *buffer;
2276
 
    size_t size;
2277
 
 
2278
 
    dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma);
2279
 
    if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found");
2280
 
 
2281
 
    err = pcilib_start_dma(handle, dmaid, 0);
2282
 
    if (err) Error("Error starting the specified DMA engine");
2283
 
    
2284
 
    err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
2285
 
    if (err) Error("Failed to obtain status of the specified DMA engine");
2286
 
    
2287
 
    buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t));
2288
 
    if (!buffer) Error("Failed to allocate memory for status buffer");
2289
 
 
2290
 
    err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer);
2291
 
    if (err) Error("Failed to obtain extended status of the specified DMA engine");
2292
 
 
2293
 
    if (block == (size_t)-1) {
2294
 
        // get current 
2295
 
    }
2296
 
 
2297
 
    size = buffer[block].size;
2298
 
 
2299
 
    free(buffer);
2300
 
 
2301
 
    pcilib_stop_dma(handle, dmaid, 0);
2302
 
 
2303
 
    return ReadKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, o);
2304
 
}
2305
 
 
2306
 
 
2307
 
int EnableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) {
2308
 
    int err;
2309
 
 
2310
 
    err = pcilib_enable_irq(handle, irq_type, 0);
2311
 
    if (err) {
2312
 
        if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE))
2313
 
            Error("Error enabling IRQs");
2314
 
    }
2315
 
    
2316
 
    return err;
2317
 
}
2318
 
 
2319
 
int DisableIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_type_t irq_type) {
2320
 
    int err;
2321
 
    
2322
 
    err = pcilib_disable_irq(handle, 0);
2323
 
    if (err) {
2324
 
        if ((err != PCILIB_ERROR_NOTSUPPORTED)&&(err != PCILIB_ERROR_NOTAVAILABLE))
2325
 
            Error("Error disabling IRQs");
2326
 
    }
2327
 
    
2328
 
    return err;
2329
 
}
2330
 
 
2331
 
int AckIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source) {
2332
 
    pcilib_clear_irq(handle, irq_source);
2333
 
    return 0;
2334
 
}
2335
 
 
2336
 
int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source, pcilib_timeout_t timeout) {
2337
 
    int err;
2338
 
    size_t count;
2339
 
 
2340
 
    err = pcilib_wait_irq(handle, irq_source, timeout, &count);
2341
 
    if (err) {
2342
 
        if (err == PCILIB_ERROR_TIMEOUT) Error("Timeout waiting for IRQ");
2343
 
        else Error("Error waiting for IRQ");
2344
 
    }
2345
 
 
2346
 
    return 0;
2347
 
}
2348
 
 
2349
 
 
2350
 
int main(int argc, char **argv) {
2351
 
    int i;
2352
 
    long itmp;
2353
 
    size_t ztmp;
2354
 
    unsigned char c;
2355
 
 
2356
 
    const char *stmp;
2357
 
    const char *num_offset;
2358
 
 
2359
 
    int details = 0;
2360
 
    int verbose = 0;
2361
 
    int quiete = 0;
2362
 
    int force = 0;
2363
 
    int verify = 0;
2364
 
    
2365
 
    pcilib_model_t model = PCILIB_MODEL_DETECT;
2366
 
    pcilib_model_description_t *model_info;
2367
 
    MODE mode = MODE_INVALID;
2368
 
    GRAB_MODE grab_mode = 0;
2369
 
    size_t trigger_time = 0;
2370
 
    size_t run_time = 0;
2371
 
    size_t buffer = 0;
2372
 
    size_t threads = 1;
2373
 
    FORMAT format = FORMAT_DEFAULT;
2374
 
    PARTITION partition = PARTITION_UNKNOWN;
2375
 
    FLAGS flags = 0;
2376
 
    const char *atype = NULL;
2377
 
    const char *type = NULL;
2378
 
    ACCESS_MODE amode = ACCESS_BAR;
2379
 
    const char *fpga_device = DEFAULT_FPGA_DEVICE;
2380
 
    pcilib_bar_t bar = PCILIB_BAR_DETECT;
2381
 
    const char *addr = NULL;
2382
 
    const char *reg = NULL;
2383
 
    const char *bank = NULL;
2384
 
    char **data = NULL;
2385
 
    const char *event = NULL;
2386
 
    const char *data_type = NULL;
2387
 
    const char *dma_channel = NULL;
2388
 
    const char *use = NULL;
2389
 
    size_t block = (size_t)-1;
2390
 
    pcilib_irq_type_t irq_type = PCILIB_IRQ_TYPE_ALL;
2391
 
    pcilib_irq_hw_source_t irq_source =  PCILIB_IRQ_SOURCE_DEFAULT;
2392
 
    pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
2393
 
    pcilib_kmem_use_t useid = 0;
2394
 
    
2395
 
    pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID;
2396
 
    long addr_shift = 0;
2397
 
    uintptr_t start = -1;
2398
 
    size_t block_size = 0;
2399
 
    size_t size = 1;
2400
 
    access_t access = 4;
2401
 
//    int skip = 0;
2402
 
    int endianess = 0;
2403
 
    size_t timeout = 0;
2404
 
    size_t alignment = 0;
2405
 
    const char *output = NULL;
2406
 
    FILE *ofile = NULL;
2407
 
    size_t iterations = BENCHMARK_ITERATIONS;
2408
 
 
2409
 
    pcilib_t *handle;
2410
 
 
2411
 
    int size_set = 0;
2412
 
    int timeout_set = 0;
2413
 
//    int run_time_set = 0;
2414
 
 
2415
 
    while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) {
2416
 
        extern int optind;
2417
 
        switch (c) {
2418
 
            case OPT_HELP:
2419
 
                Usage(argc, argv, NULL);
2420
 
            break;
2421
 
            case OPT_INFO:
2422
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2423
 
 
2424
 
                mode = MODE_INFO;
2425
 
            break;
2426
 
            case OPT_LIST:
2427
 
                if (mode == MODE_LIST) details++;
2428
 
                else if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2429
 
 
2430
 
                mode = MODE_LIST;
2431
 
            break;
2432
 
            case OPT_RESET:
2433
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2434
 
 
2435
 
                mode = MODE_RESET;
2436
 
            break;
2437
 
            case OPT_BENCHMARK:
2438
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2439
 
 
2440
 
                mode = MODE_BENCHMARK;
2441
 
 
2442
 
                if (optarg) addr = optarg;
2443
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
2444
 
            break;
2445
 
            case OPT_READ:
2446
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2447
 
                
2448
 
                mode = MODE_READ;
2449
 
                if (optarg) addr = optarg;
2450
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
2451
 
            break;
2452
 
            case OPT_WRITE:
2453
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2454
 
 
2455
 
                mode = MODE_WRITE;
2456
 
                if (optarg) addr = optarg;
2457
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
2458
 
            break;
2459
 
            case OPT_GRAB:
2460
 
                if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_GRAB))) Usage(argc, argv, "Multiple operations are not supported");
2461
 
 
2462
 
                mode = MODE_GRAB;
2463
 
                grab_mode |= GRAB_MODE_GRAB;
2464
 
                
2465
 
                stmp = NULL;
2466
 
                if (optarg) stmp = optarg;
2467
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++];
2468
 
 
2469
 
                if (stmp) {
2470
 
                    if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event");
2471
 
                    event = stmp;
2472
 
                }
2473
 
            break;
2474
 
            case OPT_TRIGGER:
2475
 
                if ((mode != MODE_INVALID)&&((mode != MODE_GRAB)||(grab_mode&GRAB_MODE_TRIGGER))) Usage(argc, argv, "Multiple operations are not supported");
2476
 
 
2477
 
                mode = MODE_GRAB;
2478
 
                grab_mode |= GRAB_MODE_TRIGGER;
2479
 
                
2480
 
                stmp = NULL;
2481
 
                if (optarg) stmp = optarg;
2482
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) stmp = argv[optind++];
2483
 
 
2484
 
                if (stmp) {
2485
 
                    if ((event)&&(strcasecmp(stmp,event))) Usage(argc, argv, "Redefinition of considered event");
2486
 
                    event = stmp;
2487
 
                }
2488
 
            break;
2489
 
            case OPT_LIST_DMA:
2490
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2491
 
                
2492
 
                mode = MODE_LIST_DMA;
2493
 
            break;
2494
 
            case OPT_LIST_DMA_BUFFERS:
2495
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2496
 
                
2497
 
                mode = MODE_LIST_DMA_BUFFERS;
2498
 
                dma_channel = optarg;
2499
 
            break;
2500
 
            case OPT_READ_DMA_BUFFER:
2501
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2502
 
                
2503
 
                mode = MODE_READ_DMA_BUFFER;
2504
 
 
2505
 
                num_offset = strchr(optarg, ':');
2506
 
 
2507
 
                if (num_offset) {
2508
 
                    if (sscanf(num_offset + 1, "%zu", &block) != 1)
2509
 
                        Usage(argc, argv, "Invalid buffer is specified (%s)", num_offset + 1);
2510
 
 
2511
 
                    *(char*)num_offset = 0;
2512
 
                } else block = (size_t)-1;
2513
 
                
2514
 
                dma_channel = optarg;
2515
 
            break;
2516
 
            case OPT_START_DMA:
2517
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2518
 
                
2519
 
                mode = MODE_START_DMA;
2520
 
                if (optarg) dma_channel = optarg;
2521
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
2522
 
            break;
2523
 
            case OPT_STOP_DMA:
2524
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2525
 
                
2526
 
                mode = MODE_STOP_DMA;
2527
 
                if (optarg) dma_channel = optarg;
2528
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) dma_channel = argv[optind++];
2529
 
            break;
2530
 
            case OPT_ENABLE_IRQ:
2531
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2532
 
                
2533
 
                mode = MODE_ENABLE_IRQ;
2534
 
                if (optarg) num_offset = optarg;
2535
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  num_offset = argv[optind++];
2536
 
                else num_offset = NULL;
2537
 
                
2538
 
                if (num_offset) {
2539
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
2540
 
                        Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
2541
 
 
2542
 
                    irq_type = itmp;
2543
 
                }
2544
 
            break;
2545
 
            case OPT_DISABLE_IRQ:
2546
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2547
 
                
2548
 
                mode = MODE_DISABLE_IRQ;
2549
 
                if (optarg) num_offset = optarg;
2550
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  num_offset = argv[optind++];
2551
 
                else num_offset = NULL;
2552
 
                
2553
 
                if (num_offset) {
2554
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
2555
 
                        Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
2556
 
 
2557
 
                    irq_type = itmp;
2558
 
                }
2559
 
            break;
2560
 
            case OPT_ACK_IRQ:
2561
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2562
 
                
2563
 
                mode = MODE_ACK_IRQ;
2564
 
                if (optarg) num_offset = optarg;
2565
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  num_offset = argv[optind++];
2566
 
                else num_offset = NULL;
2567
 
                
2568
 
                if (num_offset) {
2569
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
2570
 
                        Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
2571
 
 
2572
 
                    irq_source = itmp;
2573
 
                }
2574
 
            break;
2575
 
            case OPT_WAIT_IRQ:
2576
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2577
 
                
2578
 
                mode = MODE_WAIT_IRQ;
2579
 
                if (optarg) num_offset = optarg;
2580
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  num_offset = argv[optind++];
2581
 
                else num_offset = NULL;
2582
 
                
2583
 
                if (num_offset) {
2584
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
2585
 
                        Usage(argc, argv, "Invalid IRQ source is specified (%s)", num_offset);
2586
 
 
2587
 
                    irq_source = itmp;
2588
 
                }
2589
 
            break;
2590
 
            case OPT_LIST_KMEM:
2591
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2592
 
                mode = MODE_LIST_KMEM;
2593
 
                
2594
 
                if (optarg) use = optarg;
2595
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  use = argv[optind++];
2596
 
                else use = NULL;
2597
 
                
2598
 
                if (use) {
2599
 
                    num_offset = strchr(use, ':');
2600
 
 
2601
 
                    if (num_offset) {
2602
 
                        if (sscanf(num_offset + 1, "%zu", &block) != 1)
2603
 
                            Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
2604
 
 
2605
 
                        *(char*)num_offset = 0;
2606
 
                    }
2607
 
                }
2608
 
            break;
2609
 
            case OPT_READ_KMEM:
2610
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2611
 
                mode = MODE_READ_KMEM;
2612
 
 
2613
 
                num_offset = strchr(optarg, ':');
2614
 
 
2615
 
                if (num_offset) {
2616
 
                    if (sscanf(num_offset + 1, "%zu", &block) != 1)
2617
 
                        Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
2618
 
 
2619
 
                    *(char*)num_offset = 0;
2620
 
                }
2621
 
                
2622
 
                use = optarg;
2623
 
                useid = ParseUse(use);
2624
 
            break;
2625
 
            case OPT_ALLOC_KMEM:
2626
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2627
 
                mode = MODE_ALLOC_KMEM;
2628
 
 
2629
 
                if (optarg) use = optarg;
2630
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++];
2631
 
            break;
2632
 
            case OPT_FREE_KMEM:
2633
 
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
2634
 
                mode = MODE_FREE_KMEM;
2635
 
 
2636
 
                if (optarg) use = optarg;
2637
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) use = argv[optind++];
2638
 
            break;
2639
 
            case OPT_DEVICE:
2640
 
                fpga_device = optarg;
2641
 
            break;
2642
 
            case OPT_MODEL:
2643
 
                if (!strcasecmp(optarg, "pci")) model = PCILIB_MODEL_PCI;
2644
 
                else if (!strcasecmp(optarg, "ipecamera")) model = PCILIB_MODEL_IPECAMERA;
2645
 
                else if (!strcasecmp(optarg, "kapture")) model = PCILIB_MODEL_KAPTURE;
2646
 
                else Usage(argc, argv, "Invalid memory model (%s) is specified", optarg);
2647
 
            break;
2648
 
            case OPT_BAR:
2649
 
                bank = optarg;
2650
 
//              if ((sscanf(optarg,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
2651
 
//              else bar = itmp;
2652
 
            break;
2653
 
            case OPT_ALIGNMENT:
2654
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &alignment) != 1)) {
2655
 
                    Usage(argc, argv, "Invalid alignment is specified (%s)", optarg);
2656
 
                }
2657
 
            break;
2658
 
            case OPT_ACCESS:
2659
 
                if (!strncasecmp(optarg, "fifo", 4)) {
2660
 
                    atype = "fifo";
2661
 
                    num_offset = optarg + 4;
2662
 
                    amode = ACCESS_FIFO;
2663
 
                } else if (!strncasecmp(optarg, "dma", 3)) {
2664
 
                    atype = "dma";
2665
 
                    num_offset = optarg + 3;
2666
 
                    amode = ACCESS_DMA;
2667
 
                } else if (!strncasecmp(optarg, "bar", 3)) {
2668
 
                    atype = "plain";
2669
 
                    num_offset = optarg + 3;
2670
 
                    amode = ACCESS_BAR;
2671
 
                } else if (!strncasecmp(optarg, "config", 6)) {
2672
 
                    atype = "config";
2673
 
                    num_offset = optarg + 6;
2674
 
                    amode = ACCESS_CONFIG;
2675
 
                } else if (!strncasecmp(optarg, "plain", 5)) {
2676
 
                    atype = "plain";
2677
 
                    num_offset = optarg + 5;
2678
 
                    amode = ACCESS_BAR;
2679
 
                } else {
2680
 
                    num_offset = optarg;
2681
 
                }
2682
 
 
2683
 
                if (*num_offset) {
2684
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%li", &itmp) != 1))
2685
 
                        Usage(argc, argv, "Invalid access type (%s) is specified", optarg);
2686
 
 
2687
 
                    switch (itmp) {
2688
 
                        case 8: access = 1; break;
2689
 
                        case 16: access = 2; break;
2690
 
                        case 32: access = 4; break;
2691
 
                        case 64: access = 8; break;
2692
 
                        default: Usage(argc, argv, "Invalid data width (%s) is specified", num_offset);
2693
 
                    }   
2694
 
                }
2695
 
            break;
2696
 
            case OPT_SIZE:
2697
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &size) != 1)) {
2698
 
                    if (strcasecmp(optarg, "unlimited"))
2699
 
                        Usage(argc, argv, "Invalid size is specified (%s)", optarg);
2700
 
                    else
2701
 
                        size = 0;//(size_t)-1;
2702
 
                }
2703
 
                        
2704
 
                size_set = 1;
2705
 
            break;
2706
 
            case OPT_BLOCK_SIZE:
2707
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &block_size) != 1)) {
2708
 
                    Usage(argc, argv, "Invalid size is specified (%s)", optarg);
2709
 
                }
2710
 
            break;
2711
 
            case OPT_ENDIANESS:
2712
 
                if ((*optarg == 'b')||(*optarg == 'B')) {
2713
 
                    if (ntohs(1) == 1) endianess = 0;
2714
 
                    else endianess = 1;
2715
 
                } else if ((*optarg == 'l')||(*optarg == 'L')) {
2716
 
                    if (ntohs(1) == 1) endianess = 1;
2717
 
                    else endianess = 0;
2718
 
                } else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);
2719
 
                
2720
 
            break;
2721
 
            case OPT_TIMEOUT:
2722
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1)) {
2723
 
                    if (strcasecmp(optarg, "unlimited"))
2724
 
                        Usage(argc, argv, "Invalid timeout is specified (%s)", optarg);
2725
 
                    else
2726
 
                        timeout = PCILIB_TIMEOUT_INFINITE;
2727
 
                }
2728
 
                timeout_set = 1;
2729
 
            break;
2730
 
            case OPT_OUTPUT:
2731
 
                output = optarg;
2732
 
            break;
2733
 
            case OPT_ITERATIONS:
2734
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &iterations) != 1))
2735
 
                    Usage(argc, argv, "Invalid number of iterations is specified (%s)", optarg);
2736
 
            break;
2737
 
            case OPT_EVENT:
2738
 
                event = optarg;
2739
 
            break;
2740
 
            case OPT_TYPE:
2741
 
                type = optarg;
2742
 
            break;
2743
 
            case OPT_DATA_TYPE:
2744
 
                data_type = optarg;
2745
 
            break;
2746
 
            case OPT_RUN_TIME:
2747
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &run_time) != 1)) {
2748
 
                    if (strcasecmp(optarg, "unlimited"))
2749
 
                        Usage(argc, argv, "Invalid run-time is specified (%s)", optarg);
2750
 
                    else
2751
 
                        run_time = 0;
2752
 
                }
2753
 
//              run_time_set = 1;
2754
 
            break;
2755
 
            case OPT_TRIGGER_TIME:
2756
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1))
2757
 
                    Usage(argc, argv, "Invalid trigger-time is specified (%s)", optarg);
2758
 
            break;          
2759
 
            case OPT_TRIGGER_RATE:
2760
 
                if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &ztmp) != 1))
2761
 
                    Usage(argc, argv, "Invalid trigger-rate is specified (%s)", optarg);
2762
 
                    
2763
 
                    trigger_time = (1000000 / ztmp) + ((1000000 % ztmp)?1:0);
2764
 
            break;
2765
 
            case OPT_BUFFER:
2766
 
                if (optarg) num_offset = optarg;
2767
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
2768
 
                else num_offset = NULL;
2769
 
                
2770
 
                if (num_offset) {
2771
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%zu", &buffer) != 1))
2772
 
                        Usage(argc, argv, "Invalid buffer size is specified (%s)", num_offset);
2773
 
                    buffer *= 1024 * 1024;
2774
 
                } else {
2775
 
                    buffer = get_free_memory();
2776
 
                    if (buffer < 256) Error("Not enough free memory (%lz MB) for buffering", buffer / 1024 / 1024);
2777
 
                    
2778
 
                    buffer -= 128 + buffer/16;
2779
 
                }
2780
 
            break;         
2781
 
            case OPT_THREADS:
2782
 
                if (optarg) num_offset = optarg;
2783
 
                else if ((optind < argc)&&(argv[optind][0] != '-')) num_offset = argv[optind++];
2784
 
                else num_offset = NULL;
2785
 
                
2786
 
                if (num_offset) {
2787
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%zu", &threads) != 1))
2788
 
                        Usage(argc, argv, "Invalid threads number is specified (%s)", num_offset);
2789
 
                } else {
2790
 
                    threads = 0;
2791
 
                }
2792
 
            break;         
2793
 
            case OPT_FORMAT:
2794
 
                if (!strcasecmp(optarg, "raw")) format =  FORMAT_RAW;
2795
 
                else if (!strcasecmp(optarg, "add_header")) format =  FORMAT_HEADER;
2796
 
//              else if (!strcasecmp(optarg, "ringfs")) format =  FORMAT_RINGFS;
2797
 
                else if (strcasecmp(optarg, "default")) Error("Invalid format (%s) is specified", optarg);
2798
 
            break; 
2799
 
            case OPT_QUIETE:
2800
 
                quiete = 1;
2801
 
                verbose = -1;
2802
 
            break;
2803
 
            case OPT_VERBOSE:
2804
 
                if (optarg) num_offset = optarg;
2805
 
                else if ((optind < argc)&&(argv[optind][0] != '-'))  num_offset = argv[optind++];
2806
 
                else num_offset = NULL;
2807
 
                
2808
 
                if (num_offset) {
2809
 
                    if ((!isnumber(num_offset))||(sscanf(num_offset, "%i", &verbose) != 1))
2810
 
                        Usage(argc, argv, "Invalid verbosity level is specified (%s)", num_offset);
2811
 
                } else {
2812
 
                    verbose = 1;
2813
 
                }
2814
 
            break;
2815
 
            case OPT_FORCE:
2816
 
                force = 1;
2817
 
            break;
2818
 
            case OPT_VERIFY:
2819
 
                verify = 1;
2820
 
            break;
2821
 
            case OPT_MULTIPACKET:
2822
 
                flags |= FLAG_MULTIPACKET;
2823
 
            break;
2824
 
            case OPT_WAIT:
2825
 
                flags |= FLAG_WAIT;
2826
 
            break;
2827
 
            default:
2828
 
                Usage(argc, argv, "Unknown option (%s) with argument (%s)", optarg?argv[optind-2]:argv[optind-1], optarg?optarg:"(null)");
2829
 
        }
2830
 
    }
2831
 
 
2832
 
    if (mode == MODE_INVALID) {
2833
 
        if (argc > 1) Usage(argc, argv, "Operation is not specified");
2834
 
        else Usage(argc, argv, NULL);
2835
 
    }
2836
 
 
2837
 
    pcilib_set_error_handler(&Error, quiete?Silence:NULL);
2838
 
 
2839
 
    handle = pcilib_open(fpga_device, model);
2840
 
    if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device);
2841
 
 
2842
 
    model = pcilib_get_model(handle);
2843
 
    model_info = pcilib_get_model_description(handle);
2844
 
 
2845
 
    switch (mode) {
2846
 
     case MODE_WRITE:
2847
 
        if (((argc - optind) == 1)&&(*argv[optind] == '*')) {
2848
 
            int vallen = strlen(argv[optind]);
2849
 
            if (vallen > 1) {
2850
 
                data = (char**)malloc(size * (vallen + sizeof(char*)));
2851
 
                if (!data) Error("Error allocating memory for data array");
2852
 
 
2853
 
                for (i = 0; i < size; i++) {
2854
 
                    data[i] = ((char*)data) + size * sizeof(char*) + i * vallen;
2855
 
                    strcpy(data[i], argv[optind] + 1);
2856
 
                }
2857
 
            } else {
2858
 
                data = (char**)malloc(size * (9 + sizeof(char*)));
2859
 
                if (!data) Error("Error allocating memory for data array");
2860
 
                
2861
 
                for (i = 0; i < size; i++) {
2862
 
                    data[i] = ((char*)data) + size * sizeof(char*) + i * 9;
2863
 
                    sprintf(data[i], "%x", i);
2864
 
                }
2865
 
            }
2866
 
        } else if ((argc - optind) == size) data = argv + optind;
2867
 
        else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size);
2868
 
     case MODE_READ:
2869
 
        if (!addr) {
2870
 
            if (model == PCILIB_MODEL_PCI) {
2871
 
                if ((amode != ACCESS_DMA)&&(amode != ACCESS_CONFIG)) 
2872
 
                    Usage(argc, argv, "The address is not specified");
2873
 
            } else ++mode;
2874
 
        }
2875
 
     break;
2876
 
     case MODE_START_DMA:
2877
 
     case MODE_STOP_DMA:
2878
 
     case MODE_LIST_DMA_BUFFERS:
2879
 
     case MODE_READ_DMA_BUFFER:
2880
 
        if ((dma_channel)&&(*dma_channel)) {
2881
 
            itmp = strlen(dma_channel) - 1;
2882
 
            if (dma_channel[itmp] == 'r') dma_direction = PCILIB_DMA_FROM_DEVICE;
2883
 
            else if (dma_channel[itmp] == 'w') dma_direction = PCILIB_DMA_TO_DEVICE;
2884
 
 
2885
 
            if (dma_direction != PCILIB_DMA_BIDIRECTIONAL) itmp--;
2886
 
            
2887
 
            if (strncmp(dma_channel, "dma", 3)) num_offset = dma_channel;
2888
 
            else {
2889
 
                num_offset = dma_channel + 3;
2890
 
                itmp -= 3;
2891
 
            }
2892
 
            
2893
 
            if (bank) {
2894
 
                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);
2895
 
            }
2896
 
                 
2897
 
            if (!isnumber_n(num_offset, itmp))
2898
 
                 Usage(argc, argv, "Invalid DMA channel (%s) is specified", dma_channel);
2899
 
 
2900
 
            dma = atoi(num_offset);
2901
 
        }
2902
 
     break;
2903
 
     default:
2904
 
        if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
2905
 
    }
2906
 
 
2907
 
 
2908
 
    if (addr) {
2909
 
        if ((!strncmp(addr, "dma", 3))&&((addr[3]==0)||isnumber(addr+3))) {
2910
 
            if ((atype)&&(amode != ACCESS_DMA)) Usage(argc, argv, "Conflicting access modes, the DMA read is requested, but access type is (%s)", type);
2911
 
            if (bank) {
2912
 
                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);
2913
 
            } else {
2914
 
                if (addr[3] == 0) Usage(argc, argv, "The DMA channel is not specified");
2915
 
            }
2916
 
            dma = atoi(addr + 3);
2917
 
            amode = ACCESS_DMA;
2918
 
            addr = NULL;
2919
 
        } else if ((!strncmp(addr, "bar", 3))&&((addr[3]==0)||isnumber(addr+3))) {
2920
 
            if ((atype)&&(amode != ACCESS_BAR)) Usage(argc, argv, "Conflicting access modes, the plain PCI read is requested, but access type is (%s)", type);
2921
 
            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);
2922
 
            bar = atoi(addr + 3);
2923
 
            amode = ACCESS_BAR;
2924
 
            addr = NULL;
2925
 
        } else if (!strcmp(addr, "config")) {
2926
 
            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);
2927
 
            amode = ACCESS_CONFIG;
2928
 
            addr = NULL;
2929
 
        } else if ((isxnumber(addr))&&(sscanf(addr, "%lx", &start) == 1)) {
2930
 
                // check if the address in the register range
2931
 
            pcilib_register_range_t *ranges =  model_info->ranges;
2932
 
            
2933
 
            if (ranges) {
2934
 
                for (i = 0; ranges[i].start != ranges[i].end; i++) 
2935
 
                    if ((start >= ranges[i].start)&&(start <= ranges[i].end)) break;
2936
 
                        
2937
 
                    // register access in plain mode
2938
 
                if (ranges[i].start != ranges[i].end) {
2939
 
                    pcilib_register_bank_t regbank = pcilib_find_bank_by_addr(handle, ranges[i].bank);
2940
 
                    if (regbank == PCILIB_REGISTER_BANK_INVALID) Error("Configuration error: register bank specified in the address range is not found");
2941
 
                    
2942
 
                    bank = model_info->banks[regbank].name;
2943
 
                    start += ranges[i].addr_shift;
2944
 
                    addr_shift = ranges[i].addr_shift;
2945
 
                    ++mode;
2946
 
                }
2947
 
            }
2948
 
        } else {
2949
 
            if (pcilib_find_register(handle, bank, addr) == PCILIB_REGISTER_INVALID) {
2950
 
                Usage(argc, argv, "Invalid address (%s) is specified", addr);
2951
 
            } else {
2952
 
                reg = addr;
2953
 
                ++mode;
2954
 
            }
2955
 
        } 
2956
 
    }
2957
 
        
2958
 
    if (mode == MODE_GRAB) {
2959
 
        if (output) {
2960
 
            char fsname[128];
2961
 
            if (!get_file_fs(output, 127, fsname)) {
2962
 
                if (!strcmp(fsname, "ext4")) partition = PARTITION_EXT4;
2963
 
                else if (!strcmp(fsname, "raw")) partition = PARTITION_RAW;
2964
 
            }
2965
 
        } else {
2966
 
            output = "/dev/null";
2967
 
            partition = PARTITION_NULL;
2968
 
        }
2969
 
 
2970
 
        if (!timeout_set) {
2971
 
            if (run_time) timeout = PCILIB_TIMEOUT_INFINITE;
2972
 
            else timeout = PCILIB_EVENT_TIMEOUT;
2973
 
        }
2974
 
        
2975
 
        if (!size_set) {
2976
 
            if (run_time) size = 0;
2977
 
        }
2978
 
    }
2979
 
    
2980
 
    if (mode != MODE_GRAB) {
2981
 
        if (size == (size_t)-1)
2982
 
            Usage(argc, argv, "Unlimited size is not supported in selected operation mode");
2983
 
    }
2984
 
    
2985
 
 
2986
 
    if ((bank)&&(amode == ACCESS_DMA)) {
2987
 
        if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)) 
2988
 
            Usage(argc, argv, "Invalid DMA channel (%s) is specified", bank);
2989
 
        else dma = itmp;
2990
 
    } else if (bank) {
2991
 
        switch (mode) {
2992
 
            case MODE_BENCHMARK:
2993
 
            case MODE_READ:
2994
 
            case MODE_WRITE:
2995
 
                if ((!isnumber(bank))||(sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) 
2996
 
                    Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
2997
 
                else bar = itmp;
2998
 
            break;
2999
 
            default:
3000
 
                if (pcilib_find_bank(handle, bank) == PCILIB_REGISTER_BANK_INVALID)
3001
 
                    Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
3002
 
        }
3003
 
    }
3004
 
 
3005
 
    signal(SIGINT, signal_exit_handler);
3006
 
 
3007
 
    if ((mode != MODE_GRAB)&&(output)) {
3008
 
        ofile = fopen(output, "a+");
3009
 
        if (!ofile) {
3010
 
            Error("Failed to open file \"%s\"", output);
3011
 
        }
3012
 
    }    
3013
 
 
3014
 
    switch (mode) {
3015
 
     case MODE_INFO:
3016
 
        Info(handle, model_info);
3017
 
     break;
3018
 
     case MODE_LIST:
3019
 
        List(handle, model_info, bank, details);
3020
 
     break;
3021
 
     case MODE_BENCHMARK:
3022
 
        Benchmark(handle, amode, dma, bar, start, size_set?size:0, access, iterations);
3023
 
     break;
3024
 
     case MODE_READ:
3025
 
        if (amode == ACCESS_DMA) {
3026
 
            ReadData(handle, amode, flags, dma, bar, start, size_set?size:0, access, endianess, timeout_set?timeout:(size_t)-1, ofile);
3027
 
        } else if (amode == ACCESS_CONFIG) {
3028
 
            ReadData(handle, amode, flags, dma, bar, addr?start:0, (addr||size_set)?size:(256/abs(access)), access, endianess, (size_t)-1, ofile);
3029
 
        } else if (addr) {
3030
 
            ReadData(handle, amode, flags, dma, bar, start, size, access, endianess, (size_t)-1, ofile);
3031
 
        } else {
3032
 
            Error("Address to read is not specified");
3033
 
        }
3034
 
     break;
3035
 
     case MODE_READ_REGISTER:
3036
 
        if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg);
3037
 
        else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile);
3038
 
     break;
3039
 
     case MODE_WRITE:
3040
 
        WriteData(handle, amode, dma, bar, start, size, access, endianess, data, verify);
3041
 
     break;
3042
 
     case MODE_WRITE_REGISTER:
3043
 
        if (reg) WriteRegister(handle, model_info, bank, reg, data);
3044
 
        else WriteRegisterRange(handle, model_info, bank, start, addr_shift, size, data);
3045
 
     break;
3046
 
     case MODE_RESET:
3047
 
        pcilib_reset(handle);
3048
 
     break;
3049
 
     case MODE_GRAB:
3050
 
        TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, timeout, partition, format, buffer, threads, verbose, output);
3051
 
     break;
3052
 
     case MODE_LIST_DMA:
3053
 
        ListDMA(handle, fpga_device, model_info);
3054
 
     break;
3055
 
     case MODE_LIST_DMA_BUFFERS:
3056
 
        ListBuffers(handle, fpga_device, model_info, dma, dma_direction);
3057
 
     break;
3058
 
     case MODE_READ_DMA_BUFFER:
3059
 
        ReadBuffer(handle, fpga_device, model_info, dma, dma_direction, block, ofile);
3060
 
     break;
3061
 
     case MODE_START_DMA:
3062
 
        StartStopDMA(handle, model_info, dma, dma_direction, 1);
3063
 
     break;
3064
 
     case MODE_STOP_DMA:
3065
 
        StartStopDMA(handle, model_info, dma, dma_direction, 0);
3066
 
     break;
3067
 
     case MODE_ENABLE_IRQ:
3068
 
        EnableIRQ(handle, model_info, irq_type);
3069
 
     break;
3070
 
     case MODE_DISABLE_IRQ:
3071
 
        DisableIRQ(handle, model_info, irq_type);
3072
 
     break;
3073
 
     case MODE_ACK_IRQ:
3074
 
        AckIRQ(handle, model_info, irq_source);
3075
 
     break;
3076
 
     case MODE_WAIT_IRQ:
3077
 
        WaitIRQ(handle, model_info, irq_source, timeout);
3078
 
     break;
3079
 
     case MODE_LIST_KMEM:
3080
 
        if (use) DetailKMEM(handle, fpga_device, use, block);
3081
 
        else ListKMEM(handle, fpga_device);
3082
 
     break;
3083
 
     case MODE_READ_KMEM:
3084
 
        ReadKMEM(handle, fpga_device, useid, block, 0, ofile);
3085
 
     break;
3086
 
     case MODE_ALLOC_KMEM:
3087
 
        AllocKMEM(handle, fpga_device, use, type, size, block_size, alignment);
3088
 
     break;
3089
 
     case MODE_FREE_KMEM:
3090
 
        FreeKMEM(handle, fpga_device, use, force);
3091
 
     break;
3092
 
     case MODE_INVALID:
3093
 
        break;
3094
 
    }
3095
 
 
3096
 
    if (ofile) fclose(ofile);
3097
 
 
3098
 
    pcilib_close(handle);
3099
 
    
3100
 
    if (data != argv + optind) free(data);
3101
 
}