70
static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc) {
81
static int pcilib_xml_parse_view_reference(pcilib_t *ctx, xmlDocPtr doc, xmlNodePtr node, pcilib_view_reference_t *desc) {
85
for (cur = node->properties; cur != NULL; cur = cur->next) {
86
if(!cur->children) continue;
87
if(!xmlNodeIsText(cur->children)) continue;
89
name = (char*)cur->name;
90
value = (char*)cur->children->content;
92
if (!strcasecmp(name, "name")) {
94
} else if (!strcasecmp(name, "view")) {
100
desc->name = desc->view;
105
static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc) {
71
107
pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc;
109
xmlXPathObjectPtr nodes;
110
xmlNodeSetPtr nodeset;
74
113
char *value, *name;
77
for (cur = node->children; cur != NULL; cur = cur->next) {
78
if (!cur->children) continue;
79
if (!xmlNodeIsText(cur->children)) continue;
81
name = (char*)cur->name;
117
for (cur = node->properties; cur != NULL; cur = cur->next) {
118
if (!cur->children) continue;
119
if (!xmlNodeIsText(cur->children)) continue;
121
name = (char*)cur->name;
82
122
value = (char*)cur->children->content;
83
123
if (!value) continue;
85
125
if (!strcasecmp((char*)name, "address")) {
86
uintptr_t addr = strtol(value, &endptr, 0);
87
if ((strlen(endptr) > 0)) {
88
pcilib_error("Invalid address (%s) is specified in the XML register description", value);
89
return PCILIB_ERROR_INVALID_DATA;
126
uintptr_t addr = strtol(value, &endptr, 0);
127
if ((strlen(endptr) > 0)) {
128
pcilib_error("Invalid address (%s) is specified in the XML register description", value);
129
return PCILIB_ERROR_INVALID_DATA;
91
131
desc->addr = addr;
92
132
} else if(!strcasecmp(name, "offset")) {
93
int offset = strtol(value, &endptr, 0);
94
if ((strlen(endptr) > 0)||(offset < 0)||(offset > (8 * sizeof(pcilib_register_value_t)))) {
95
pcilib_error("Invalid offset (%s) is specified in the XML register description", value);
96
return PCILIB_ERROR_INVALID_DATA;
133
int offset = strtol(value, &endptr, 0);
134
if ((strlen(endptr) > 0)||(offset < 0)||(offset > (8 * sizeof(pcilib_register_value_t)))) {
135
pcilib_error("Invalid offset (%s) is specified in the XML register description", value);
136
return PCILIB_ERROR_INVALID_DATA;
98
138
desc->offset = (pcilib_register_size_t)offset;
99
139
} else if (!strcasecmp(name,"size")) {
100
int size = strtol(value, &endptr, 0);
101
if ((strlen(endptr) > 0)||(size <= 0)||(size > (8 * sizeof(pcilib_register_value_t)))) {
102
pcilib_error("Invalid size (%s) is specified in the XML register description", value);
103
return PCILIB_ERROR_INVALID_DATA;
140
int size = strtol(value, &endptr, 0);
141
if ((strlen(endptr) > 0)||(size <= 0)||(size > (8 * sizeof(pcilib_register_value_t)))) {
142
pcilib_error("Invalid size (%s) is specified in the XML register description", value);
143
return PCILIB_ERROR_INVALID_DATA;
105
145
desc->bits = (pcilib_register_size_t)size;
106
146
} else if (!strcasecmp(name, "default")) {
107
pcilib_register_value_t val = strtol(value, &endptr, 0);
108
if ((strlen(endptr) > 0)) {
109
pcilib_error("Invalid default value (%s) is specified in the XML register description", value);
110
return PCILIB_ERROR_INVALID_DATA;
147
pcilib_register_value_t val = strtol(value, &endptr, 0);
148
if ((strlen(endptr) > 0)) {
149
pcilib_error("Invalid default value (%s) is specified in the XML register description", value);
150
return PCILIB_ERROR_INVALID_DATA;
112
152
desc->defvalue = val;
113
153
} else if (!strcasecmp(name,"min")) {
114
pcilib_register_value_t min = strtol(value, &endptr, 0);
115
if ((strlen(endptr) > 0)) {
116
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
117
return PCILIB_ERROR_INVALID_DATA;
154
pcilib_register_value_t min = strtol(value, &endptr, 0);
155
if ((strlen(endptr) > 0)) {
156
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
157
return PCILIB_ERROR_INVALID_DATA;
120
160
} else if (!strcasecmp(name, "max")) {
121
pcilib_register_value_t max = strtol(value, &endptr, 0);
122
if ((strlen(endptr) > 0)) {
123
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
124
return PCILIB_ERROR_INVALID_DATA;
161
pcilib_register_value_t max = strtol(value, &endptr, 0);
162
if ((strlen(endptr) > 0)) {
163
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
164
return PCILIB_ERROR_INVALID_DATA;
127
167
} else if (!strcasecmp((char*)name,"rwmask")) {
128
168
if (!strcasecmp(value, "all")) {
129
169
desc->rwmask = PCILIB_REGISTER_ALL_BITS;
130
170
} else if (!strcasecmp(value, "none")) {
131
171
desc->rwmask = 0;
133
uintptr_t mask = strtol(value, &endptr, 0);
134
if ((strlen(endptr) > 0)) {
135
pcilib_error("Invalid mask (%s) is specified in the XML register description", value);
136
return PCILIB_ERROR_INVALID_DATA;
173
uintptr_t mask = strtol(value, &endptr, 0);
174
if ((strlen(endptr) > 0)) {
175
pcilib_error("Invalid mask (%s) is specified in the XML register description", value);
176
return PCILIB_ERROR_INVALID_DATA;
140
180
} else if (!strcasecmp(name, "mode")) {
141
181
if (!strcasecmp(value, "R")) {
142
182
desc->mode = PCILIB_REGISTER_R;
212
nodes = xmlXPathEvalExpression(REGISTER_VIEWS_PATH, xpath);
216
xmlErrorPtr xmlerr = xmlGetLastError();
218
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTER_VIEWS_PATH, xmlerr->code, xmlerr->message);
219
else pcilib_error("Failed to parse XPath expression %s", REGISTER_VIEWS_PATH);
220
return PCILIB_ERROR_FAILED;
224
nodeset = nodes->nodesetval;
225
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
228
desc->views = (pcilib_view_reference_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t));
230
xmlXPathFreeObject(nodes);
231
pcilib_error("Failed to allocate %zu bytes of memory to store supported register views", (nodeset->nodeNr + 1) * sizeof(char*));
232
return PCILIB_ERROR_MEMORY;
235
memset(desc->views, 0, (nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t));
236
for (i = 0; i < nodeset->nodeNr; i++) {
237
err = pcilib_xml_parse_view_reference(ctx, doc, nodeset->nodeTab[i], &desc->views[i]);
239
xmlXPathFreeObject(nodes);
244
xmlXPathFreeObject(nodes);
174
249
static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
177
251
xmlXPathObjectPtr nodes;
178
252
xmlNodeSetPtr nodeset;
180
254
pcilib_xml_register_description_t desc = {{0}};
181
255
pcilib_xml_register_description_t fdesc;
183
257
pcilib_register_t reg;
185
259
desc.base.bank = ctx->banks[bank].addr;
186
260
desc.base.rwmask = PCILIB_REGISTER_ALL_BITS;
187
261
desc.base.mode = PCILIB_REGISTER_R;
188
262
desc.base.type = PCILIB_REGISTER_STANDARD;
190
err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank]);
264
err = pcilib_xml_parse_register(ctx, &desc, xpath, doc, node, &ctx->banks[bank]);
192
pcilib_error("Error (%i) parsing an XML register", err);
266
pcilib_error("Error (%i) parsing an XML register", err);
196
270
err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &desc.base, ®);
198
pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name);
272
if (desc.base.views) free(desc.base.views);
273
pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name);
202
ctx->register_ctx[reg].xml = node;
277
ctx->register_ctx[reg].xml = node;
203
278
ctx->register_ctx[reg].min = desc.min;
204
279
ctx->register_ctx[reg].max = desc.max;
280
ctx->register_ctx[reg].views = desc.base.views;
206
283
xpath->node = node;
207
284
nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath);
208
285
xpath->node = NULL;
211
xmlErrorPtr xmlerr = xmlGetLastError();
288
xmlErrorPtr xmlerr = xmlGetLastError();
213
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BIT_REGISTERS_PATH, xmlerr->code, xmlerr->message);
214
else pcilib_error("Failed to parse XPath expression %s", BIT_REGISTERS_PATH);
215
return PCILIB_ERROR_FAILED;
290
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BIT_REGISTERS_PATH, xmlerr->code, xmlerr->message);
291
else pcilib_error("Failed to parse XPath expression %s", BIT_REGISTERS_PATH);
292
return PCILIB_ERROR_FAILED;
218
295
nodeset = nodes->nodesetval;
219
296
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
222
for (i = 0; i < nodeset->nodeNr; i++) {
223
memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t));
225
fdesc.base.bank = desc.base.bank;
226
fdesc.base.addr = desc.base.addr;
227
fdesc.base.mode = desc.base.mode;
228
fdesc.base.rwmask = desc.base.rwmask;
229
fdesc.base.type = PCILIB_REGISTER_BITS;
231
err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank]);
233
pcilib_error("Error parsing field in the XML register %s", desc.base.name);
237
err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, ®);
239
pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name);
243
ctx->register_ctx[reg].xml = nodeset->nodeTab[i];
244
ctx->register_ctx[reg].min = fdesc.min;
245
ctx->register_ctx[reg].max = fdesc.max;
299
for (i = 0; i < nodeset->nodeNr; i++) {
300
memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t));
302
fdesc.base.bank = desc.base.bank;
303
fdesc.base.addr = desc.base.addr;
304
fdesc.base.mode = desc.base.mode;
305
fdesc.base.rwmask = desc.base.rwmask;
306
fdesc.base.type = PCILIB_REGISTER_BITS;
308
err = pcilib_xml_parse_register(ctx, &fdesc, xpath, doc, nodeset->nodeTab[i], &ctx->banks[bank]);
310
pcilib_error("Error parsing field in the XML register %s", desc.base.name);
314
err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, ®);
316
if (fdesc.base.views) free(fdesc.base.views);
317
pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name);
321
ctx->register_ctx[reg].xml = nodeset->nodeTab[i];
322
ctx->register_ctx[reg].min = fdesc.min;
323
ctx->register_ctx[reg].max = fdesc.max;
324
ctx->register_ctx[reg].views = fdesc.base.views;
248
327
xmlXPathFreeObject(nodes);
273
352
desc.endianess = PCILIB_HOST_ENDIAN;
274
353
desc.raw_endianess = PCILIB_HOST_ENDIAN;
276
// iterate through all children, representing bank properties, to fill the structure
277
for (cur = node->children; cur != NULL; cur = cur->next) {
278
if (!cur->children) continue;
279
if (!xmlNodeIsText(cur->children)) continue;
281
name = (char*)cur->name;
355
// iterate through all children, representing bank properties, to fill the structure
356
for (cur = node->properties; cur != NULL; cur = cur->next) {
357
if (!cur->children) continue;
358
if (!xmlNodeIsText(cur->children)) continue;
360
name = (char*)cur->name;
282
361
value = (char*)cur->children->content;
283
362
if (!value) continue;
285
364
if (!strcasecmp(name, "bar")) {
286
char bar = value[0]-'0';
287
if ((strlen(value) != 1)||(bar < 0)||(bar > 5)) {
288
pcilib_error("Invalid BAR (%s) is specified in the XML bank description", value);
289
return PCILIB_ERROR_INVALID_DATA;
365
char bar = value[0]-'0';
366
if ((strlen(value) != 1)||(bar < 0)||(bar > 5)) {
367
pcilib_error("Invalid BAR (%s) is specified in the XML bank description", value);
368
return PCILIB_ERROR_INVALID_DATA;
291
370
desc.bar = (pcilib_bar_t)bar;
293
372
} else if (!strcasecmp(name,"size")) {
294
long size = strtol(value, &endptr, 0);
295
if ((strlen(endptr) > 0)||(size<=0)) {
296
pcilib_error("Invalid bank size (%s) is specified in the XML bank description", value);
297
return PCILIB_ERROR_INVALID_DATA;
373
long size = strtol(value, &endptr, 0);
374
if ((strlen(endptr) > 0)||(size<=0)) {
375
pcilib_error("Invalid bank size (%s) is specified in the XML bank description", value);
376
return PCILIB_ERROR_INVALID_DATA;
299
378
desc.size = (size_t)size;
301
380
} else if (!strcasecmp(name,"protocol")) {
302
pcilib_register_protocol_t protocol = pcilib_find_register_protocol_by_name(ctx, value);
303
if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) {
304
pcilib_error("Unsupported protocol (%s) is specified in the XML bank description", value);
305
return PCILIB_ERROR_NOTSUPPORTED;
307
desc.protocol = ctx->protocols[protocol].addr;
381
pcilib_register_protocol_t protocol = pcilib_find_register_protocol_by_name(ctx, value);
382
if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) {
383
pcilib_error("Unsupported protocol (%s) is specified in the XML bank description", value);
384
return PCILIB_ERROR_NOTSUPPORTED;
386
desc.protocol = ctx->protocols[protocol].addr;
309
388
} else if (!strcasecmp(name,"address")) {
310
uintptr_t addr = strtol(value, &endptr, 0);
311
if ((strlen(endptr) > 0)) {
312
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
313
return PCILIB_ERROR_INVALID_DATA;
389
uintptr_t addr = strtol(value, &endptr, 0);
390
if ((strlen(endptr) > 0)) {
391
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
392
return PCILIB_ERROR_INVALID_DATA;
315
394
desc.read_addr = addr;
316
395
desc.write_addr = addr;
318
397
} else if (!strcasecmp(name,"read_address")) {
319
uintptr_t addr = strtol(value, &endptr, 0);
320
if ((strlen(endptr) > 0)) {
321
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
322
return PCILIB_ERROR_INVALID_DATA;
398
uintptr_t addr = strtol(value, &endptr, 0);
399
if ((strlen(endptr) > 0)) {
400
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
401
return PCILIB_ERROR_INVALID_DATA;
324
403
desc.read_addr = addr;
326
405
} else if (!strcasecmp(name,"write_address")) {
327
uintptr_t addr = strtol(value, &endptr, 0);
328
if ((strlen(endptr) > 0)) {
329
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
330
return PCILIB_ERROR_INVALID_DATA;
406
uintptr_t addr = strtol(value, &endptr, 0);
407
if ((strlen(endptr) > 0)) {
408
pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
409
return PCILIB_ERROR_INVALID_DATA;
332
411
desc.write_addr = addr;
334
413
} else if(strcasecmp((char*)name,"word_size")==0) {
335
int access = strtol(value, &endptr, 0);
336
if ((strlen(endptr) > 0)||(access%8)||(access<=0)||(access>(8 * sizeof(pcilib_register_value_t)))) {
337
pcilib_error("Invalid word size (%s) is specified in the XML bank description", value);
338
return PCILIB_ERROR_INVALID_DATA;
414
int access = strtol(value, &endptr, 0);
415
if ((strlen(endptr) > 0)||(access%8)||(access<=0)||(access>(8 * sizeof(pcilib_register_value_t)))) {
416
pcilib_error("Invalid word size (%s) is specified in the XML bank description", value);
417
return PCILIB_ERROR_INVALID_DATA;
340
419
desc.access = access;
342
421
} else if (!strcasecmp(name,"endianess")) {
370
449
ctx->xml.bank_nodes[bank] = node;
371
450
if (ctx->bank_ctx[bank]) {
372
ctx->bank_ctx[bank]->xml = node;
451
ctx->bank_ctx[bank]->xml = node;
375
454
xpath->node = node;
376
455
nodes = xmlXPathEvalExpression(REGISTERS_PATH, xpath);
377
456
xpath->node = NULL;
459
xmlErrorPtr xmlerr = xmlGetLastError();
460
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTERS_PATH, xmlerr->code, xmlerr->message);
461
else pcilib_error("Failed to parse XPath expression %s", REGISTERS_PATH);
462
return PCILIB_ERROR_FAILED;
465
nodeset = nodes->nodesetval;
466
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
468
for (i = 0; i < nodeset->nodeNr; i++) {
469
err = pcilib_xml_create_register(ctx, bank, xpath, doc, nodeset->nodeTab[i]);
470
if (err) pcilib_error("Error creating XML registers for bank %s", desc.name);
473
xmlXPathFreeObject(nodes);
478
static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_view_description_t *desc) {
480
const char *value, *name;
482
desc->type = PCILIB_TYPE_STRING;
484
for (cur = node->properties; cur != NULL; cur = cur->next) {
485
if (!cur->children) continue;
486
if (!xmlNodeIsText(cur->children)) continue;
488
name = (char*)cur->name;
489
value = (char*)cur->children->content;
490
if (!value) continue;
492
if (!strcasecmp(name, "name")) {
494
} else if (!strcasecmp((char*)name, "description")) {
495
desc->description = value;
496
} else if (!strcasecmp((char*)name, "unit")) {
498
} else if (!strcasecmp((char*)name, "type")) {
499
if (!strcasecmp(value, "string")) desc->type = PCILIB_TYPE_STRING;
500
else if (!strcasecmp(value, "float")) desc->type = PCILIB_TYPE_DOUBLE;
501
else if (!strcasecmp(value, "int")) desc->type = PCILIB_TYPE_LONG;
503
pcilib_error("Invalid type (%s) of register view is specified in the XML bank description", value);
504
return PCILIB_ERROR_INVALID_DATA;
512
static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
515
const char *value, *name;
517
pcilib_transform_view_description_t desc = {0};
519
desc.base.api = &pcilib_enum_view_xml_api;
521
err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
524
for (cur = node->properties; cur != NULL; cur = cur->next) {
525
if (!cur->children) continue;
526
if (!xmlNodeIsText(cur->children)) continue;
528
name = (char*)cur->name;
529
value = (char*)cur->children->content;
530
if (!value) continue;
532
if (!strcasecmp(name, "read_from_register")) {
533
desc.read_from_reg = value;
534
} else if (!strcasecmp(name, "write_to_register")) {
535
desc.write_to_reg = value;
540
return pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
544
static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_value_name_t *desc) {
549
int min_set = 0, max_set = 0;
550
pcilib_register_value_t val;
380
xmlErrorPtr xmlerr = xmlGetLastError();
381
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTERS_PATH, xmlerr->code, xmlerr->message);
382
else pcilib_error("Failed to parse XPath expression %s", REGISTERS_PATH);
383
return PCILIB_ERROR_FAILED;
552
for (cur = node->properties; cur != NULL; cur = cur->next) {
553
if(!cur->children) continue;
554
if(!xmlNodeIsText(cur->children)) continue;
556
name = (char*)cur->name;
557
value = (char*)cur->children->content;
559
if (!strcasecmp(name, "name")) {
561
} else if (!strcasecmp(name, "value")) {
562
val = strtol(value, &endptr, 0);
563
if ((strlen(endptr) > 0)) {
564
pcilib_error("Invalid enum value (%s) is specified in the XML enum node", value);
565
return PCILIB_ERROR_INVALID_DATA;
568
} else if (!strcasecmp(name, "min")) {
569
val = strtol(value, &endptr, 0);
570
if ((strlen(endptr) > 0)) {
571
pcilib_error("Invalid enum min-value (%s) is specified in the XML enum node", value);
572
return PCILIB_ERROR_INVALID_DATA;
576
} else if (!strcasecmp(name, "max")) {
577
val = strtol(value, &endptr, 0);
578
if ((strlen(endptr) > 0)) {
579
pcilib_error("Invalid enum max-value (%s) is specified in the XML enum node", value);
580
return PCILIB_ERROR_INVALID_DATA;
587
if ((!min_set)&&(!max_set)) {
588
desc->min = desc->value;
589
desc->max = desc->value;
590
} else if (max_set) {
592
} else if (min_set) {
593
desc->max = (pcilib_register_value_t)-1;
596
if ((desc->min > desc->max)||(desc->value < desc->min)||(desc->value > desc->max)) {
597
pcilib_error("Invalid enum configuration (min: %lu, max: %lu, value: %lu)", desc->min, desc->max, desc->value);
598
return PCILIB_ERROR_INVALID_DATA;
604
static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
608
xmlXPathObjectPtr nodes;
609
xmlNodeSetPtr nodeset;
611
pcilib_enum_view_description_t desc = {0};
613
desc.base.unit = pcilib_xml_enum_view_unit;
614
desc.base.api = &pcilib_enum_view_xml_api;
616
err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
621
nodes = xmlXPathEvalExpression(ENUM_ELEMENTS_PATH, xpath);
625
xmlErrorPtr xmlerr = xmlGetLastError();
626
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", ENUM_ELEMENTS_PATH, xmlerr->code, xmlerr->message);
627
else pcilib_error("Failed to parse XPath expression %s", ENUM_ELEMENTS_PATH);
628
return PCILIB_ERROR_FAILED;
631
nodeset = nodes->nodesetval;
632
if (xmlXPathNodeSetIsEmpty(nodeset)) {
633
xmlXPathFreeObject(nodes);
634
pcilib_error("No names is defined for enum view (%s)", desc.base.name);
635
return PCILIB_ERROR_INVALID_DATA;
638
desc.names = (pcilib_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_value_name_t));
640
xmlXPathFreeObject(nodes);
641
pcilib_error("No names is defined for enum view (%s)", desc.base.name);
642
return PCILIB_ERROR_INVALID_DATA;
646
for (i = 0; i < nodeset->nodeNr; i++) {
647
err = pcilib_xml_parse_value_name(ctx, xpath, doc, nodeset->nodeTab[i], &desc.names[i]);
649
xmlXPathFreeObject(nodes);
654
memset(&desc.names[nodeset->nodeNr], 0, sizeof(pcilib_value_name_t));
656
xmlXPathFreeObject(nodes);
659
err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
660
if (err) free(desc.names);
664
static int pcilib_xml_parse_unit_transform(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_unit_transform_t *desc) {
668
for (cur = node->properties; cur != NULL; cur = cur->next) {
669
if (!cur->children) continue;
670
if (!xmlNodeIsText(cur->children)) continue;
672
name = (char*)cur->name;
673
value = (char*)cur->children->content;
675
if (!strcasecmp(name, "unit")) {
677
} else if (!strcasecmp(name, "transform")) {
678
desc->transform = value;
686
* function to create a unit from a unit xml node, then populating ctx with it
687
*@param[in,out] ctx - the pcilib_t running
688
*@param[in] xpath - the xpath context of the unis xml file
689
*@param[in] doc - the AST of the unit xml file
690
*@param[in] node - the node representing the unit
691
*@return an error code: 0 if evrythinh is ok
693
static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
696
pcilib_unit_description_t desc = {0};
698
xmlXPathObjectPtr nodes;
699
xmlNodeSetPtr nodeset;
704
for (cur = node->properties; cur != NULL; cur = cur->next) {
705
if (!cur->children) continue;
706
if (!xmlNodeIsText(cur->children)) continue;
708
name = (char*)cur->name;
709
value = (char*)cur->children->content;
710
if (!strcasecmp(name, "name")) {
716
nodes = xmlXPathEvalExpression(UNIT_TRANSFORMS_PATH, xpath);
720
xmlErrorPtr xmlerr = xmlGetLastError();
721
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", UNIT_TRANSFORMS_PATH, xmlerr->code, xmlerr->message);
722
else pcilib_error("Failed to parse XPath expression %s", UNIT_TRANSFORMS_PATH);
723
return PCILIB_ERROR_FAILED;
386
726
nodeset = nodes->nodesetval;
387
727
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
730
if (nodeset->nodeNr > PCILIB_MAX_TRANSFORMS_PER_UNIT) {
731
xmlXPathFreeObject(nodes);
732
pcilib_error("Too many transforms for unit %s are defined, only %lu are supported", desc.name, PCILIB_MAX_TRANSFORMS_PER_UNIT);
733
return PCILIB_ERROR_INVALID_DATA;
389
736
for (i = 0; i < nodeset->nodeNr; i++) {
390
err = pcilib_xml_create_register(ctx, bank, xpath, doc, nodeset->nodeTab[i]);
391
if (err) pcilib_error("Error creating XML registers for bank %s", desc.name);
737
err = pcilib_xml_parse_unit_transform(ctx, xpath, doc, nodeset->nodeTab[i], &desc.transforms[i]);
739
xmlXPathFreeObject(nodes);
394
744
xmlXPathFreeObject(nodes);
746
return pcilib_add_units(ctx, 1, &desc);
405
755
* @param[in] pci the pcilib_t running, which will be filled
407
757
static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) {
408
xmlXPathObjectPtr bank_nodes;
759
xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL;
409
760
xmlNodeSetPtr nodeset;
411
bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath);
413
xmlErrorPtr xmlerr = xmlGetLastError();
414
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message);
415
else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH);
416
return PCILIB_ERROR_FAILED;
763
bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath);
764
if (bank_nodes) transform_nodes = xmlXPathEvalExpression(TRANSFORM_VIEWS_PATH, xpath);
765
if (transform_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath);
766
if (enum_nodes) unit_nodes = xmlXPathEvalExpression(UNITS_PATH, xpath);
769
const unsigned char *expr = (enum_nodes?UNITS_PATH:(transform_nodes?ENUM_VIEWS_PATH:(bank_nodes?TRANSFORM_VIEWS_PATH:BANKS_PATH)));
771
if (enum_nodes) xmlXPathFreeObject(enum_nodes);
772
if (transform_nodes) xmlXPathFreeObject(transform_nodes);
773
if (bank_nodes) xmlXPathFreeObject(bank_nodes);
774
xmlErrorPtr xmlerr = xmlGetLastError();
775
if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", expr, xmlerr->code, xmlerr->message);
776
else pcilib_error("Failed to parse XPath expression %s", expr);
777
return PCILIB_ERROR_FAILED;
780
nodeset = unit_nodes->nodesetval;
781
if(!xmlXPathNodeSetIsEmpty(nodeset)) {
782
for(i=0; i < nodeset->nodeNr; i++) {
783
err = pcilib_xml_create_unit(ctx, xpath, doc, nodeset->nodeTab[i]);
784
if (err) pcilib_error("Error (%i) creating unit", err);
788
nodeset = transform_nodes->nodesetval;
789
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
790
for(i=0; i < nodeset->nodeNr; i++) {
791
err = pcilib_xml_create_transform_view(ctx, xpath, doc, nodeset->nodeTab[i]);
792
if (err) pcilib_error("Error (%i) creating register transform", err);
796
nodeset = enum_nodes->nodesetval;
797
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
798
for(i=0; i < nodeset->nodeNr; i++) {
799
err = pcilib_xml_create_enum_view(ctx, xpath, doc, nodeset->nodeTab[i]);
800
if (err) pcilib_error("Error (%i) creating register enum", err);
420
804
nodeset = bank_nodes->nodesetval;
421
805
if (!xmlXPathNodeSetIsEmpty(nodeset)) {
423
for (i = 0; i < nodeset->nodeNr; i++) {
424
pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]);
806
for (i = 0; i < nodeset->nodeNr; i++) {
807
err = pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]);
808
if (err) pcilib_error("Error (%i) creating bank", err);
813
xmlXPathFreeObject(unit_nodes);
814
xmlXPathFreeObject(enum_nodes);
815
xmlXPathFreeObject(transform_nodes);
427
816
xmlXPathFreeObject(bank_nodes);
432
821
static int pcilib_xml_load_xsd(pcilib_t *ctx, char *xsd_filename) {
435
824
xmlSchemaParserCtxtPtr ctxt;
437
826
/** we first parse the xsd file for AST with validation*/
438
827
ctxt = xmlSchemaNewParserCtxt(xsd_filename);
440
xmlErrorPtr xmlerr = xmlGetLastError();
441
if (xmlerr) pcilib_error("xmlSchemaNewParserCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
442
else pcilib_error("Failed to create a parser for XML schemas");
443
return PCILIB_ERROR_FAILED;
829
xmlErrorPtr xmlerr = xmlGetLastError();
830
if (xmlerr) pcilib_error("xmlSchemaNewParserCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
831
else pcilib_error("Failed to create a parser for XML schemas");
832
return PCILIB_ERROR_FAILED;
446
835
ctx->xml.schema = xmlSchemaParse(ctxt);
447
836
if (!ctx->xml.schema) {
448
xmlErrorPtr xmlerr = xmlGetLastError();
449
xmlSchemaFreeParserCtxt(ctxt);
450
if (xmlerr) pcilib_error("Failed to parse XML schema, xmlSchemaParse reported error %d - %s", xmlerr->code, xmlerr->message);
451
else pcilib_error("Failed to parse XML schema");
452
return PCILIB_ERROR_INVALID_DATA;
837
xmlErrorPtr xmlerr = xmlGetLastError();
838
xmlSchemaFreeParserCtxt(ctxt);
839
if (xmlerr) pcilib_error("Failed to parse XML schema, xmlSchemaParse reported error %d - %s", xmlerr->code, xmlerr->message);
840
else pcilib_error("Failed to parse XML schema");
841
return PCILIB_ERROR_INVALID_DATA;
455
844
xmlSchemaFreeParserCtxt(ctxt);
457
846
ctx->xml.validator = xmlSchemaNewValidCtxt(ctx->xml.schema);
458
847
if (!ctx->xml.validator) {
459
xmlErrorPtr xmlerr = xmlGetLastError();
460
if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
461
else pcilib_error("Failed to create a validation context");
462
return PCILIB_ERROR_FAILED;
848
xmlErrorPtr xmlerr = xmlGetLastError();
849
if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
850
else pcilib_error("Failed to create a validation context");
851
return PCILIB_ERROR_FAILED;
465
854
err = xmlSchemaSetValidOptions(ctx->xml.validator, XML_SCHEMA_VAL_VC_I_CREATE);
467
xmlErrorPtr xmlerr = xmlGetLastError();
468
if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message);
469
else pcilib_error("Failed to configure the validation context to populate default attributes");
470
return PCILIB_ERROR_FAILED;
856
xmlErrorPtr xmlerr = xmlGetLastError();
857
if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message);
858
else pcilib_error("Failed to configure the validation context to populate default attributes");
859
return PCILIB_ERROR_FAILED;
482
871
full_name = (char*)alloca(strlen(path) + strlen(name) + 2);
484
pcilib_error("Error allocating %zu bytes of memory in stack to create a file name", strlen(path) + strlen(name) + 2);
485
return PCILIB_ERROR_MEMORY;
873
pcilib_error("Error allocating %zu bytes of memory in stack to create a file name", strlen(path) + strlen(name) + 2);
874
return PCILIB_ERROR_MEMORY;
488
877
sprintf(full_name, "%s/%s", path, name);
490
879
doc = xmlCtxtReadFile(ctx->xml.parser, full_name, NULL, 0);
492
xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
493
if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
494
else pcilib_error("Error parsing %s", full_name);
495
return PCILIB_ERROR_INVALID_DATA;
881
xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
882
if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
883
else pcilib_error("Error parsing %s", full_name);
884
return PCILIB_ERROR_INVALID_DATA;
498
887
err = xmlSchemaValidateDoc(ctx->xml.validator, doc);
500
xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
502
if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
503
else pcilib_error("Error validating %s", full_name);
504
return PCILIB_ERROR_VERIFY;
889
xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
891
if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
892
else pcilib_error("Error validating %s", full_name);
893
return PCILIB_ERROR_VERIFY;
507
896
xpath = xmlXPathNewContext(doc);
509
xmlErrorPtr xmlerr = xmlGetLastError();
511
if (xmlerr) pcilib_error("Document %s: xmlXpathNewContext reported error %d - %s for document %s", full_name, xmlerr->code, xmlerr->message);
512
else pcilib_error("Error creating XPath context for %s", full_name);
513
return PCILIB_ERROR_FAILED;
898
xmlErrorPtr xmlerr = xmlGetLastError();
900
if (xmlerr) pcilib_error("Document %s: xmlXpathNewContext reported error %d - %s for document %s", full_name, xmlerr->code, xmlerr->message);
901
else pcilib_error("Error creating XPath context for %s", full_name);
902
return PCILIB_ERROR_FAILED;
516
// This can only partially fail... Therefore we need to keep XML and just return the error...
905
// This can only partially fail... Therefore we need to keep XML and just return the error...
517
906
err = pcilib_xml_process_document(ctx, doc, xpath);
519
908
if (ctx->xml.num_files == PCILIB_MAX_MODEL_FILES) {
521
910
xmlXPathFreeContext(xpath);
522
pcilib_error("Too many XML files for a model, only up to %zu are supported", PCILIB_MAX_MODEL_FILES);
523
return PCILIB_ERROR_TOOBIG;
911
pcilib_error("Too many XML files for a model, only up to %zu are supported", PCILIB_MAX_MODEL_FILES);
912
return PCILIB_ERROR_TOOBIG;
526
915
ctx->xml.docs[ctx->xml.num_files] = doc;