bzr branch
http://suren.me/webbzr/alps/pcitool
236
by Suren A. Chilingaryan
Big redign of model structures |
1 |
#include <stdio.h> |
2 |
#include <string.h> |
|
3 |
#include <strings.h> |
|
4 |
#include <stdlib.h> |
|
5 |
#include <stdint.h> |
|
6 |
#include <stdarg.h> |
|
7 |
#include <fcntl.h> |
|
8 |
#include <unistd.h> |
|
9 |
#include <sys/ioctl.h> |
|
10 |
#include <sys/mman.h> |
|
11 |
#include <arpa/inet.h> |
|
12 |
#include <errno.h> |
|
13 |
#include <assert.h> |
|
14 |
||
15 |
#include "pci.h" |
|
16 |
||
17 |
#include "tools.h" |
|
18 |
#include "error.h" |
|
19 |
||
20 |
int pcilib_init_register_banks(pcilib_t *ctx) { |
|
21 |
int err; |
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
22 |
size_t start = ctx->num_banks_init; |
236
by Suren A. Chilingaryan
Big redign of model structures |
23 |
|
24 |
err = pcilib_map_register_space(ctx); |
|
25 |
if (err) return err; |
|
26 |
||
27 |
for (; ctx->num_banks_init < ctx->num_banks; ctx->num_banks_init++) { |
|
28 |
pcilib_register_bank_context_t *bank_ctx; |
|
29 |
pcilib_register_protocol_t protocol; |
|
30 |
const pcilib_register_protocol_api_description_t *bapi; |
|
31 |
||
32 |
protocol = pcilib_find_register_protocol_by_addr(ctx, ctx->banks[ctx->num_banks_init].protocol); |
|
33 |
if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) { |
|
34 |
const char *name = ctx->banks[ctx->num_banks_init].name; |
|
35 |
if (!name) name = "unnamed"; |
|
36 |
pcilib_error("Invalid register protocol address (%u) is specified for bank %i (%s)", ctx->banks[ctx->num_banks_init].protocol, ctx->banks[ctx->num_banks_init].addr, name); |
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
37 |
pcilib_free_register_banks(ctx, start); |
236
by Suren A. Chilingaryan
Big redign of model structures |
38 |
return PCILIB_ERROR_INVALID_BANK; |
39 |
}
|
|
40 |
||
41 |
bapi = ctx->protocols[protocol].api; |
|
42 |
||
240
by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines |
43 |
if (bapi->init) { |
44 |
const char *model = ctx->protocols[protocol].model; |
|
45 |
if (!model) model = ctx->model; |
|
46 |
||
47 |
bank_ctx = bapi->init(ctx, ctx->num_banks_init, model, ctx->protocols[protocol].args); |
|
48 |
} else |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
49 |
bank_ctx = (pcilib_register_bank_context_t*)malloc(sizeof(pcilib_register_bank_context_t)); |
50 |
||
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
51 |
if (!bank_ctx) { |
52 |
pcilib_free_register_banks(ctx, start); |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
53 |
return PCILIB_ERROR_FAILED; |
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
54 |
}
|
236
by Suren A. Chilingaryan
Big redign of model structures |
55 |
|
56 |
bank_ctx->bank = ctx->banks + ctx->num_banks_init; |
|
57 |
bank_ctx->api = bapi; |
|
303
by Suren A. Chilingaryan
Initial integration of XML support |
58 |
bank_ctx->xml = ctx->xml.bank_nodes[ctx->num_banks_init]; |
236
by Suren A. Chilingaryan
Big redign of model structures |
59 |
ctx->bank_ctx[ctx->num_banks_init] = bank_ctx; |
60 |
}
|
|
61 |
||
62 |
return 0; |
|
63 |
}
|
|
64 |
||
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
65 |
void pcilib_free_register_banks(pcilib_t *ctx, pcilib_register_bank_t start) { |
236
by Suren A. Chilingaryan
Big redign of model structures |
66 |
size_t i; |
67 |
||
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
68 |
for (i = start; i < ctx->num_banks_init; i++) { |
236
by Suren A. Chilingaryan
Big redign of model structures |
69 |
const pcilib_register_protocol_api_description_t *bapi = ctx->bank_ctx[i]->api; |
70 |
||
71 |
if (ctx->bank_ctx[i]) { |
|
72 |
if (bapi->free) |
|
275
by Suren A. Chilingaryan
Integration of software registers |
73 |
bapi->free(ctx, ctx->bank_ctx[i]); |
236
by Suren A. Chilingaryan
Big redign of model structures |
74 |
else
|
75 |
free(ctx->bank_ctx[i]); |
|
76 |
||
77 |
ctx->bank_ctx[i] = NULL; |
|
78 |
}
|
|
79 |
}
|
|
80 |
||
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
81 |
ctx->num_banks_init = start; |
236
by Suren A. Chilingaryan
Big redign of model structures |
82 |
}
|
83 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
84 |
int pcilib_add_register_banks(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_bank_description_t *banks, pcilib_register_bank_t *ids) { |
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
85 |
int err; |
303
by Suren A. Chilingaryan
Initial integration of XML support |
86 |
size_t i; |
87 |
pcilib_register_bank_t bank; |
|
88 |
size_t dyn_banks = ctx->dyn_banks; |
|
89 |
size_t num_banks = ctx->num_banks; |
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
90 |
size_t cur_banks = num_banks; |
236
by Suren A. Chilingaryan
Big redign of model structures |
91 |
|
92 |
if (!n) { |
|
93 |
for (n = 0; banks[n].access; n++); |
|
94 |
}
|
|
95 |
||
96 |
if ((ctx->num_banks + n + 1) > PCILIB_MAX_REGISTER_BANKS) |
|
97 |
return PCILIB_ERROR_TOOBIG; |
|
303
by Suren A. Chilingaryan
Initial integration of XML support |
98 |
|
99 |
for (i = 0; i < n; i++) { |
|
100 |
// Try to find if the bank is already existing...
|
|
101 |
bank = pcilib_find_register_bank_by_name(ctx, banks[i].name); |
|
102 |
if ((bank == PCILIB_REGISTER_BANK_INVALID)&&(banks[i].addr != PCILIB_REGISTER_BANK_DYNAMIC)) |
|
103 |
bank = pcilib_find_register_bank_by_addr(ctx, banks[i].addr); |
|
104 |
||
105 |
if (bank == PCILIB_REGISTER_BANK_INVALID) { |
|
106 |
bank = num_banks++; |
|
107 |
} else if (flags&PCILIB_MODEL_MODIFICATION_FLAG_SKIP_EXISTING) { |
|
108 |
if (ids) ids[i] = bank; |
|
109 |
continue; |
|
110 |
} else if ((flags&PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE) == 0) { |
|
111 |
if (pcilib_find_register_bank_by_name(ctx, banks[i].name) == PCILIB_REGISTER_BANK_INVALID) |
|
112 |
pcilib_error("The bank %s is already existing and override flag is not set", banks[i].name); |
|
113 |
else
|
|
114 |
pcilib_error("The bank with address 0x%lx is already existing and override flag is not set", banks[i].addr); |
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
115 |
memset(ctx->banks + ctx->num_banks, 0, sizeof(pcilib_register_bank_description_t)); |
303
by Suren A. Chilingaryan
Initial integration of XML support |
116 |
return PCILIB_ERROR_EXIST; |
117 |
}
|
|
118 |
||
119 |
memcpy(ctx->banks + bank, banks + i, sizeof(pcilib_register_bank_description_t)); |
|
120 |
if (ids) ids[i] = bank; |
|
121 |
||
122 |
if (banks[i].addr == PCILIB_REGISTER_BANK_DYNAMIC) { |
|
123 |
ctx->banks[bank].addr = PCILIB_REGISTER_BANK_DYNAMIC + dyn_banks + 1; |
|
124 |
dyn_banks++; |
|
125 |
}
|
|
126 |
}
|
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
127 |
|
303
by Suren A. Chilingaryan
Initial integration of XML support |
128 |
ctx->num_banks = num_banks; |
236
by Suren A. Chilingaryan
Big redign of model structures |
129 |
|
130 |
// If banks are already initialized, we need to re-run the initialization code
|
|
131 |
if (ctx->reg_bar_mapped) { |
|
132 |
ctx->reg_bar_mapped = 0; |
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
133 |
err = pcilib_init_register_banks(ctx); |
134 |
if (err) { |
|
135 |
ctx->num_banks = cur_banks; |
|
136 |
memset(ctx->banks + ctx->num_banks, 0, sizeof(pcilib_register_bank_description_t)); |
|
137 |
return err; |
|
138 |
}
|
|
236
by Suren A. Chilingaryan
Big redign of model structures |
139 |
}
|
315
by Suren A. Chilingaryan
Support properties of arbitrary type |
140 |
|
141 |
ctx->dyn_banks = dyn_banks; |
|
142 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
143 |
return 0; |
144 |
}
|
|
145 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
146 |
int pcilib_add_register_protocols(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_protocol_description_t *protocols, pcilib_register_protocol_t *ids) { |
242
by Suren A. Chilingaryan
Initial support for event engines |
147 |
// DS: Override existing banks
|
148 |
||
149 |
if (!n) { |
|
150 |
for (n = 0; protocols[n].api; n++); |
|
151 |
}
|
|
152 |
||
153 |
if ((ctx->num_protocols + n + 1) > PCILIB_MAX_REGISTER_PROTOCOLS) |
|
154 |
return PCILIB_ERROR_TOOBIG; |
|
155 |
||
156 |
memcpy(ctx->protocols + ctx->num_protocols, protocols, n * sizeof(pcilib_register_protocol_description_t)); |
|
157 |
ctx->num_protocols += n; |
|
158 |
||
159 |
return 0; |
|
160 |
}
|
|
161 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
162 |
int pcilib_add_register_ranges(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_range_t *ranges) { |
242
by Suren A. Chilingaryan
Initial support for event engines |
163 |
if (!n) { |
164 |
for (n = 0; ranges[n].end; n++); |
|
165 |
}
|
|
166 |
||
167 |
if ((ctx->num_ranges + n + 1) > PCILIB_MAX_REGISTER_RANGES) |
|
168 |
return PCILIB_ERROR_TOOBIG; |
|
169 |
||
170 |
memcpy(ctx->ranges + ctx->num_ranges, ranges, n * sizeof(pcilib_register_range_t)); |
|
171 |
ctx->num_ranges += n; |
|
172 |
||
173 |
return 0; |
|
174 |
}
|
|
175 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
176 |
pcilib_register_bank_t pcilib_find_register_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) { |
177 |
pcilib_register_bank_t i; |
|
178 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
179 |
for (i = 0; ctx->banks[i].access; i++) |
180 |
if (ctx->banks[i].addr == bank) return i; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
181 |
|
182 |
return PCILIB_REGISTER_BANK_INVALID; |
|
183 |
}
|
|
184 |
||
185 |
pcilib_register_bank_t pcilib_find_register_bank_by_name(pcilib_t *ctx, const char *bankname) { |
|
186 |
pcilib_register_bank_t i; |
|
187 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
188 |
for (i = 0; ctx->banks[i].access; i++) |
189 |
if (!strcasecmp(ctx->banks[i].name, bankname)) return i; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
190 |
|
191 |
return PCILIB_REGISTER_BANK_INVALID; |
|
192 |
}
|
|
193 |
||
194 |
pcilib_register_bank_t pcilib_find_register_bank(pcilib_t *ctx, const char *bank) { |
|
195 |
pcilib_register_bank_t res; |
|
196 |
unsigned long addr; |
|
197 |
||
198 |
if (!bank) { |
|
199 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
200 |
const pcilib_register_bank_description_t *banks = model_info->banks; |
|
201 |
if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0; |
|
202 |
return PCILIB_REGISTER_BANK_INVALID; |
|
203 |
}
|
|
204 |
||
205 |
if (pcilib_isxnumber(bank)&&(sscanf(bank,"%lx", &addr) == 1)) { |
|
206 |
res = pcilib_find_register_bank_by_addr(ctx, addr); |
|
207 |
if (res != PCILIB_REGISTER_BANK_INVALID) return res; |
|
208 |
}
|
|
209 |
||
210 |
return pcilib_find_register_bank_by_name(ctx, bank); |
|
211 |
}
|
|
212 |
||
213 |
// DS: FIXME create hash during map_register space
|
|
214 |
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) { |
|
215 |
pcilib_register_t i; |
|
216 |
pcilib_register_bank_t bank_id; |
|
217 |
pcilib_register_bank_addr_t bank_addr = 0; |
|
310
by Suren A. Chilingaryan
Introduce hashes |
218 |
pcilib_register_context_t *reg_ctx; |
236
by Suren A. Chilingaryan
Big redign of model structures |
219 |
|
220 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
221 |
const pcilib_register_description_t *registers = model_info->registers; |
|
222 |
||
223 |
if (bank) { |
|
224 |
bank_id = pcilib_find_register_bank(ctx, bank); |
|
225 |
if (bank_id == PCILIB_REGISTER_BANK_INVALID) { |
|
226 |
pcilib_error("Invalid bank (%s) is specified", bank); |
|
227 |
return PCILIB_REGISTER_INVALID; |
|
228 |
}
|
|
229 |
||
230 |
bank_addr = model_info->banks[bank_id].addr; |
|
310
by Suren A. Chilingaryan
Introduce hashes |
231 |
|
232 |
// ToDo: we can use additionaly per-bank hashes
|
|
233 |
for (i = 0; registers[i].bits; i++) { |
|
234 |
if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; |
|
235 |
}
|
|
236 |
} else { |
|
237 |
HASH_FIND_STR(ctx->reg_hash, reg, reg_ctx); |
|
238 |
if (reg_ctx) return reg_ctx->reg; |
|
239 |
}
|
|
240 |
||
236
by Suren A. Chilingaryan
Big redign of model structures |
241 |
|
242 |
return PCILIB_REGISTER_INVALID; |
|
243 |
};
|
|
244 |
||
245 |
pcilib_register_protocol_t pcilib_find_register_protocol_by_addr(pcilib_t *ctx, pcilib_register_protocol_addr_t protocol) { |
|
246 |
pcilib_register_protocol_t i; |
|
247 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
248 |
for (i = 0; ctx->protocols[i].api; i++) |
249 |
if (ctx->protocols[i].addr == protocol) return i; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
250 |
|
251 |
return PCILIB_REGISTER_PROTOCOL_INVALID; |
|
252 |
}
|
|
253 |
||
254 |
pcilib_register_protocol_t pcilib_find_register_protocol_by_name(pcilib_t *ctx, const char *name) { |
|
255 |
pcilib_register_protocol_t i; |
|
256 |
||
303
by Suren A. Chilingaryan
Initial integration of XML support |
257 |
for (i = 0; ctx->protocols[i].api; i++) |
258 |
if (!strcasecmp(ctx->protocols[i].name, name)) return i; |
|
236
by Suren A. Chilingaryan
Big redign of model structures |
259 |
|
260 |
return PCILIB_REGISTER_PROTOCOL_INVALID; |
|
261 |
}
|
|
262 |
||
263 |
pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const char *protocol) { |
|
264 |
pcilib_register_bank_t res; |
|
265 |
unsigned long addr; |
|
266 |
||
267 |
if (pcilib_isxnumber(protocol)&&(sscanf(protocol,"%lx", &addr) == 1)) { |
|
268 |
res = pcilib_find_register_protocol_by_addr(ctx, addr); |
|
269 |
if (res != PCILIB_REGISTER_BANK_INVALID) return res; |
|
270 |
}
|
|
271 |
||
272 |
return pcilib_find_register_protocol_by_name(ctx, protocol); |
|
273 |
}
|
|
318
by Suren A. Chilingaryan
Support reading/writting register views by id |
274 |
|
332
by Suren A. Chilingaryan
Provide API calls for register and bank address resolution |
275 |
uintptr_t pcilib_resolve_bank_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_bank_t bank) { |
276 |
pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank]; |
|
277 |
||
278 |
if (!bctx->api->resolve) |
|
279 |
return PCILIB_ADDRESS_INVALID; |
|
280 |
||
281 |
return bctx->api->resolve(ctx, bctx, flags, PCILIB_REGISTER_ADDRESS_INVALID); |
|
282 |
}
|
|
283 |
||
284 |
uintptr_t pcilib_resolve_bank_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank) { |
|
285 |
pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank); |
|
286 |
if (bank_id == PCILIB_REGISTER_BANK_INVALID) { |
|
287 |
if (bank) pcilib_error("Invalid register bank is specified (%s)", bank); |
|
288 |
else pcilib_error("Register bank should be specified"); |
|
289 |
return PCILIB_ADDRESS_INVALID; |
|
290 |
}
|
|
291 |
||
292 |
return pcilib_resolve_bank_address_by_id(ctx, flags, bank_id); |
|
293 |
}
|
|
294 |
||
295 |
uintptr_t pcilib_resolve_register_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_t reg) { |
|
296 |
pcilib_register_bank_context_t *bctx = ctx->bank_ctx[ctx->register_ctx[reg].bank]; |
|
297 |
||
298 |
if (!bctx->api->resolve) |
|
299 |
return PCILIB_ADDRESS_INVALID; |
|
300 |
||
301 |
return bctx->api->resolve(ctx, bctx, 0, ctx->registers[reg].addr); |
|
302 |
}
|
|
303 |
||
304 |
uintptr_t pcilib_resolve_register_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank, const char *regname) { |
|
305 |
pcilib_register_t reg = pcilib_find_register(ctx, bank, regname); |
|
306 |
if (reg == PCILIB_REGISTER_INVALID) { |
|
307 |
pcilib_error("Register (%s) is not found", regname); |
|
308 |
return PCILIB_ADDRESS_INVALID; |
|
309 |
}
|
|
310 |
||
311 |
return pcilib_resolve_register_address_by_id(ctx, flags, reg); |
|
312 |
}
|
|
313 |
||
318
by Suren A. Chilingaryan
Support reading/writting register views by id |
314 |
int pcilib_get_register_bank_attr_by_id(pcilib_t *ctx, pcilib_register_bank_t bank, const char *attr, pcilib_value_t *val) { |
315 |
assert(bank < ctx->num_banks); |
|
316 |
||
317 |
return pcilib_get_xml_attr(ctx, ctx->bank_ctx[bank]->xml, attr, val); |
|
318 |
}
|
|
319 |
||
320 |
int pcilib_get_register_bank_attr(pcilib_t *ctx, const char *bankname, const char *attr, pcilib_value_t *val) { |
|
321 |
pcilib_register_bank_t bank; |
|
322 |
||
323 |
bank = pcilib_find_register_bank_by_name(ctx, bankname); |
|
324 |
if (bank == PCILIB_REGISTER_BANK_INVALID) { |
|
325 |
pcilib_error("Bank (%s) is not found", bankname); |
|
326 |
return PCILIB_ERROR_NOTFOUND; |
|
327 |
}
|
|
328 |
||
329 |
return pcilib_get_register_bank_attr_by_id(ctx, bank, attr, val); |
|
330 |
}
|