/alps/pcitool

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

« back to all changes in this revision

Viewing changes to pci.c

  • Committer: Suren A. Chilingaryan
  • Date: 2011-02-13 02:07:11 UTC
  • Revision ID: csa@dside.dyndns.org-20110213020711-y9bjh3n4ke6p4t4n
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************
 
2
 * This is a test program for the IOctl interface of the 
 
3
 * pciDriver.
 
4
 * 
 
5
 * $Revision: 1.3 $
 
6
 * $Date: 2006-11-17 18:49:01 $
 
7
 * 
 
8
 *******************************************************************/
 
9
 
 
10
/*******************************************************************
 
11
 * Change History:
 
12
 * 
 
13
 * $Log: not supported by cvs2svn $
 
14
 * Revision 1.2  2006/10/16 16:56:09  marcus
 
15
 * Added nice comment at the start.
 
16
 *
 
17
 *******************************************************************/
 
18
 
 
19
#include <stdio.h>
 
20
#include <string.h>
 
21
#include <stdlib.h>
 
22
#include <stdint.h>
 
23
#include <stdarg.h>
 
24
#include <fcntl.h>
 
25
#include <unistd.h>
 
26
#include <sys/ioctl.h>
 
27
#include <sys/mman.h>
 
28
#include <errno.h>
 
29
#include <alloca.h>
 
30
 
 
31
#include <getopt.h>
 
32
 
 
33
#include "driver/pciDriver.h"
 
34
 
 
35
#include "tools.h"
 
36
 
 
37
/* defines */
 
38
#define MAX_KBUF 14
 
39
//#define BIGBUFSIZE (512*1024*1024)
 
40
#define BIGBUFSIZE (1024*1024)
 
41
 
 
42
 
 
43
#define DEFAULT_FPGA_DEVICE "/dev/fpga0"
 
44
#define MAX_BANKS 6
 
45
 
 
46
#define LINE_WIDTH 80
 
47
#define SEPARATOR_WIDTH 2
 
48
#define BLOCK_SEPARATOR_WIDTH 2
 
49
#define BLOCK_SIZE 8
 
50
#define BENCHMARK_ITERATIONS 128
 
51
 
 
52
//#define FILE_IO
 
53
 
 
54
typedef enum {
 
55
    MODE_INVALID,
 
56
    MODE_INFO,
 
57
    MODE_LIST,
 
58
    MODE_BENCHMARK,
 
59
    MODE_READ,
 
60
    MODE_WRITE
 
61
} MODE;
 
62
 
 
63
typedef enum {
 
64
    OPT_DEVICE = 'd',
 
65
    OPT_BAR = 'b',
 
66
    OPT_ACCESS = 'a',
 
67
    OPT_SIZE = 's',
 
68
    OPT_INFO = 'i',
 
69
    OPT_BENCHMARK = 'p',
 
70
    OPT_LIST = 'l',
 
71
    OPT_READ = 'r',
 
72
    OPT_WRITE = 'w',
 
73
    OPT_HELP = 'h',
 
74
} OPTIONS;
 
75
 
 
76
static struct option long_options[] = {
 
77
    {"device",                  required_argument, 0, OPT_DEVICE },
 
78
    {"bar",                     required_argument, 0, OPT_BAR },
 
79
    {"access",                  required_argument, 0, OPT_ACCESS },
 
80
    {"size",                    required_argument, 0, OPT_SIZE },
 
81
    {"info",                    no_argument, 0, OPT_INFO },
 
82
    {"list",                    no_argument, 0, OPT_LIST },
 
83
    {"benchmark",               no_argument, 0, OPT_BENCHMARK },
 
84
    {"read",                    optional_argument, 0, OPT_READ },
 
85
    {"write",                   optional_argument, 0, OPT_WRITE },
 
86
    {"help",                    no_argument, 0, OPT_HELP },
 
87
    { 0, 0, 0, 0 }
 
88
};
 
