/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
315 by Suren A. Chilingaryan
Support properties of arbitrary type
1
#define _GNU_SOURCE
2
#include <stdio.h>
3
#include <string.h>
4
#include <strings.h>
5
#include <stdlib.h>
6
7
#include <views/register.h>
8
9
#include "pci.h"
10
#include "bank.h"
11
#include "view.h"
12
#include "register.h"
13
#include "property.h"
14
15
#include "tools.h"
16
#include "error.h"
17
321 by Suren A. Chilingaryan
Support computed (property-based) registers
18
19
int pcilib_add_registers_from_properties(pcilib_t *ctx, size_t n, pcilib_view_context_t* const *view_ctx, pcilib_view_description_t* const *v) {
324 by Suren A. Chilingaryan
Documentation update
20
    int err;
21
    
321 by Suren A. Chilingaryan
Support computed (property-based) registers
22
    pcilib_view_t i;
23
    pcilib_register_t pos = 0;
24
    pcilib_register_description_t regs[n];
25
324 by Suren A. Chilingaryan
Documentation update
26
    int access;
27
    pcilib_register_bank_t bank;
28
29
    bank = pcilib_find_register_bank_by_addr(ctx, pcilib_property_register_bank.addr);
30
    if (bank == PCILIB_REGISTER_BANK_INVALID) {
31
        err = pcilib_add_register_banks(ctx, 0, 1, &pcilib_property_register_bank, &bank);
32
        if (err) {
33
            pcilib_error("Error (%i) adding register bank (%s)", err, pcilib_property_register_bank.name);
34
            return err;
35
        }
36
    }
325 by Suren A. Chilingaryan
Fix access to the property-based registers
37
38
    access = ctx->banks[bank].access / 8;
39
321 by Suren A. Chilingaryan
Support computed (property-based) registers
40
    for (i = 0; i < n; i++) {
41
        if ((v[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) continue;
42
43
        regs[pos++] = (pcilib_register_description_t){
324 by Suren A. Chilingaryan
Documentation update
44
            .addr = view_ctx[i]->view * access,
321 by Suren A. Chilingaryan
Support computed (property-based) registers
45
            .bits = 8 * sizeof(pcilib_register_value_t),
46
            .mode = v[i]->mode,
47
            .type = PCILIB_REGISTER_PROPERTY,
48
            .bank = PCILIB_REGISTER_BANK_PROPERTY,
49
            .name = (v[i]->regname?v[i]->regname:v[i]->name),
50
            .description = v[i]->description
51
        };
52
    }
53
54
    if (pos)
55
        return pcilib_add_registers(ctx, 0, pos, regs, NULL);
56
57
    return 0;
58
}
59
60
61
int pcilib_add_properties_from_registers(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers) {
315 by Suren A. Chilingaryan
Support properties of arbitrary type
62
    int err;
63
64
    pcilib_register_t i;
65
    pcilib_view_t cur_view = ctx->num_views;
66
67
    if (!n) 
68
        return PCILIB_ERROR_INVALID_ARGUMENT;
69
70
71
    for (i = 0; i < n; i++) {
321 by Suren A. Chilingaryan
Support computed (property-based) registers
72
        char *view_name;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
73
        pcilib_access_mode_t mode = 0;
74
329 by Suren A. Chilingaryan
IPEDMA Update
75
        pcilib_register_view_description_t v = {{0}};
315 by Suren A. Chilingaryan
Support properties of arbitrary type
76
        pcilib_register_bank_description_t *b = &ctx->banks[banks[i]];
77
321 by Suren A. Chilingaryan
Support computed (property-based) registers
78
        if (registers[i].type == PCILIB_REGISTER_PROPERTY) continue;
79
80
        view_name = malloc(strlen(registers[i].name) + strlen(b->name) + 13);
315 by Suren A. Chilingaryan
Support properties of arbitrary type
81
        if (!view_name) {
82
            pcilib_clean_views(ctx, cur_view);
83
            return PCILIB_ERROR_MEMORY;
84
        }
85
86
        sprintf(view_name, "/registers/%s/%s", b->name, registers[i].name);
87
88
        if ((registers[i].views)&&(registers[i].views[0].view)) {
89
            pcilib_view_t view = pcilib_find_view_by_name(ctx, registers[i].views[0].view);
90
            if (view == PCILIB_VIEW_INVALID) return PCILIB_ERROR_NOTFOUND;
91
92
            memcpy(&v, ctx->views[view], sizeof(pcilib_view_description_t));
93
            v.view = registers[i].views[0].name;
94
95
            if (ctx->views[view]->api->read_from_reg) mode |= PCILIB_ACCESS_R;
96
            if (ctx->views[view]->api->write_to_reg) mode |= PCILIB_ACCESS_W;
97
            mode &= ctx->views[view]->mode;
98
        } else {
99
            v.base.type = PCILIB_TYPE_LONG;
100
            mode = PCILIB_ACCESS_RW;
101
        }
102
103
        v.base.api = &pcilib_register_view_api;
104
        v.base.name = view_name;
105
        v.base.description = registers[i].description;
106
        v.base.mode = registers[i].mode&mode;
316 by Suren A. Chilingaryan
Support XML properties
107
        v.base.flags |= PCILIB_VIEW_FLAG_PROPERTY;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
108
        v.reg = registers[i].name;
109
        v.bank = b->name;
110
111
        err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&v);
112
        if (err) {
113
            free(view_name);
114
            pcilib_clean_views(ctx, cur_view);
115
            return err;
116
        }
328 by Suren A. Chilingaryan
Fix segmentation crash due to uninitialized variable
117
316 by Suren A. Chilingaryan
Support XML properties
118
/*
119
        pcilib_view_context_t *view_ctx = pcilib_find_view_context_by_name(ctx, v.base.name);
315 by Suren A. Chilingaryan
Support properties of arbitrary type
120
        view_ctx->flags |= PCILIB_VIEW_FLAG_PROPERTY;
316 by Suren A. Chilingaryan
Support XML properties
121
*/
315 by Suren A. Chilingaryan
Support properties of arbitrary type
122
    }
123
124
    return 0;
125
}
126
127
pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *branch, pcilib_list_flags_t flags) {
128
    int err = 0;
129
130
    size_t pos = 0;
131
    size_t name_offset = 0;
132
    pcilib_view_context_t *view_ctx, *view_tmp;
133
    pcilib_property_info_t *info = (pcilib_property_info_t*)malloc((ctx->num_views + 1) * sizeof(pcilib_property_info_t));
134
135
    struct dir_hash_s {
136
        char *name;
137
        UT_hash_handle hh;
138
    } *dir_hash = NULL, *dir, *dir_tmp;
139
140
    if (branch) {
141
        name_offset = strlen(branch);
142
        if (branch[name_offset - 1] != '/') name_offset++;
143
    }
144
145
        // Find all folders
146
    HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
147
        const pcilib_view_description_t *v = ctx->views[view_ctx->view];
148
        const char *subname = v->name + name_offset;
149
        const char *suffix;
150
316 by Suren A. Chilingaryan
Support XML properties
151
        if (!(v->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
152
        if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
153
154
        suffix = strchr(subname, '/');
155
        if (suffix) {
156
            char *name = strndup(v->name, suffix - v->name);
157
            if (!name) {
158
                err = PCILIB_ERROR_MEMORY;
159
                break;
160
            }
161
162
            HASH_FIND_STR(dir_hash, name + name_offset, dir);
163
            if (dir) {
164
                free(name);
165
                continue;
166
            }
167
168
            dir = (struct dir_hash_s*)malloc(sizeof(struct dir_hash_s));
169
            if (!dir) {
170
                err = PCILIB_ERROR_MEMORY;
171
                break;
172
            }
173
174
            dir->name = name;
175
176
            HASH_ADD_KEYPTR(hh, dir_hash, dir->name + name_offset, strlen(dir->name + name_offset), dir);
177
        }
178
    }
179
180
    HASH_ITER(hh, ctx->view_hash, view_ctx, view_tmp) {
181
        const pcilib_view_description_t *v = ctx->views[view_ctx->view];
182
        const char *subname = v->name + name_offset;
183
316 by Suren A. Chilingaryan
Support XML properties
184
        if (!(v->flags&PCILIB_VIEW_FLAG_PROPERTY)) continue;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
185
        if ((branch)&&(strncasecmp(branch, v->name, strlen(branch)))) continue;
186
187
        if (!strchr(subname, '/')) {
188
            pcilib_view_context_t *found_view;
189
190
            char *path = strdup(v->name);
191
            if (!path) {
192
                err = PCILIB_ERROR_MEMORY;
193
                break;
194
            }
195
            char *name = strrchr(v->name, '/');
196
            if (name) name++;
197
            else name = path;
198
199
            HASH_FIND_STR(dir_hash, name, found_view);
200
201
            info[pos++] = (pcilib_property_info_t) {
202
                .name = name,
203
                .path = path,
204
                .description = v->description,
205
                .type = v->type,
206
                .mode = v->mode,
207
                .unit = v->unit,
208
                .flags = (found_view?PCILIB_LIST_FLAG_CHILDS:0)
209
            };
210
211
            if (found_view) HASH_DEL(dir_hash, found_view);
212
        }
213
    }
214
215
    HASH_ITER(hh, dir_hash, dir, dir_tmp) {
216
        char *name = strrchr(dir->name, '/');
217
        if (name) name++;
218
        else name = dir->name;
219
220
        info[pos++] = (pcilib_property_info_t) {
221
            .name = name,
222
            .path = dir->name,
223
            .type = PCILIB_TYPE_INVALID,
224
            .flags = PCILIB_LIST_FLAG_CHILDS
225
        };
226
    }
227
346.1.13 by Vasilii Chernov
Fix memory leaks
228
    HASH_ITER(hh, dir_hash, dir, dir_tmp) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
229
	HASH_DEL(dir_hash, dir);
230
	free(dir);
346.1.13 by Vasilii Chernov
Fix memory leaks
231
    }
315 by Suren A. Chilingaryan
Support properties of arbitrary type
232
    HASH_CLEAR(hh, dir_hash);
233
234
    memset(&info[pos], 0, sizeof(pcilib_property_info_t));
235
236
    if (err) {
237
        pcilib_free_property_info(ctx, info);
238
        return NULL;
239
    }
240
241
    return info;
242
}
243
244
void pcilib_free_property_info(pcilib_t *ctx, pcilib_property_info_t *info) {
245
    int i;
246
247
    for (i = 0; info[i].path; i++)
248
        free((char*)info[i].path);
249
    free(info);
250
}
251
252
int pcilib_get_property(pcilib_t *ctx, const char *prop, pcilib_value_t *val) {
253
    return pcilib_read_register_view(ctx, NULL, NULL, prop, val);
254
}
255
256
int pcilib_set_property(pcilib_t *ctx, const char *prop, const pcilib_value_t *val) {
257
    return pcilib_write_register_view(ctx, NULL, NULL, prop, val);
258
}
318 by Suren A. Chilingaryan
Support reading/writting register views by id
259
260
int pcilib_get_property_attr(pcilib_t *ctx, const char *prop, const char *attr, pcilib_value_t *val) {
261
    pcilib_view_context_t *view_ctx;
262
263
    view_ctx = pcilib_find_view_context_by_name(ctx, prop);
264
    if (!view_ctx) {
265
        pcilib_error("The specified property (%s) is not found", prop);
266
        return PCILIB_ERROR_NOTFOUND;
267
    }
268
324 by Suren A. Chilingaryan
Documentation update
269
    if (!view_ctx->xml) return PCILIB_ERROR_NOTFOUND;
318 by Suren A. Chilingaryan
Support reading/writting register views by id
270
271
    return pcilib_get_xml_attr(ctx, view_ctx->xml, attr, val);
272
}