/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 pcilib/bar.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-10-22 13:57:59 UTC
  • Revision ID: csa@suren.me-20151022135759-nqs5wowy38tvbw09
Documentation update

Show diffs side-by-side

added added

removed removed

Lines of Context:
130
130
#endif
131
131
}
132
132
 
 
133
char *pcilib_resolve_bar_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr) {
 
134
    if (bar == PCILIB_BAR_DETECT) {    
 
135
        bar = pcilib_detect_bar(ctx, addr, 1);
 
136
        if (bar != PCILIB_BAR_INVALID) {
 
137
            size_t offset = addr - ctx->board_info.bar_start[bar];
 
138
            if ((offset < ctx->board_info.bar_length[bar])&&(ctx->bar_space[bar])) {
 
139
                if (!ctx->bar_space[bar]) {
 
140
                    if (!pcilib_map_bar(ctx, bar)) {
 
141
                        pcilib_error("Failed to map the requested bar (%i)", bar);
 
142
                        return NULL;
 
143
                    }
 
144
                }
 
145
                return ctx->bar_space[bar] + offset + (ctx->board_info.bar_start[bar] & ctx->page_mask);
 
146
            }
 
147
        }
 
148
    } else {
 
149
        if (!ctx->bar_space[bar]) {
 
150
            if (!pcilib_map_bar(ctx, bar)) {
 
151
                pcilib_error("Failed to map the requested bar (%i)", bar);
 
152
                return NULL;
 
153
            }
 
154
        }
 
155
        
 
156
        if (addr < ctx->board_info.bar_length[bar]) {
 
157
            return ctx->bar_space[bar] + addr + (ctx->board_info.bar_start[bar] & ctx->page_mask);
 
158
        }
 
159
        
 
160
        if ((addr >= ctx->board_info.bar_start[bar])&&(addr < (ctx->board_info.bar_start[bar] + ctx->board_info.bar_length[ctx->reg_bar]))) {
 
161
            return ctx->bar_space[bar] + (addr - ctx->board_info.bar_start[bar]) + (ctx->board_info.bar_start[bar] & ctx->page_mask);
 
162
        }
 
163
    }
 
164
 
 
165
    return NULL;
 
166
}
 
167
 
133
168
int pcilib_map_register_space(pcilib_t *ctx) {
134
169
    int err;
135
170
    pcilib_register_bank_t i;
183
218
    return 0;
184
219
}
185
220
 
 
221
char *pcilib_resolve_register_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr) {
 
222
    if (bar == PCILIB_BAR_DETECT) {
 
223
            // First checking the default register bar
 
224
        size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];
 
225
        if ((addr > ctx->board_info.bar_start[ctx->reg_bar])&&(offset < ctx->board_info.bar_length[ctx->reg_bar])) {
 
226
            return pcilib_resolve_bar_address(ctx, ctx->reg_bar, addr - ctx->board_info.bar_start[ctx->reg_bar]);
 
227
        }
 
228
    }
 
229
        // Otherwise trying to detect
 
230
    return pcilib_resolve_bar_address(ctx, bar, addr);
 
231
}
 
232
 
 
233
int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) {
 
234
    int err;
 
235
    pcilib_bar_t i;
 
236
    
 
237
    if (!ctx->data_bar_mapped) {
 
238
        const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
 
239
        if (!board_info) return PCILIB_ERROR_FAILED;
 
240
 
 
241
        err = pcilib_map_register_space(ctx);
 
242
        if (err) {
 
243
            pcilib_error("Error mapping register space");
 
244
            return err;
 
245
        }
 
246
        
 
247
        int data_bar = -1;
 
248
        
 
249
        for (i = 0; i < PCILIB_MAX_BARS; i++) {
 
250
            if ((ctx->bar_space[i])||(!board_info->bar_length[i])) continue;
 
251
            
 
252
            if (addr) {
 
253
                if (board_info->bar_start[i] == addr) {
 
254
                    data_bar = i;
 
255
                    break;
 
256
                }
 
257
            } else {
 
258
                if (data_bar >= 0) {
 
259
                    data_bar = -1;
 
260
                    break;
 
261
                }
 
262
                
 
263
                data_bar = i;
 
264
            }
 
265
        }
 
266
            
 
267
 
 
268
        if (data_bar < 0) {
 
269
            if (addr) pcilib_error("Unable to find the specified data space (%lx)", addr);
 
270
            else pcilib_error("Unable to find the data space");
 
271
            return PCILIB_ERROR_NOTFOUND;
 
272
        }
 
273
        
 
274
        ctx->data_bar = data_bar;
 
275
        
 
276
        if (!ctx->bar_space[data_bar]) {
 
277
            char *data_space = pcilib_map_bar(ctx, data_bar);
 
278
            if (data_space) ctx->bar_space[data_bar] = data_space;
 
279
            else {
 
280
                pcilib_error("Unable to map the data space");
 
281
                return PCILIB_ERROR_FAILED;
 
282
            }
 
283
        }
 
284
        
 
285
        ctx->data_bar_mapped = 0;
 
286
    }
 
287
    
 
288
    return 0;
 
289
}
 
290
        
 
291
char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) {
 
292
    int err;
 
293
    
 
294
    err = pcilib_map_data_space(ctx, addr);
 
295
    if (err) {
 
296
        pcilib_error("Failed to map the specified address space (%lx)", addr);
 
297
        return NULL;
 
298
    }
 
299
    
 
300
    if (size) *size = ctx->board_info.bar_length[ctx->data_bar];
 
301
    
 
302
    return ctx->bar_space[ctx->data_bar] + (ctx->board_info.bar_start[ctx->data_bar] & ctx->page_mask);
 
303
}
 
304
 
 
305
 
186
306
int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
187
307
    void *data;
188
308