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 |
}
|