89
 
 
90
 
 
91
void Usage(int argc, char *argv[], const char *format, ...) {
 
92
    if (format) {
 
93
        va_list ap;
 
94
    
 
95
        va_start(ap, format);
 
96
        printf("Error %i: ", errno);
 
97
        vprintf(format, ap);
 
98
        printf("\n");
 
99
        va_end(ap);
 
100
    
 
101
        printf("\n");
 
102
    }
 
103
 
 
104
 
 
105
    printf(
 
106
"Usage:\n"
 
107
" %s <mode> [options] [hex data]\n"
 
108
"  Modes:\n"
 
109
"       -i              - Device Info\n"
 
110
"       -l              - List Data Banks\n"
 
111
"       -p              - Performance Evaluation\n"
 
112
"       -r <addr>       - Read Data\n"
 
113
"       -w <addr>       - Write Data\n"
 
114
"       --help          - Help message\n"
 
115
"\n"
 
116
"  Addressing:\n"
 
117
"       -d <device>     - FPGA device (/dev/fpga0)\n"
 
118
"       -b <bank>       - Data bank (autodetected)\n"
 
119
"\n"
 
120
"  Options:\n"
 
121
"       -s <size>       - Number of words (default: 1)\n"
 
122
"       -a <bitness>    - Bits per word (default: 32)\n"
 
123
"\n\n",
 
124
argv[0]);
 
125
 
 
126
    exit(0);
 
127
}
 
128
 
 
129
void Error(const char *format, ...) {
 
130
    va_list ap;
 
131
    
 
132
    va_start(ap, format);
 
133
    printf("Error %i: ", errno);
 
134
    vprintf(format, ap);
 
135
    if (errno) printf("\n errno: %s", strerror(errno));
 
136
    printf("\n\n");
 
137
    va_end(ap);
 
138
    
 
139
    exit(-1);
 
140
}
 
141
 
 
142
static pci_board_info board_info;
 
143
static page_mask = -1;
 
144
 
 
145
void GetBoardInfo(int handle) {
 
146
    int ret;
 
147
    
 
148
    if (page_mask < 0) {
 
149
        ret = ioctl( handle, PCIDRIVER_IOC_PCI_INFO, &board_info );
 
150
        if (ret) Error("PCIDRIVER_IOC_PCI_INFO ioctl have failed");
 
151
        
 
152
        page_mask = get_page_mask();
 
153
    }
 
154
}
 
155
 
 
156
void List(int handle) {
 
157
    int i;
 
158
 
 
159
    GetBoardInfo(handle);
 
160
 
 
161
    for (i = 0; i < MAX_BANKS; i++) {
 
162
        if (board_info.bar_length[i] > 0) {
 
163
            printf(" BAR %d - Start: 0x%x, Length: 0x%x\n", i, board_info.bar_start[i], board_info.bar_length[i] );
 
164
        }
 
165
    }
 
166
}
 
167
 
 
168
void Info(int handle) {
 
169
    GetBoardInfo(handle);
 
170
 
 
171
    printf("Vendor: %lx, Device: %lx, Interrupt Pin: %i, Interrupt Line: %i\n", board_info.vendor_id, board_info.device_id, board_info.interrupt_pin, board_info.interrupt_line);
 
172
    List(handle);
 
173
}
 
174
 
 
175
 
 
176
int DetectBar(int handle, unsigned long addr, int size) {
 
177
    int ret,i;
 
178
        
 
179
    GetBoardInfo(handle);
 
180
                
 
181
    for (i = 0; i < MAX_BANKS; i++) {
 
182
        if ((addr >= board_info.bar_start[i])&&((board_info.bar_start[i] + board_info.bar_length[i]) >= (addr + size))) return i;
 
183
    }
 
184
        
 
185
    return -1;
 
186
}
 
