/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to pcilib/bar.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-05-05 13:27:22 UTC
  • Revision ID: csa@suren.me-20150505132722-rz47ppxkx39x2koj
Split bar manipulation and fifo operations in stand-alone source and publish kmem and bar headers

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _BSD_SOURCE
 
2
#define _POSIX_C_SOURCE 200809L
 
3
 
 
4
#include <stdio.h>
 
5
#include <string.h>
 
6
#include <strings.h>
 
7
#include <stdlib.h>
 
8
#include <stdint.h>
 
9
#include <fcntl.h>
 
10
#include <unistd.h>
 
11
#include <sys/ioctl.h>
 
12
#include <sys/mman.h>
 
13
#include <arpa/inet.h>
 
14
#include <errno.h>
 
15
#include <assert.h>
 
16
 
 
17
#include "pcilib.h"
 
18
#include "pci.h"
 
19
#include "tools.h"
 
20
#include "error.h"
 
21
#include "model.h"
 
22
#include "plugin.h"
 
23
 
 
24
pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) {
 
25
    int n = 0;
 
26
    pcilib_bar_t i;
 
27
        
 
28
    const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
 
29
    if (!board_info) return PCILIB_BAR_INVALID;
 
30
                
 
31
    for (i = 0; i < PCILIB_MAX_BARS; i++) {
 
32
        if (board_info->bar_length[i] > 0) {
 
33
            if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i;
 
34
 
 
35
            if (n) n = -1;
 
36
            else n = i + 1;
 
37
        }
 
38
    }
 
39
 
 
40
    if (n > 0) return n - 1;
 
41
 
 
42
    return PCILIB_BAR_INVALID;
 
43
}
 
44
 
 
45
int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size) {
 
46
    const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
 
47
    if (!board_info) return PCILIB_ERROR_NOTFOUND;
 
48
    
 
49
    if (*bar == PCILIB_BAR_DETECT) {
 
50
        *bar = pcilib_detect_bar(ctx, *addr, size);
 
51
        if (*bar == PCILIB_BAR_INVALID) {
 
52
            pcilib_error("The requested data block at address 0x%x with size %zu does not belongs to any available memory bar", *addr, size);
 
53
            return PCILIB_ERROR_NOTFOUND;
 
54
        }
 
55
        if (*addr < board_info->bar_start[*bar]) 
 
56
            *addr += board_info->bar_start[*bar];
 
57
    } else {
 
58
        if ((*addr < board_info->bar_start[*bar])||((board_info->bar_start[*bar] + board_info->bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
 
59
            if ((board_info->bar_length[*bar]) >= (((uintptr_t)*addr) + size)) {
 
60
                *addr += board_info->bar_start[*bar];
 
61
            } else {
 
62
                pcilib_error("The requested data block at address 0x%x with size %zu does not belong the specified memory bar (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]);
 
63
                return PCILIB_ERROR_NOTFOUND;
 
64
            }
 
65
        }
 
66
    }
 
67
 
 
68
    *addr -= board_info->bar_start[*bar];
 
69
    *addr += board_info->bar_start[*bar] & ctx->page_mask;
 
70
 
 
71
    return 0;
 
72
}
 
73
 
 
74
void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) {
 
75
    void *res;
 
76
    int ret; 
 
77
 
 
78
    const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
 
79
    if (!board_info) return NULL;
 
80
    
 
81
    if (ctx->bar_space[bar]) return ctx->bar_space[bar];
 
82
    
 
83
    ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
 
84
    if (ret) {
 
85
        pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
 
86
        return NULL;
 
87
    }
 
88
 
 
89
    ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
 
90
    if (ret) {
 
91
        pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
 
92
        return NULL;
 
93
    }
 
94
 
 
95
#ifdef PCILIB_FILE_IO
 
96
    file_io_handle = open("/root/data", O_RDWR);
 
97
    res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->file_io_handle, 0 );
 
98
#else
 
99
    res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 );
 
100
#endif
 
101
    if ((!res)||(res == MAP_FAILED)) {
 
102
        pcilib_error("Failed to mmap data bank %i", bar);
 
103
        return NULL;
 
104
    }
 
105
 
 
106
    
 
107
    return res;
 
108
}
 
109
 
 
110
void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) {
 
111
    const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
 
112
    if (!board_info) return;
 
113
 
 
114
    if (ctx->bar_space[bar]) return;
 
115
    
 
116
    munmap(data, board_info->bar_length[bar]);
 
117
#ifdef PCILIB_FILE_IO
 
118
    close(ctx->file_io_handle);
 
119
#endif
 
120
}
 
121
 
 
122
int pcilib_map_register_space(pcilib_t *ctx) {
 
123
    int err;
 
124
    pcilib_register_bank_t i;
 
125
    
 
126
    if (!ctx->reg_bar_mapped)  {
 
127
        const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
128
        const pcilib_register_bank_description_t *banks = model_info->banks;
 
129
    
 
130
        for (i = 0; ((banks)&&(banks[i].access)); i++) {
 
131
//          uint32_t buf[2];
 
132
            void *reg_space;
 
133
            pcilib_bar_t bar = banks[i].bar;
 
134
 
 
135
            if (bar == PCILIB_BAR_DETECT) {
 
136
                uintptr_t addr = banks[0].read_addr;
 
137
            
 
138
                err = pcilib_detect_address(ctx, &bar, &addr, 1);
 
139
                if (err) return err;
 
140
                
 
141
                if (!ctx->bar_space[bar]) {
 
142
                    reg_space = pcilib_map_bar(ctx, bar);
 
143
//                  pcilib_memcpy(&buf, reg_space, 8);
 
144
            
 
145
                    if (reg_space) {
 
146
                        ctx->bar_space[bar] = reg_space;
 
147
                    } else {
 
148
                        return PCILIB_ERROR_FAILED;
 
149
                    }
 
150
                }
 
151
            } else if (!ctx->bar_space[bar]) {
 
152
                reg_space = pcilib_map_bar(ctx, bar);
 
153
                if (reg_space) {
 
154
                    ctx->bar_space[bar] = reg_space;
 
155
                } else {
 
156
                    return PCILIB_ERROR_FAILED;
 
157
                }
 
158
//              pcilib_memcpy(&buf, reg_space, 8);
 
159
                
 
160
            }
 
161
            
 
162
            if (!i) ctx->reg_bar = bar;
 
163
        }
 
164
        
 
165
        
 
166
        ctx->reg_bar_mapped = 1;
 
167
    }
 
168
    
 
169
    return 0;
 
170
}
 
171
 
 
172
int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
 
173
    void *data;
 
174
 
 
175
    pcilib_detect_address(ctx, &bar, &addr, size);
 
176
    data = pcilib_map_bar(ctx, bar);
 
177
 
 
178
    pcilib_memcpy(buf, data + addr, size);
 
179
 
 
180
    pcilib_unmap_bar(ctx, bar, data);
 
181
 
 
182
    return 0;
 
183
}
 
184
 
 
185
int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
 
186
    void *data;
 
187
 
 
188
    pcilib_detect_address(ctx, &bar, &addr, size);
 
189
    data = pcilib_map_bar(ctx, bar);
 
190
 
 
191
    pcilib_memcpy(data + addr, buf, size);
 
192
 
 
193
    pcilib_unmap_bar(ctx, bar, data);
 
194
 
 
195
    return 0;
 
196
}
 
197