187
 
 
188
void *DetectAddress(int handle, int *bar, unsigned long *addr, int size) {
 
189
    if (*bar < 0) {
 
190
        *bar = DetectBar(handle, *addr, size);
 
191
        if (*bar < 0) Error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
 
192
    } else {
 
193
        GetBoardInfo(handle);
 
194
        
 
195
        if ((*addr < board_info.bar_start[*bar])||((board_info.bar_start[*bar] + board_info.bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
 
196
            if ((board_info.bar_length[*bar]) >= (((uintptr_t)*addr) + size)) 
 
197
                *addr += board_info.bar_start[*bar];
 
198
            else
 
199
                Error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info.bar_start[*bar], board_info.bar_length[*bar]);
 
200
        }
 
201
    }
 
202
    
 
203
    *addr -= board_info.bar_start[*bar];
 
204
    *addr += board_info.bar_start[*bar] & page_mask;
 
205
}
 
206
 
 
207
 
 
208
#ifdef FILE_IO
 
209
int file_io_handle;
 
210
#endif /* FILE_IO */
 
211
 
 
212
void *MapBar(int handle, int bar) {
 
213
    void *res;
 
214
    int ret; 
 
215
 
 
216
    GetBoardInfo(handle);
 
217
    
 
218
    ret = ioctl( handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
 
219
    if (ret) Error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
 
220
 
 
221
    ret = ioctl( handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
 
222
    if (ret) Error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
 
223
 
 
224
#ifdef FILE_IO
 
225
    file_io_handle = open("/root/drivers/pciDriver/data", O_RDWR);
 
226
    res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, file_io_handle, 0 );
 
227
#else
 
228
    res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, handle, 0 );
 
229
#endif
 
230
    if ((!res)||(res == MAP_FAILED)) Error("Failed to mmap data bank %i", bar);
 
231
 
 
232
    
 
233
    return res;
 
234
}
 
235
 
 
236
void UnmapBar(int handle, int bar, void *data) {
 
237
    munmap(data, board_info.bar_length[bar]);
 
238
#ifdef FILE_IO
 
239
    close(file_io_handle);
 
240
#endif
 
241
}
 
242
 
 
243
 
 
244
 
 
245
int Read(void *buf, int handle, int bar, unsigned long addr, int size) {
 
246
    int i;
 
247
    void *data;
 
248
    unsigned int offset;
 
249
    char local_buf[size];
 
250
    
 
251
 
 
252
 
 
253
    DetectAddress(handle, &bar, &addr, size);
 
254
    data = MapBar(handle, bar);
 
255
 
 
256
/*
 
257
    for (i = 0; i < size/4; i++)  {
 
258
        ((uint32_t*)((char*)data+addr))[i] = 0x100 * i + 1;
 
259
    }
 
260
*/
 
261
 
 
262
    memcpy0(buf, data + addr, size);
 
263
    
 
264
    UnmapBar(handle, bar, data);    
 
265
}
 
266
 
 
267
int Write(void *buf, int handle, int bar, unsigned long addr, int size) {
 
268
    int i;
 
269
    void *data;
 
270
    unsigned int offset;
 
271
    char local_buf[size];
 
272
    
 
273
 
 
274
    DetectAddress(handle, &bar, &addr, size);
 
275
    data = MapBar(handle, bar);
 
276
 
 
277
    memcpy0(data + addr, buf, size);
 
278
    
 
279
    UnmapBar(handle, bar, data);    
 
280
}
 
281
 
 
282
 
 
283
int Benchmark(int handle, int bar) {
 
284
    int i;
 
285
    void *data, *buf, *check;
 
286
    struct timeval start, end;
 
287
    unsigned long time;
 
288
    unsigned int size, max_size;
 
289
    
 
290
    GetBoardInfo(handle);
 
291
                
 
292
    if (bar < 0) {
 
293
        for (i = 0; i < MAX_BANKS; i++) {
 
294
            if (board_info.bar_length[i] > 0) {
 
295
                bar = i;
 
296
                break;
 
297
            }
 
298
        }
 
299
        
 
300
        if (bar < 0) Error("Data banks are not available");
 
301
    }
 
302
    
 
303
 
 
304
    max_size = board_info.bar_length[bar];
 
305
    
 
306
    posix_memalign( (void**)&buf, 256, max_size );
 
307
    posix_memalign( (void**)&check, 256, max_size );
 
308
    if ((!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", max_size);
 
309
 
 
310
    printf("Transfer time:\n");    
 
311
    data = MapBar(handle, bar);
 
312
    
 
313
    for (size = 4 ; size < max_size; size *= 8) {
 
314
        gettimeofday(&start,NULL);
 
315
        for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
 
316
            memcpy0(buf, data, size);
 
317
        }
 
318
        gettimeofday(&end,NULL);
 
319
 
 
320
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
 
321
        printf("%8i bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024 * 1024));
 
322
        
 
323
        fflush(0);
 
324
 
 
325
        gettimeofday(&start,NULL);
 
326
        for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
 
327
            memcpy0(data, buf, size);
 
328
        }
 
329
        gettimeofday(&end,NULL);
 
330
 
 
331
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
 
332
        printf(", write: %8.2lf MB/s\n", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024 * 1024));
 
333
    }
 
334
    
 
335
    UnmapBar(handle, bar, data);
 
336
 
 
337
    printf("\n\nOpen-Transfer-Close time: \n");
 
338
    
 
339
    for (size = 4 ; size < max_size; size *= 8) {
 
340
        gettimeofday(&start,NULL);
 
341
        for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
 
342
            Read(buf, handle, bar, 0, size);
 
343
        }
 
344
        gettimeofday(&end,NULL);
 
345
 
 
346
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
 
347
        printf("%8i bytes - read: %8.2lf MB/s", size, 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024 * 1024));
 
348
        
 
349
        fflush(0);
 
350
 
 
351
        gettimeofday(&start,NULL);
 
352
        for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
 
353
            Write(buf, handle, bar, 0, size);
 
354
        }
 
355
        gettimeofday(&end,NULL);
 
356
 
 
357
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
 
358
        printf(", write: %8.2lf MB/s", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024 * 1024));
 
359
 
 
360
        gettimeofday(&start,NULL);
 
361
        for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
 
362
            Write(buf, handle, bar, 0, size);
 
363
            Read(check, handle, bar, 0, size);
 
364
            memcmp(buf, check, size);
 
365
        }
 
366
        gettimeofday(&end,NULL);
 
367
 
 
368
        time = (end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec);
 
369
        printf(", write-verify: %8.2lf MB/s\n", 1000000. * size * BENCHMARK_ITERATIONS / (time * 1024 * 1024));
 
370
    }
 
371
    
 
372
    printf("\n\n");
 
373
 
 
374
    free(check);
 
375
    free(buf);
 
376
}
 
377
 
 
378
int ReadData(int handle, int bar, unsigned long addr, int n, int access) {
 
379
    void *buf;
 
380
    int i;
 
381
    int size = n * abs(access);
 
382
    int block_width, blocks_per_line;
 
383
    int numbers_per_block, numbers_per_line; 
 
384
    
 
385
    numbers_per_block = BLOCK_SIZE / access;
 
386
 
 
387
    block_width = numbers_per_block * ((access * 2) +  SEPARATOR_WIDTH);
 
388
    blocks_per_line = (LINE_WIDTH - 10) / (block_width +  BLOCK_SEPARATOR_WIDTH);
 
389
    if ((blocks_per_line > 1)&&(blocks_per_line % 2)) --blocks_per_line;
 
390
    numbers_per_line = blocks_per_line * numbers_per_block;
 
391
 
 
392
//    buf = alloca(size);
 
393
    posix_memalign( (void**)&buf, 256, size );
 
394
 
 
395
    if (!buf) Error("Allocation of %i bytes of memory have failed", size);
 
396
    
 
397
    Read(buf, handle, bar, addr, size);
 
398
 
 
399
    for (i = 0; i < n; i++) {
 
400
        if ((i)&&(i%numbers_per_line == 0)) printf("\n");
 
401
        else if ((i)&&(i%numbers_per_block == 0)) printf("%*s", BLOCK_SEPARATOR_WIDTH, "");
 
402
 
 
403
        if (i%numbers_per_line == 0) printf("%8lx: ", addr + i * abs(access));
 
404
 
 
405
        switch (access) {
 
406
            case 1: printf("% *hhx", access * 2 +  SEPARATOR_WIDTH, ((uint8_t*)buf)[i]); break;
 
407
            case 2: printf("% *hx", access * 2 +  SEPARATOR_WIDTH, ((uint16_t*)buf)[i]); break;
 
408
            case 4: printf("% *x", access * 2 +  SEPARATOR_WIDTH, ((uint32_t*)buf)[i]); break;
 
409
            case 8: printf("% *lx", access * 2 +  SEPARATOR_WIDTH, ((uint64_t*)buf)[i]); break;
 
410
        }
 
411
    }
 
412
    printf("\n\n");
 
413
 
 
414
    
 
415
    free(buf);
 
416
}
 
417
 
 
418
int WriteData(int handle, int bar, unsigned long addr, int n, int access, char ** data) {
 
419
    void *buf, *check;
 
420
    int res, i;
 
421
    int size = n * abs(access);
 
422
    
 
423
    posix_memalign( (void**)&buf, 256, size );
 
424
    posix_memalign( (void**)&check, 256, size );
 
425
    if ((!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
 
426
 
 
427
    for (i = 0; i < n; i++) {
 
428
        switch (access) {
 
429
            case 1: res = sscanf(data[i], "%hhx", ((uint8_t*)buf)+i); break;
 
430
            case 2: res = sscanf(data[i], "%hx", ((uint16_t*)buf)+i); break;
 
431
            case 4: res = sscanf(data[i], "%x", ((uint32_t*)buf)+i); break;
 
432
            case 8: res = sscanf(data[i], "%lx", ((uint64_t*)buf)+i); break;
 
433
        }
 
434
        
 
435
        if (res != 1) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
 
436
    }
 
437
 
 
438
    Write(buf, handle, bar, addr, size);
 
439
//    ReadData(handle, bar, addr, n, access);
 
440
    Read(check, handle, bar, addr, size);
 
441
    
 
442
    if (memcmp(buf, check, size)) Error("Write failed, the data written and read differ");
 
443
 
 
444
    free(check);
 
445
    free(buf);
 
446
}
 
447
 
 
448
 
 
449
 
 
450
int main(int argc, char **argv) {
 
451
    unsigned char c;
 
452
 
 
453
    MODE mode = MODE_INVALID;
 
454
    const char *fpga_device = DEFAULT_FPGA_DEVICE;
 
455
    int bar = -1;
 
456
    const char *addr = NULL;
 
457
    unsigned long start = -1;
 
458
    int size = 1;
 
459
    int access = 4;
 
460
    int skip = 0;
 
461
 
 
462
    int handle;
 
463
    
 
464
    while ((c = getopt_long(argc, argv, "hilpr::w::d:b:a:s:", long_options, NULL)) != (unsigned char)-1) {
 
465
        extern int optind;
 
466
        switch (c) {
 
467
            case OPT_HELP:
 
468
                Usage(argc, argv, NULL);
 
469
            break;
 
470
            case OPT_INFO:
 
471
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
 
472
 
 
473
                mode = MODE_INFO;
 
474
            break;
 
475
            case OPT_LIST:
 
476
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
 
477
 
 
478
                mode = MODE_LIST;
 
479
            break;
 
480
            case OPT_BENCHMARK:
 
481
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
 
482
 
 
483
                mode = MODE_BENCHMARK;
 
484
            break;
 
485
            case OPT_READ:
 
486
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
 
487
                
 
488
                mode = MODE_READ;
 
489
                if (optarg) addr = optarg;
 
490
                else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
 
491
            break;
 
492
            case OPT_WRITE:
 
493
                if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
 
494
 
 
495
                mode = MODE_WRITE;
 
496
                if (optarg) addr = optarg;
 
497
                else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
 
498
            break;
 
499
            case OPT_DEVICE:
 
500
                fpga_device = optarg;
 
501
            break;
 
502
            case OPT_BAR:
 
503
                if ((sscanf(optarg,"%u", &bar) != 1)||(bar < 0)||(bar >= MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
 
504
            break;
 
505
            case OPT_ACCESS:
 
506
                if (sscanf(optarg, "%i", &access) != 1) access = 0;
 
507
                switch (access) {
 
508
                    case 8: access = 1; break;
 
509
                    case 16: access = 2; break;
 
510
                    case 32: access = 4; break;
 
511
                    case 64: access = 8; break;
 
512
                    default: Usage(argc, argv, "Invalid data width (%s) is specified", optarg);
 
513
                }       
 
514
            break;
 
515
            case OPT_SIZE:
 
516
                if (sscanf(optarg, "%u", &size) != 1)
 
517
                    Usage(argc, argv, "Invalid size is specified (%s)", optarg);
 
518
            break;
 
519
            default:
 
520
                Usage(argc, argv, "Unknown option (%s)", argv[optind]);
 
521
        }
 
522
    }
 
523
 
 
524
    if (mode == MODE_INVALID) {
 
525
        if (argc > 1) Usage(argc, argv, "Operation is not specified");
 
526
        else Usage(argc, argv, NULL);
 
527
    }
 
528
 
 
529
    if (addr) {
 
530
        if (sscanf(addr, "%lx", &start) != 1) Usage(argc, argv, "Invalid address (%s) is specified", addr);
 
531
    }
 
532
    
 
533
    switch (mode) {
 
534
     case MODE_WRITE:
 
535
        if ((argc - optind) != size) Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size);
 
536
     case MODE_READ:
 
537
        if (!addr) Usage(argc, argv, "The address is not specified");
 
538
     break;
 
539
     default:
 
540
        if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
 
541
    }
 
542
 
 
543
    handle = open(fpga_device, O_RDWR);
 
544
    if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device);
 
545
    
 
546
    switch (mode) {
 
547
     case MODE_INFO:
 
548
        Info(handle);
 
549
     break;
 
550
     case MODE_LIST:
 
551
        List(handle);
 
552
     break;
 
553
     case MODE_BENCHMARK:
 
554
        Benchmark(handle, bar);
 
555
     break;
 
556
     case MODE_READ:
 
557
        if (addr) {
 
558
            ReadData(handle, bar, start, size, access);
 
559
        } else {
 
560
            Error("Address to read is not specified");
 
561
        }
 
562
     break;
 
563
     case MODE_WRITE:
 
564
        WriteData(handle, bar, start, size, access, argv + optind);
 
565
     break;
 
566
    }
 
567
 
 
568
    close(handle);
 
569
}