/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
1
/**
324 by Suren A. Chilingaryan
Documentation update
2
 * @file xml.c
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
3
 * @version 1.0
303 by Suren A. Chilingaryan
Initial integration of XML support
4
 *
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
5
 * @brief this file is the main source file for the implementation of dynamic registers using xml and several funtionalities for the "pci-tool" line command tool from XML files. the xml part has been implemented using libxml2
303 by Suren A. Chilingaryan
Initial integration of XML support
6
 *
277.2.17 by zilio nicolas
further modifications
7
 * @details registers and banks nodes are parsed using xpath expression, but their properties is get by recursively getting all properties nodes. In this sense, if a property changes, the algorithm has to be changed, but if it's registers or banks nodes, just the xpath expression modification should be enough.
8
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
9
 Libxml2 considers blank spaces within the XML as node natively and this code as been produced considering blank spaces in the XML files. In case XML files would not contain blank spaces anymore, please change the code.
10
277.2.17 by zilio nicolas
further modifications
11
 In case the performance is not good enough, please consider the following : hard code of formulas
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
12
 */
277.2.9 by zilio nicolas
xml files get by model and remove of validation mode
13
#define _XOPEN_SOURCE 700
303 by Suren A. Chilingaryan
Initial integration of XML support
14
#define _BSD_SOURCE
15
#define _DEFAULT_SOURCE
16
277.2.1 by zilio nicolas
registers and banks support in xml v1. pci -ll works fine, but got segfault on pci -r name and pci -r name gives 0 always. might be due to the order in pci.c ------> ask suren
17
#include <stdlib.h>
18
#include <stdio.h>
19
#include <string.h>
277.2.16 by zilio nicolas
end of modifications
20
#include <strings.h>
303 by Suren A. Chilingaryan
Initial integration of XML support
21
#include <dirent.h>
22
#include <errno.h>
23
#include <alloca.h>
24
#include <unistd.h>
25
#include <sys/types.h>
26
#include <sys/stat.h>
27
28
277.2.9 by zilio nicolas
xml files get by model and remove of validation mode
29
#include <libxml/xmlschemastypes.h>
277.2.13 by zilio nicolas
almost finished regarding suren remarks
30
#include <libxml/tree.h>
31
#include <libxml/parser.h>
32
#include <libxml/xpath.h>
33
#include <libxml/xpathInternals.h>
303 by Suren A. Chilingaryan
Initial integration of XML support
34
277.2.17 by zilio nicolas
further modifications
35
#include "config.h"
36
303 by Suren A. Chilingaryan
Initial integration of XML support
37
#include "pci.h"
38
#include "bank.h"
39
#include "register.h"
40
#include "xml.h"
41
#include "error.h"
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
42
#include "view.h"
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
43
#include "py.h"
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
44
#include "views/enum.h"
45
#include "views/transform.h"
46
47
48
#define BANKS_PATH ((xmlChar*)"/model/bank")					/**< path to complete nodes of banks */
49
#define REGISTERS_PATH ((xmlChar*)"./register")		 			/**< all standard registers nodes */
50
#define BIT_REGISTERS_PATH ((xmlChar*)"./field") 				/**< all bits registers nodes */
51
#define REGISTER_VIEWS_PATH ((xmlChar*)"./view") 				/**< supported register & field views */
379 by Suren A. Chilingaryan
Support XML configuration of device models
52
#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform")			/**< path to complete nodes of views */
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
53
#define ENUM_VIEWS_PATH ((xmlChar*)"/model/enum")	 			/**< path to complete nodes of views */
54
#define ENUM_ELEMENTS_PATH ((xmlChar*)"./name") 				/**< all elements in the enum */
55
#define UNITS_PATH ((xmlChar*)"/model/unit")	 				/**< path to complete nodes of units */
379 by Suren A. Chilingaryan
Support XML configuration of device models
56
#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform")				/**< all transforms of the unit */
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
57
58
59
static const char *pcilib_xml_bank_default_format = "0x%lx";
60
static const char *pcilib_xml_enum_view_unit = "name";
303 by Suren A. Chilingaryan
Initial integration of XML support
61
62
typedef struct {
63
    pcilib_register_description_t base;
319 by Suren A. Chilingaryan
Provide register listings in public API
64
    pcilib_register_value_range_t range;
303 by Suren A. Chilingaryan
Initial integration of XML support
65
} pcilib_xml_register_description_t;
66
67
/*
68
static xmlNodePtr pcilib_xml_get_parent_bank_node(xmlDocPtr doc, xmlNodePtr node) {
69
    xmlNodePtr bank_node;
70
    bank_node = node->parent->parent;
71
	// bank_description is always a first node according to the XSD schema
72
    return xmlFirstElementChild(bank_node);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
73
303 by Suren A. Chilingaryan
Initial integration of XML support
74
}
75
76
static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr node) {
77
    return node->parent->parent;
78
}
79
*/
80
322 by Suren A. Chilingaryan
Support multiple XML files per folder
81
int pcilib_get_xml_attr(pcilib_t *ctx, pcilib_xml_node_t *node, const char *attr, pcilib_value_t *val) {
82
    xmlAttr *prop;
83
    xmlChar *str;
84
85
    prop = xmlHasProp(node, BAD_CAST attr);
86
    if ((!prop)||(!prop->children)) return PCILIB_ERROR_NOTFOUND;
87
88
    str = prop->children->content;
89
    return pcilib_set_value_from_static_string(ctx, val, (const char*)str);
90
}
91
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
92
static int pcilib_xml_parse_view_reference(pcilib_t *ctx, xmlDocPtr doc, xmlNodePtr node, pcilib_view_reference_t *desc) {
93
    xmlAttr *cur;
94
    char *value, *name;
95
96
    for (cur = node->properties; cur != NULL; cur = cur->next) {
97
        if(!cur->children) continue;
98
        if(!xmlNodeIsText(cur->children)) continue;
99
100
        name = (char*)cur->name;
101
        value = (char*)cur->children->content;
102
103
        if (!strcasecmp(name, "name")) {
104
	    desc->name = value;
105
        } else if (!strcasecmp(name, "view")) {
106
            desc->view = value;
107
        }
108
    }
109
110
    if (!desc->name)
111
	desc->name = desc->view;
112
305.1.4 by zilio nicolas
more towards views
113
    return 0;
114
}
115
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
116
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) {
117
    int err;
303 by Suren A. Chilingaryan
Initial integration of XML support
118
    pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc;
119
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
120
    xmlXPathObjectPtr nodes;
121
    xmlNodeSetPtr nodeset;
122
123
    xmlAttrPtr cur;
303 by Suren A. Chilingaryan
Initial integration of XML support
124
    char *value, *name;
125
    char *endptr;
126
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
127
128
    for (cur = node->properties; cur != NULL; cur = cur->next) {
129
        if (!cur->children) continue;
130
        if (!xmlNodeIsText(cur->children)) continue;
131
132
        name = (char*)cur->name;
303 by Suren A. Chilingaryan
Initial integration of XML support
133
        value = (char*)cur->children->content;
134
        if (!value) continue;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
135
303 by Suren A. Chilingaryan
Initial integration of XML support
136
        if (!strcasecmp((char*)name, "address")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
137
            uintptr_t addr = strtol(value, &endptr, 0);
138
            if ((strlen(endptr) > 0)) {
139
                pcilib_error("Invalid address (%s) is specified in the XML register description", value);
140
                return PCILIB_ERROR_INVALID_DATA;
141
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
142
            desc->addr = addr;
143
        } else if(!strcasecmp(name, "offset")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
144
            int offset = strtol(value, &endptr, 0);
145
            if ((strlen(endptr) > 0)||(offset < 0)||(offset > (8 * sizeof(pcilib_register_value_t)))) {
146
                pcilib_error("Invalid offset (%s) is specified in the XML register description", value);
147
                return PCILIB_ERROR_INVALID_DATA;
148
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
149
            desc->offset = (pcilib_register_size_t)offset;
150
        } else if (!strcasecmp(name,"size")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
151
            int size = strtol(value, &endptr, 0);
152
            if ((strlen(endptr) > 0)||(size <= 0)||(size > (8 * sizeof(pcilib_register_value_t)))) {
153
                pcilib_error("Invalid size (%s) is specified in the XML register description", value);
154
                return PCILIB_ERROR_INVALID_DATA;
155
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
156
            desc->bits = (pcilib_register_size_t)size;
157
        } else if (!strcasecmp(name, "default")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
158
            pcilib_register_value_t val  = strtol(value, &endptr, 0);
159
            if ((strlen(endptr) > 0)) {
160
                pcilib_error("Invalid default value (%s) is specified in the XML register description", value);
161
                return PCILIB_ERROR_INVALID_DATA;
162
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
163
            desc->defvalue = val;
164
        } else if (!strcasecmp(name,"min")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
165
            pcilib_register_value_t min = strtol(value, &endptr, 0);
166
            if ((strlen(endptr) > 0)) {
167
                pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
168
                return PCILIB_ERROR_INVALID_DATA;
169
            }
319 by Suren A. Chilingaryan
Provide register listings in public API
170
            xml_desc->range.min = min;
303 by Suren A. Chilingaryan
Initial integration of XML support
171
        } else if (!strcasecmp(name, "max")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
172
            pcilib_register_value_t max = strtol(value, &endptr, 0);
173
            if ((strlen(endptr) > 0)) {
174
                pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
175
                return PCILIB_ERROR_INVALID_DATA;
176
            }
319 by Suren A. Chilingaryan
Provide register listings in public API
177
            xml_desc->range.max = max;
303 by Suren A. Chilingaryan
Initial integration of XML support
178
        } else if (!strcasecmp((char*)name,"rwmask")) {
179
            if (!strcasecmp(value, "all")) {
180
                desc->rwmask = PCILIB_REGISTER_ALL_BITS;
181
            } else if (!strcasecmp(value, "none")) {
182
                desc->rwmask = 0;
183
            } else {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
184
                uintptr_t mask = strtol(value, &endptr, 0);
185
                if ((strlen(endptr) > 0)) {
186
                    pcilib_error("Invalid mask (%s) is specified in the XML register description", value);
187
                    return PCILIB_ERROR_INVALID_DATA;
188
                }
189
                desc->rwmask = mask;
190
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
191
        } else if (!strcasecmp(name, "mode")) {
192
            if (!strcasecmp(value, "R")) {
193
                desc->mode = PCILIB_REGISTER_R;
194
            } else if (!strcasecmp(value, "W")) {
195
                desc->mode = PCILIB_REGISTER_W;
196
            } else if (!strcasecmp(value, "RW")) {
197
                desc->mode = PCILIB_REGISTER_RW;
198
            } else if (!strcasecmp(value, "RW1C")) {
199
                desc->mode = PCILIB_REGISTER_RW1C;
200
            } else if (!strcasecmp(value, "W1C")) {
201
                desc->mode = PCILIB_REGISTER_W1C;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
202
            } else if (!strcasecmp(value, "RW1I")) {
203
                desc->mode = PCILIB_REGISTER_RW1I;
204
            } else if (!strcasecmp(value, "W1I")) {
205
                desc->mode = PCILIB_REGISTER_W1I;
206
            } else if (!strcasecmp(value, "-")) {
207
                desc->mode = 0;
303 by Suren A. Chilingaryan
Initial integration of XML support
208
            } else {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
209
                pcilib_error("Invalid access mode (%s) is specified in the XML register description", value);
210
                return PCILIB_ERROR_INVALID_DATA;
303 by Suren A. Chilingaryan
Initial integration of XML support
211
            }
212
        } else if (!strcasecmp(name, "type")) {
213
            if (!strcasecmp(value, "fifo")) {
214
                desc->type = PCILIB_REGISTER_FIFO;
215
            } else {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
216
                pcilib_error("Invalid register type (%s) is specified in the XML register description", value);
217
                return PCILIB_ERROR_INVALID_DATA;
303 by Suren A. Chilingaryan
Initial integration of XML support
218
            }
219
        } else if (!strcasecmp(name,"name")) {
220
            desc->name = value;
221
        } else if (!strcasecmp(name,"description")) {
222
            desc->description = value;
223
        }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
224
    }
225
226
    xpath->node = node;
227
    nodes = xmlXPathEvalExpression(REGISTER_VIEWS_PATH, xpath);
228
    xpath->node = NULL;
229
230
    if (!nodes) {
231
        xmlErrorPtr xmlerr = xmlGetLastError();
232
233
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTER_VIEWS_PATH, xmlerr->code, xmlerr->message);
234
        else pcilib_error("Failed to parse XPath expression %s", REGISTER_VIEWS_PATH);
235
        return PCILIB_ERROR_FAILED;
236
    }
237
238
239
    nodeset = nodes->nodesetval;
240
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
241
        int i;
242
243
        desc->views = (pcilib_view_reference_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t));
244
        if (!desc->views) {
245
	    xmlXPathFreeObject(nodes);
246
	    pcilib_error("Failed to allocate %zu bytes of memory to store supported register views", (nodeset->nodeNr + 1) * sizeof(char*));
247
	    return PCILIB_ERROR_MEMORY;
305.1.4 by zilio nicolas
more towards views
248
        }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
249
250
	memset(desc->views, 0, (nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t));
251
        for (i = 0; i < nodeset->nodeNr; i++) {
252
	    err = pcilib_xml_parse_view_reference(ctx, doc, nodeset->nodeTab[i], &desc->views[i]);
253
	    if (err) {
254
		xmlXPathFreeObject(nodes);
255
		return err;
256
	    }
257
	}
303 by Suren A. Chilingaryan
Initial integration of XML support
258
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
259
    xmlXPathFreeObject(nodes);
303 by Suren A. Chilingaryan
Initial integration of XML support
260
261
    return 0;
262
}
263
264
static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
265
    int err;
266
    xmlXPathObjectPtr nodes;
267
    xmlNodeSetPtr nodeset;
268
269
    pcilib_xml_register_description_t desc = {{0}};
270
    pcilib_xml_register_description_t fdesc;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
271
303 by Suren A. Chilingaryan
Initial integration of XML support
272
    pcilib_register_t reg;
305.1.6 by nicolas.zilio at hotmail
more towards views
273
303 by Suren A. Chilingaryan
Initial integration of XML support
274
    desc.base.bank = ctx->banks[bank].addr;
275
    desc.base.rwmask = PCILIB_REGISTER_ALL_BITS;
276
    desc.base.mode = PCILIB_REGISTER_R;
277
    desc.base.type = PCILIB_REGISTER_STANDARD;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
278
279
    err = pcilib_xml_parse_register(ctx, &desc, xpath, doc, node, &ctx->banks[bank]);
303 by Suren A. Chilingaryan
Initial integration of XML support
280
    if (err) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
281
        pcilib_error("Error (%i) parsing an XML register", err);
282
        return err;
303 by Suren A. Chilingaryan
Initial integration of XML support
283
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
284
303 by Suren A. Chilingaryan
Initial integration of XML support
285
    err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &desc.base, &reg);
286
    if (err) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
287
        if (desc.base.views) free(desc.base.views);
288
        pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name);
289
        return err;
303 by Suren A. Chilingaryan
Initial integration of XML support
290
    }
291
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
292
    ctx->register_ctx[reg].xml = node;
319 by Suren A. Chilingaryan
Provide register listings in public API
293
    memcpy(&ctx->register_ctx[reg].range, &desc.range, sizeof(pcilib_register_value_range_t));
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
294
    ctx->register_ctx[reg].views = desc.base.views;
295
303 by Suren A. Chilingaryan
Initial integration of XML support
296
297
    xpath->node = node;
298
    nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath);
299
    xpath->node = NULL;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
300
303 by Suren A. Chilingaryan
Initial integration of XML support
301
    if (!nodes) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
302
        xmlErrorPtr xmlerr = xmlGetLastError();
303 by Suren A. Chilingaryan
Initial integration of XML support
303
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
304
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BIT_REGISTERS_PATH, xmlerr->code, xmlerr->message);
305
        else pcilib_error("Failed to parse XPath expression %s", BIT_REGISTERS_PATH);
306
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
307
    }
308
309
    nodeset = nodes->nodesetval;
310
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
311
        int i;
312
313
        for (i = 0; i < nodeset->nodeNr; i++) {
314
            memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t));
315
316
            fdesc.base.bank = desc.base.bank;
317
            fdesc.base.addr = desc.base.addr;
318
            fdesc.base.mode = desc.base.mode;
319
            fdesc.base.rwmask = desc.base.rwmask;
320
            fdesc.base.type = PCILIB_REGISTER_BITS;
321
322
            err = pcilib_xml_parse_register(ctx, &fdesc, xpath, doc, nodeset->nodeTab[i], &ctx->banks[bank]);
323
            if (err) {
324
                pcilib_error("Error parsing field in the XML register %s", desc.base.name);
325
                continue;
326
            }
327
328
            err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, &reg);
329
            if (err) {
330
                if (fdesc.base.views) free(fdesc.base.views);
331
                pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name);
332
                continue;
333
            }
334
335
            ctx->register_ctx[reg].xml = nodeset->nodeTab[i];
319 by Suren A. Chilingaryan
Provide register listings in public API
336
            memcpy(&ctx->register_ctx[reg].range, &fdesc.range, sizeof(pcilib_register_value_range_t));
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
337
            ctx->register_ctx[reg].views = fdesc.base.views;
338
        }
303 by Suren A. Chilingaryan
Initial integration of XML support
339
    }
340
    xmlXPathFreeObject(nodes);
341
342
    return 0;
343
}
344
345
static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
346
    int err;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
347
303 by Suren A. Chilingaryan
Initial integration of XML support
348
    int override = 0;
349
    pcilib_register_bank_description_t desc = {0};
350
    pcilib_register_bank_t bank;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
351
    xmlAttrPtr cur;
303 by Suren A. Chilingaryan
Initial integration of XML support
352
    char *value, *name;
353
    char *endptr;
354
355
    xmlXPathObjectPtr nodes;
356
    xmlNodeSetPtr nodeset;
357
358
359
    desc.format = pcilib_xml_bank_default_format;
360
    desc.addr = PCILIB_REGISTER_BANK_DYNAMIC;
361
    desc.bar = PCILIB_BAR_NOBAR;
362
    desc.size = 0x1000;
363
    desc.protocol = PCILIB_REGISTER_PROTOCOL_DEFAULT;
364
    desc.access = 32;
365
    desc.endianess = PCILIB_HOST_ENDIAN;
366
    desc.raw_endianess = PCILIB_HOST_ENDIAN;
367
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
368
    // iterate through all children, representing bank properties, to fill the structure
369
    for (cur = node->properties; cur != NULL; cur = cur->next) {
370
        if (!cur->children) continue;
371
        if (!xmlNodeIsText(cur->children)) continue;
372
373
        name = (char*)cur->name;
303 by Suren A. Chilingaryan
Initial integration of XML support
374
        value = (char*)cur->children->content;
375
        if (!value) continue;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
376
303 by Suren A. Chilingaryan
Initial integration of XML support
377
        if (!strcasecmp(name, "bar")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
378
            char bar = value[0]-'0';
379
            if ((strlen(value) != 1)||(bar < 0)||(bar > 5)) {
380
                pcilib_error("Invalid BAR (%s) is specified in the XML bank description", value);
381
                return PCILIB_ERROR_INVALID_DATA;
382
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
383
            desc.bar = (pcilib_bar_t)bar;
384
            override = 1;
385
        } else if (!strcasecmp(name,"size")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
386
            long size = strtol(value, &endptr, 0);
387
            if ((strlen(endptr) > 0)||(size<=0)) {
388
                pcilib_error("Invalid bank size (%s) is specified in the XML bank description", value);
389
                return PCILIB_ERROR_INVALID_DATA;
390
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
391
            desc.size = (size_t)size;
392
            override = 1;
393
        } else if (!strcasecmp(name,"protocol")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
394
            pcilib_register_protocol_t protocol = pcilib_find_register_protocol_by_name(ctx, value);
395
            if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) {
396
                pcilib_error("Unsupported protocol (%s) is specified in the XML bank description", value);
397
                return PCILIB_ERROR_NOTSUPPORTED;
398
            }
399
            desc.protocol = ctx->protocols[protocol].addr;
303 by Suren A. Chilingaryan
Initial integration of XML support
400
            override = 1;
401
        } else if (!strcasecmp(name,"address")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
402
            uintptr_t addr = strtol(value, &endptr, 0);
403
            if ((strlen(endptr) > 0)) {
404
                pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
405
                return PCILIB_ERROR_INVALID_DATA;
406
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
407
            desc.read_addr = addr;
408
            desc.write_addr = addr;
409
            override = 1;
410
        } else if (!strcasecmp(name,"read_address")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
411
            uintptr_t addr = strtol(value, &endptr, 0);
412
            if ((strlen(endptr) > 0)) {
413
                pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
414
                return PCILIB_ERROR_INVALID_DATA;
415
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
416
            desc.read_addr = addr;
417
            override = 1;
418
        } else if (!strcasecmp(name,"write_address")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
419
            uintptr_t addr = strtol(value, &endptr, 0);
420
            if ((strlen(endptr) > 0)) {
421
                pcilib_error("Invalid address (%s) is specified in the XML bank description", value);
422
                return PCILIB_ERROR_INVALID_DATA;
423
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
424
            desc.write_addr = addr;
425
            override = 1;
426
        } else if(strcasecmp((char*)name,"word_size")==0) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
427
            int access = strtol(value, &endptr, 0);
428
            if ((strlen(endptr) > 0)||(access%8)||(access<=0)||(access>(8 * sizeof(pcilib_register_value_t)))) {
429
                pcilib_error("Invalid word size (%s) is specified in the XML bank description", value);
430
                return PCILIB_ERROR_INVALID_DATA;
431
            }
303 by Suren A. Chilingaryan
Initial integration of XML support
432
            desc.access = access;
433
            override = 1;
434
        } else if (!strcasecmp(name,"endianess")) {
435
            if (!strcasecmp(value,"little")) desc.endianess = PCILIB_LITTLE_ENDIAN;
436
            else if (!strcasecmp(value,"big")) desc.endianess = PCILIB_BIG_ENDIAN;
437
            else if (!strcasecmp(value,"host")) desc.endianess = PCILIB_HOST_ENDIAN;
438
            else {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
439
                pcilib_error("Invalid endianess (%s) is specified in the XML bank description", value);
440
                return PCILIB_ERROR_INVALID_DATA;
303 by Suren A. Chilingaryan
Initial integration of XML support
441
            }
442
            override = 1;
443
        } else if (!strcasecmp(name,"format")) {
444
            desc.format = value;
445
            override = 1;
446
        } else if (!strcasecmp((char*)name,"name")) {
447
            desc.name = value;
448
        } else if (!strcasecmp((char*)name,"description")) {
449
            desc.description = value;
450
            override = 1;
451
        } else if (!strcasecmp((char*)name,"override")) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
452
            override = 1;
303 by Suren A. Chilingaryan
Initial integration of XML support
453
        }
454
    }
455
456
    err = pcilib_add_register_banks(ctx, override?PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE:PCILIB_MODEL_MODIFICATION_FLAG_SKIP_EXISTING, 1, &desc, &bank);
457
    if (err) {
458
        pcilib_error("Error adding register bank (%s) specified in the XML bank description", desc.name);
459
        return err;
460
    }
461
462
    ctx->xml.bank_nodes[bank] = node;
463
    if (ctx->bank_ctx[bank]) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
464
        ctx->bank_ctx[bank]->xml = node;
303 by Suren A. Chilingaryan
Initial integration of XML support
465
    }
466
467
    xpath->node = node;
468
    nodes = xmlXPathEvalExpression(REGISTERS_PATH, xpath);
469
    xpath->node = NULL;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
470
471
    if (!nodes) {
472
        xmlErrorPtr xmlerr = xmlGetLastError();
473
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTERS_PATH, xmlerr->code, xmlerr->message);
474
        else pcilib_error("Failed to parse XPath expression %s", REGISTERS_PATH);
475
        return PCILIB_ERROR_FAILED;
476
    }
477
478
    nodeset = nodes->nodesetval;
479
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
480
        int i;
481
        for (i = 0; i < nodeset->nodeNr; i++) {
482
            err = pcilib_xml_create_register(ctx, bank, xpath, doc, nodeset->nodeTab[i]);
483
            if (err) pcilib_error("Error creating XML registers for bank %s", desc.name);
484
        }
485
    }
486
    xmlXPathFreeObject(nodes);
487
488
    return 0;
489
}
490
491
static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_view_description_t *desc) {
492
    xmlAttrPtr cur;
493
    const char *value, *name;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
494
495
    int inconsistent = (desc->mode & PCILIB_ACCESS_INCONSISTENT);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
496
497
    for (cur = node->properties; cur != NULL; cur = cur->next) {
498
        if (!cur->children) continue;
499
        if (!xmlNodeIsText(cur->children)) continue;
500
501
        name = (char*)cur->name;
502
        value = (char*)cur->children->content;
503
        if (!value) continue;
504
505
        if (!strcasecmp(name, "name")) {
316 by Suren A. Chilingaryan
Support XML properties
506
                // Overriden by path
321 by Suren A. Chilingaryan
Support computed (property-based) registers
507
            if (desc->name) continue;
508
            if (*value == '/')
509
	        desc->flags |= PCILIB_VIEW_FLAG_PROPERTY;
510
            desc->name = value;
316 by Suren A. Chilingaryan
Support XML properties
511
	} else if (!strcasecmp(name, "path")) {
512
	    desc->name = value;
513
	    desc->flags |= PCILIB_VIEW_FLAG_PROPERTY;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
514
	} else if (!strcasecmp(name, "register")) {
515
	    desc->regname = value;
516
	    desc->flags |= PCILIB_VIEW_FLAG_REGISTER;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
517
        } else if (!strcasecmp((char*)name, "description")) {
518
    	    desc->description = value;
519
        } else if (!strcasecmp((char*)name, "unit")) {
520
            desc->unit = value;
521
        } else if (!strcasecmp((char*)name, "type")) {
522
            if (!strcasecmp(value, "string")) desc->type = PCILIB_TYPE_STRING;
523
            else if (!strcasecmp(value, "float")) desc->type = PCILIB_TYPE_DOUBLE;
524
            else if (!strcasecmp(value, "int")) desc->type = PCILIB_TYPE_LONG;
525
            else {
526
                pcilib_error("Invalid type (%s) of register view is specified in the XML bank description", value);
527
                return PCILIB_ERROR_INVALID_DATA;
528
            }
321 by Suren A. Chilingaryan
Support computed (property-based) registers
529
        } else if (!strcasecmp(name, "mode")) {
530
            if (!strcasecmp(value, "R")) {
531
                desc->mode = PCILIB_REGISTER_R;
532
            } else if (!strcasecmp(value, "W")) {
533
                desc->mode = PCILIB_REGISTER_W;
534
            } else if (!strcasecmp(value, "RW")) {
535
                desc->mode = PCILIB_REGISTER_RW;
536
            } else if (!strcasecmp(value, "-")) {
537
                desc->mode = 0;
538
            } else {
539
                pcilib_error("Invalid access mode (%s) is specified in the XML register description", value);
540
                return PCILIB_ERROR_INVALID_DATA;
541
            }
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
542
        } else if (!strcasecmp(name, "write_verification")) {
543
	    if (strcmp(value, "0")) inconsistent = 0;
544
	    else inconsistent = 1;
346.1.5 by Vasilii Chernov
Add write_register python wrap. Add no_set_check attribute to pcilib_view_t type
545
	}
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
546
    }
346.1.9 by Vasilii Chernov
Change no_set_check parameter name. Move Python wrap to separate directory.
547
	
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
548
    if (inconsistent) desc->mode |= PCILIB_ACCESS_INCONSISTENT;
549
    else desc->mode &= ~PCILIB_ACCESS_INCONSISTENT;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
550
551
    return 0;
552
}
553
554
static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
555
    int err;
556
    xmlAttrPtr cur;
557
    const char *value, *name;
318 by Suren A. Chilingaryan
Support reading/writting register views by id
558
    pcilib_view_context_t *view_ctx;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
559
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
560
    pcilib_access_mode_t mode = 0;
324 by Suren A. Chilingaryan
Documentation update
561
    pcilib_transform_view_description_t desc = {{0}};
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
562
311 by Suren A. Chilingaryan
Implement enum view
563
    desc.base.api = &pcilib_transform_view_api;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
564
    desc.base.type = PCILIB_TYPE_DOUBLE;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
565
    desc.base.mode = PCILIB_ACCESS_RW;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
566
567
    err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
568
    if (err) return err;
569
570
    for (cur = node->properties; cur != NULL; cur = cur->next) {
571
        if (!cur->children) continue;
572
        if (!xmlNodeIsText(cur->children)) continue;
573
574
        name = (char*)cur->name;
575
        value = (char*)cur->children->content;
576
        if (!value) continue;
577
578
        if (!strcasecmp(name, "read_from_register")) {
316 by Suren A. Chilingaryan
Support XML properties
579
            if (desc.base.flags&PCILIB_VIEW_FLAG_PROPERTY) {
580
                if (strstr(value, "$value")) {
581
                    pcilib_error("Invalid transform specified in XML property (%s). The properties can't reference $value (%s)", desc.base.name, value);
582
                    return PCILIB_ERROR_INVALID_DATA;
583
                }
584
            }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
585
            desc.read_from_reg = value;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
586
            if ((value)&&(*value)) mode |= PCILIB_ACCESS_R;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
587
        } else if (!strcasecmp(name, "write_to_register")) {
316 by Suren A. Chilingaryan
Support XML properties
588
            if (desc.base.flags&PCILIB_VIEW_FLAG_PROPERTY) {
589
                if (strstr(value, "$value")) {
590
                    pcilib_error("Invalid transform specified in XML property (%s). The properties can't reference $value (%s)", desc.base.name, value);
591
                    return PCILIB_ERROR_INVALID_DATA;
592
                }
593
            }
594
            desc.write_to_reg = value;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
595
            if ((value)&&(*value)) mode |= PCILIB_ACCESS_W;
346.1.6 by Vasilii Chernov
Merge script and transform view. Add get register and properties info to python wrap.
596
        } else if (!strcasecmp(name, "script")) {
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
597
	    desc.script = value;
598
	    break;
346.1.6 by Vasilii Chernov
Merge script and transform view. Add get register and properties info to python wrap.
599
        }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
600
    }
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
601
    desc.base.mode &= (~PCILIB_ACCESS_RW)|mode;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
602
318 by Suren A. Chilingaryan
Support reading/writting register views by id
603
    err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);
604
    if (err) return err;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
605
318 by Suren A. Chilingaryan
Support reading/writting register views by id
606
    view_ctx->xml = node;
607
    return 0;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
608
}
609
319 by Suren A. Chilingaryan
Provide register listings in public API
610
static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_register_value_name_t *desc) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
611
    xmlAttr *cur;
612
    char *value, *name;
613
    char *endptr;
614
615
    int min_set = 0, max_set = 0;
616
    pcilib_register_value_t val;
346.1.25 by Vasilii Chernov
Set value description content to NULL in pcilib_xml_parse_value_name
617
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
618
    for (cur = node->properties; cur != NULL; cur = cur->next) {
619
        if(!cur->children) continue;
620
        if(!xmlNodeIsText(cur->children)) continue;
621
622
        name = (char*)cur->name;
623
        value = (char*)cur->children->content;
624
625
        if (!strcasecmp(name, "name")) {
626
	    desc->name = value;
320 by Suren A. Chilingaryan
Add optional description in the value name-aliases
627
        } else if (!strcasecmp(name, "description")) {
628
	    desc->description = value;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
629
        } else if (!strcasecmp(name, "value")) {
630
            val = strtol(value, &endptr, 0);
631
            if ((strlen(endptr) > 0)) {
632
                pcilib_error("Invalid enum value (%s) is specified in the XML enum node", value);
633
                return PCILIB_ERROR_INVALID_DATA;
634
            }
635
            desc->value = val;
636
        } else if (!strcasecmp(name, "min")) {
637
            val = strtol(value, &endptr, 0);
638
            if ((strlen(endptr) > 0)) {
639
                pcilib_error("Invalid enum min-value (%s) is specified in the XML enum node", value);
640
                return PCILIB_ERROR_INVALID_DATA;
641
            }
642
            desc->min = val;
643
	    min_set = 1;
644
        } else if (!strcasecmp(name, "max")) {
645
            val = strtol(value, &endptr, 0);
646
            if ((strlen(endptr) > 0)) {
647
                pcilib_error("Invalid enum max-value (%s) is specified in the XML enum node", value);
648
                return PCILIB_ERROR_INVALID_DATA;
649
            }
650
            desc->max = val;
651
	    max_set = 1;
652
	}
653
    }
654
655
    if ((!min_set)&&(!max_set)) {
656
	desc->min = desc->value;
657
	desc->max = desc->value;
658
    } else if (max_set) {
659
	desc->min = 0;
660
    } else if (min_set) {
661
	desc->max = (pcilib_register_value_t)-1;
662
    }
663
664
    if ((desc->min > desc->max)||(desc->value < desc->min)||(desc->value > desc->max)) {
665
	pcilib_error("Invalid enum configuration (min: %lu, max: %lu, value: %lu)", desc->min, desc->max, desc->value);
666
	return PCILIB_ERROR_INVALID_DATA;
667
    }
668
669
    return 0;
670
}
671
672
static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
673
    int i;
674
    int err;
675
676
    xmlXPathObjectPtr nodes;
677
    xmlNodeSetPtr nodeset;
678
318 by Suren A. Chilingaryan
Support reading/writting register views by id
679
    pcilib_view_context_t *view_ctx;
324 by Suren A. Chilingaryan
Documentation update
680
    pcilib_enum_view_description_t desc = {{0}};
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
681
315 by Suren A. Chilingaryan
Support properties of arbitrary type
682
    desc.base.type = PCILIB_TYPE_STRING;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
683
    desc.base.unit = pcilib_xml_enum_view_unit;
684
    desc.base.api = &pcilib_enum_view_xml_api;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
685
    desc.base.mode = PCILIB_ACCESS_RW;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
686
687
    err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
688
    if (err) return err;
689
690
691
    xpath->node = node;
692
    nodes = xmlXPathEvalExpression(ENUM_ELEMENTS_PATH, xpath);
693
    xpath->node = NULL;
694
303 by Suren A. Chilingaryan
Initial integration of XML support
695
    if (!nodes) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
696
        xmlErrorPtr xmlerr = xmlGetLastError();
697
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", ENUM_ELEMENTS_PATH, xmlerr->code, xmlerr->message);
698
        else pcilib_error("Failed to parse XPath expression %s", ENUM_ELEMENTS_PATH);
699
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
700
    }
701
702
    nodeset = nodes->nodesetval;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
703
    if (xmlXPathNodeSetIsEmpty(nodeset)) {
704
	xmlXPathFreeObject(nodes);
705
	pcilib_error("No names is defined for enum view (%s)", desc.base.name);
706
	return PCILIB_ERROR_INVALID_DATA; 
707
    }
708
319 by Suren A. Chilingaryan
Provide register listings in public API
709
    desc.names = (pcilib_register_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_register_value_name_t));
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
710
    if (!desc.names) {
711
	xmlXPathFreeObject(nodes);
712
	pcilib_error("No names is defined for enum view (%s)", desc.base.name);
713
	return PCILIB_ERROR_INVALID_DATA; 
714
    }
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
715
    memset(desc.names, 0, (nodeset->nodeNr + 1) * sizeof(pcilib_register_value_name_t));
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
716
717
    for (i = 0; i < nodeset->nodeNr; i++) {
718
        err = pcilib_xml_parse_value_name(ctx, xpath, doc, nodeset->nodeTab[i], &desc.names[i]);
719
        if (err) {
720
	    xmlXPathFreeObject(nodes);
721
	    free(desc.names);
722
	    return err;
303 by Suren A. Chilingaryan
Initial integration of XML support
723
	}
724
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
725
303 by Suren A. Chilingaryan
Initial integration of XML support
726
    xmlXPathFreeObject(nodes);
727
318 by Suren A. Chilingaryan
Support reading/writting register views by id
728
    err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);
729
    if (err) {
730
        free(desc.names);
731
        return err;
732
    }
733
    view_ctx->xml = node;
734
    return 0;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
735
}
736
737
static int pcilib_xml_parse_unit_transform(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_unit_transform_t *desc) {
738
    xmlAttrPtr cur;
739
    char *value, *name;
740
741
    for (cur = node->properties; cur != NULL; cur = cur->next) {
742
        if (!cur->children) continue;
743
        if (!xmlNodeIsText(cur->children)) continue;
744
745
        name = (char*)cur->name;
746
        value = (char*)cur->children->content;
747
748
        if (!strcasecmp(name, "unit")) {
749
	    desc->unit = value;
750
        } else if (!strcasecmp(name, "transform")) {
751
	    desc->transform = value;
752
	}
753
    }
754
303 by Suren A. Chilingaryan
Initial integration of XML support
755
    return 0;
756
}
757
305.1.8 by nicolas.zilio at hotmail
views with units functionnal (beware, as formulas are completely crap now, we could get segfault, for example if we want to write a negative value in register)
758
/**
759
 * function to create a unit from a unit xml node, then populating ctx with it
760
 *@param[in,out] ctx - the pcilib_t running
761
 *@param[in] xpath - the xpath context of the unis xml file
762
 *@param[in] doc - the AST of the unit xml file
763
 *@param[in] node - the node representing the unit
764
 *@return an error code: 0 if evrythinh is ok
765
 */
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
766
static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
305.1.7 by nicolas.zilio at hotmail
views working fine, units in progress
767
    int err;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
768
769
    pcilib_unit_description_t desc = {0};
770
771
    xmlXPathObjectPtr nodes;
772
    xmlNodeSetPtr nodeset;
773
774
    xmlAttrPtr cur;
775
    char *value, *name;
776
777
    for (cur = node->properties; cur != NULL; cur = cur->next) {
778
        if (!cur->children) continue;
779
        if (!xmlNodeIsText(cur->children)) continue;
780
781
        name = (char*)cur->name;
305.1.7 by nicolas.zilio at hotmail
views working fine, units in progress
782
        value = (char*)cur->children->content;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
783
        if (!strcasecmp(name, "name")) {
784
	    desc.name = value;
305.1.7 by nicolas.zilio at hotmail
views working fine, units in progress
785
        }
786
    }
787
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
788
    xpath->node = node;
789
    nodes = xmlXPathEvalExpression(UNIT_TRANSFORMS_PATH, xpath);
790
    xpath->node = NULL;
791
792
    if (!nodes) {
793
        xmlErrorPtr xmlerr = xmlGetLastError();
794
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", UNIT_TRANSFORMS_PATH, xmlerr->code, xmlerr->message);
795
        else pcilib_error("Failed to parse XPath expression %s", UNIT_TRANSFORMS_PATH);
796
        return PCILIB_ERROR_FAILED;
305.1.7 by nicolas.zilio at hotmail
views working fine, units in progress
797
    }
798
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
799
    nodeset = nodes->nodesetval;
800
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
801
	int i;
802
    
803
	if (nodeset->nodeNr > PCILIB_MAX_TRANSFORMS_PER_UNIT) {
804
	    xmlXPathFreeObject(nodes);
805
	    pcilib_error("Too many transforms for unit %s are defined, only %lu are supported", desc.name, PCILIB_MAX_TRANSFORMS_PER_UNIT);
806
	    return PCILIB_ERROR_INVALID_DATA;
807
	}
305.1.4 by zilio nicolas
more towards views
808
	
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
809
	for (i = 0; i < nodeset->nodeNr; i++) {
810
    	    err = pcilib_xml_parse_unit_transform(ctx, xpath, doc, nodeset->nodeTab[i], &desc.transforms[i]);
811
	    if (err) {
812
		xmlXPathFreeObject(nodes);
813
		return err;
305.1.4 by zilio nicolas
more towards views
814
	    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
815
	}
305.1.4 by zilio nicolas
more towards views
816
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
817
    xmlXPathFreeObject(nodes);
818
819
    return pcilib_add_units(ctx, 1, &desc);
305.1.4 by zilio nicolas
more towards views
820
}
821
822
277.2.7 by zilio nicolas
put xml nodes pointers for banks and registers in pcilib_t, compil ok
823
/** pcilib_xml_initialize_banks
303 by Suren A. Chilingaryan
Initial integration of XML support
824
 *
825
 * function to create the structures to store the banks from the AST
826
 * @see pcilib_xml_create_bank
277.2.7 by zilio nicolas
put xml nodes pointers for banks and registers in pcilib_t, compil ok
827
 * @param[in] doc the AST of the xml file.
277.2.12 by zilio nicolas
almost finished regarding suren remarks
828
 * @param[in] pci the pcilib_t running, which will be filled
277.2.7 by zilio nicolas
put xml nodes pointers for banks and registers in pcilib_t, compil ok
829
 */
303 by Suren A. Chilingaryan
Initial integration of XML support
830
static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
831
    int err;
346.1.3 by Vasilii Chernov
Add support for setting register value to script transfrom. Add set_property and get_property functions to pcipywrap. Cleaning cmakelists from unused dependencies
832
    xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
833
    xmlNodeSetPtr nodeset;
305.1.4 by zilio nicolas
more towards views
834
    int i;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
835
836
    bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath);
837
    if (bank_nodes) transform_nodes = xmlXPathEvalExpression(TRANSFORM_VIEWS_PATH, xpath);
346.1.3 by Vasilii Chernov
Add support for setting register value to script transfrom. Add set_property and get_property functions to pcipywrap. Cleaning cmakelists from unused dependencies
838
    if (transform_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
839
    if (enum_nodes) unit_nodes = xmlXPathEvalExpression(UNITS_PATH, xpath);
840
841
    if (!unit_nodes) {
842
	const unsigned char *expr = (enum_nodes?UNITS_PATH:(transform_nodes?ENUM_VIEWS_PATH:(bank_nodes?TRANSFORM_VIEWS_PATH:BANKS_PATH)));
843
844
        if (enum_nodes) xmlXPathFreeObject(enum_nodes);
845
        if (transform_nodes) xmlXPathFreeObject(transform_nodes);
846
        if (bank_nodes) xmlXPathFreeObject(bank_nodes);
847
        xmlErrorPtr xmlerr = xmlGetLastError();
848
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", expr, xmlerr->code, xmlerr->message);
849
        else pcilib_error("Failed to parse XPath expression %s", expr);
850
        return PCILIB_ERROR_FAILED;
851
    }
852
853
    nodeset = unit_nodes->nodesetval;
854
    if(!xmlXPathNodeSetIsEmpty(nodeset)) {
855
        for(i=0; i < nodeset->nodeNr; i++) {
856
            err = pcilib_xml_create_unit(ctx, xpath, doc, nodeset->nodeTab[i]);
857
	    if (err) pcilib_error("Error (%i) creating unit", err);
858
        }
859
    }
860
861
    nodeset = transform_nodes->nodesetval;
862
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
863
        for(i=0; i < nodeset->nodeNr; i++) {
346.1.10 by Vasilii Chernov
1. Cmakelists - move copy xml folder command to root file
864
            err = pcilib_xml_create_transform_view(ctx, xpath, doc, nodeset->nodeTab[i]);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
865
	    if (err) pcilib_error("Error (%i) creating register transform", err);
866
        }
867
    }
868
869
    nodeset = enum_nodes->nodesetval;
870
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
871
        for(i=0; i < nodeset->nodeNr; i++) {
872
            err = pcilib_xml_create_enum_view(ctx, xpath, doc, nodeset->nodeTab[i]);
873
	    if (err) pcilib_error("Error (%i) creating register enum", err);
874
        }
875
    }
305.1.6 by nicolas.zilio at hotmail
more towards views
876
877
    nodeset = bank_nodes->nodesetval;
878
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
879
        for (i = 0; i < nodeset->nodeNr; i++) {
880
            err = pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]);
881
	    if (err) pcilib_error("Error (%i) creating bank", err);
882
        }
305.1.6 by nicolas.zilio at hotmail
more towards views
883
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
884
885
886
    xmlXPathFreeObject(unit_nodes);
887
    xmlXPathFreeObject(enum_nodes);
888
    xmlXPathFreeObject(transform_nodes);
305.1.6 by nicolas.zilio at hotmail
more towards views
889
    xmlXPathFreeObject(bank_nodes);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
890
303 by Suren A. Chilingaryan
Initial integration of XML support
891
    return 0;
892
}
893
379 by Suren A. Chilingaryan
Support XML configuration of device models
894
static int pcilib_xml_load_xsd_file(pcilib_t *ctx, const char *xsd_filename, xmlSchemaPtr *schema, xmlSchemaValidCtxtPtr *validator) {
303 by Suren A. Chilingaryan
Initial integration of XML support
895
    int err;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
896
303 by Suren A. Chilingaryan
Initial integration of XML support
897
    xmlSchemaParserCtxtPtr ctxt;
898
322 by Suren A. Chilingaryan
Support multiple XML files per folder
899
    *schema = NULL;
900
    *validator = NULL;
901
303 by Suren A. Chilingaryan
Initial integration of XML support
902
    /** we first parse the xsd file for AST with validation*/
903
    ctxt = xmlSchemaNewParserCtxt(xsd_filename);
904
    if (!ctxt) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
905
        xmlErrorPtr xmlerr = xmlGetLastError();
906
        if (xmlerr) pcilib_error("xmlSchemaNewParserCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
907
        else pcilib_error("Failed to create a parser for XML schemas");
908
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
909
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
910
322 by Suren A. Chilingaryan
Support multiple XML files per folder
911
    *schema = xmlSchemaParse(ctxt);
912
    if (!*schema) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
913
        xmlErrorPtr xmlerr = xmlGetLastError();
914
        xmlSchemaFreeParserCtxt(ctxt);
915
        if (xmlerr) pcilib_error("Failed to parse XML schema, xmlSchemaParse reported error %d - %s", xmlerr->code, xmlerr->message);
916
        else pcilib_error("Failed to parse XML schema");
917
        return PCILIB_ERROR_INVALID_DATA;
303 by Suren A. Chilingaryan
Initial integration of XML support
918
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
919
303 by Suren A. Chilingaryan
Initial integration of XML support
920
    xmlSchemaFreeParserCtxt(ctxt);
921
322 by Suren A. Chilingaryan
Support multiple XML files per folder
922
    *validator  = xmlSchemaNewValidCtxt(*schema);
923
    if (!*validator) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
924
        xmlErrorPtr xmlerr = xmlGetLastError();
379 by Suren A. Chilingaryan
Support XML configuration of device models
925
	xmlSchemaFree(*schema); *schema = NULL;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
926
        if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
927
        else pcilib_error("Failed to create a validation context");
928
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
929
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
930
322 by Suren A. Chilingaryan
Support multiple XML files per folder
931
    err = xmlSchemaSetValidOptions(*validator, XML_SCHEMA_VAL_VC_I_CREATE);
303 by Suren A. Chilingaryan
Initial integration of XML support
932
    if (err) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
933
        xmlErrorPtr xmlerr = xmlGetLastError();
379 by Suren A. Chilingaryan
Support XML configuration of device models
934
	xmlSchemaFreeValidCtxt(*validator); *validator = NULL;
935
	xmlSchemaFree(*schema); *schema = NULL;
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
936
        if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message);
937
        else pcilib_error("Failed to configure the validation context to populate default attributes");
938
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
939
    }
940
941
    return 0;
942
}
943
379 by Suren A. Chilingaryan
Support XML configuration of device models
944
/*
945
static xmlDocPtr pcilib_xml_load_xml_file(pcilib_t *ctx, const char *xsd_filename, const char *xml_filename) {
946
    int err;
947
    xmlDocPtr doc;
948
    xmlSchemaPtr schema;
949
    xmlSchemaValidCtxtPtr validator;
950
    xmlParserCtxtPtr parser;
951
952
    err = pcilib_xml_load_xsd_file(ctx, xsd_filename, &schema, &validator);
953
    if (err) {
954
	pcilib_error("Error (%i) parsing the devices schema (%s)", err, xsd_filename);
955
	return NULL;
956
    }
957
958
    parser = xmlNewParserCtxt();
959
    if (!parser) {
960
        xmlErrorPtr xmlerr = xmlGetLastError();
961
	xmlSchemaFree(schema);
962
	xmlSchemaFreeValidCtxt(validator);
963
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
964
        else pcilib_error("Failed to create an XML parser context");
965
        return NULL;
966
    }
967
968
    doc = xmlCtxtReadFile(parser, xml_filename, NULL, 0);
969
    if (!doc) {
970
        xmlErrorPtr xmlerr = xmlGetLastError();
971
	xmlFreeParserCtxt(parser);
972
	xmlSchemaFree(schema);
973
	xmlSchemaFreeValidCtxt(validator);
974
	if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", xml_filename, xmlerr->code, xmlerr->message);
975
        else pcilib_error("Error parsing %s", xml_filename);
976
	return NULL;
977
    }
978
    
979
    err = xmlSchemaValidateDoc(validator, doc);
980
    if (err) {
981
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
982
	xmlFreeDoc(doc);
983
	xmlFreeParserCtxt(parser);
984
	xmlSchemaFree(schema);
985
	xmlSchemaFreeValidCtxt(validator);
986
        if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", xml_filename, xmlerr->code, xmlerr->message);
987
        else pcilib_error("Error validating %s", xml_filename);
988
        return NULL;
989
    }
990
991
    xmlFreeParserCtxt(parser);
992
    xmlSchemaFree(schema);
993
    xmlSchemaFreeValidCtxt(validator);
994
995
    return doc;
996
}
997
*/
998
999
static xmlXPathObjectPtr pcilib_xml_eval_xpath_expression(pcilib_t *ctx, xmlDocPtr doc, const xmlChar *query) {
1000
    xmlXPathContextPtr xpath;
1001
    xmlXPathObjectPtr nodes;
1002
1003
    xpath = xmlXPathNewContext(doc);
1004
    if (!xpath) {
1005
        xmlErrorPtr xmlerr = xmlGetLastError();
1006
        if (xmlerr) pcilib_error("xmlXpathNewContext reported error %d - %s", xmlerr->code, xmlerr->message);
1007
        else pcilib_error("Error creating XPath context");
1008
        return NULL;
1009
    }
1010
1011
    nodes = xmlXPathEvalExpression(query, xpath);
1012
    if (!nodes) {
1013
        xmlErrorPtr xmlerr = xmlGetLastError();
1014
	xmlXPathFreeContext(xpath);
1015
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", query, xmlerr->code, xmlerr->message);
1016
        else pcilib_error("Failed to parse XPath expression %s", query);
1017
        return NULL;
1018
    }
1019
1020
    xmlXPathFreeContext(xpath);
1021
    return nodes;
1022
}
1023
1024
static int pcilib_xml_load_xsd(pcilib_t *ctx, const char *model_dir) {
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1025
    int err;
1026
1027
    struct stat st;
1028
    char *xsd_path;
1029
1030
    xsd_path = (char*)alloca(strlen(model_dir) + 32);
1031
    if (!xsd_path) return PCILIB_ERROR_MEMORY;
1032
1033
    sprintf(xsd_path, "%s/model.xsd", model_dir);
1034
    if (stat(xsd_path, &st)) {
1035
        pcilib_info("XML models are not present, missing parts schema");
1036
        return PCILIB_ERROR_NOTFOUND;
1037
    }
1038
1039
    err = pcilib_xml_load_xsd_file(ctx, xsd_path, &ctx->xml.parts_schema, &ctx->xml.parts_validator);
1040
    if (err) return err;
1041
1042
    sprintf(xsd_path, "%s/references.xsd", model_dir);
1043
    if (stat(xsd_path, &st)) {
1044
        pcilib_info("XML models are not present, missing schema");
1045
        return PCILIB_ERROR_NOTFOUND;
1046
    }
1047
1048
    return pcilib_xml_load_xsd_file(ctx, xsd_path, &ctx->xml.schema, &ctx->xml.validator);
1049
}
1050
1051
1052
379 by Suren A. Chilingaryan
Support XML configuration of device models
1053
static xmlDocPtr pcilib_xml_load_file(pcilib_t *ctx, xmlParserCtxtPtr parser, xmlSchemaValidCtxtPtr validator, const char *path, const char *name) {
303 by Suren A. Chilingaryan
Initial integration of XML support
1054
    int err;
1055
    char *full_name;
1056
    xmlDocPtr doc;
1057
1058
    full_name = (char*)alloca(strlen(path) + strlen(name) + 2);
1059
    if (!name) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1060
        pcilib_error("Error allocating %zu bytes of memory in stack to create a file name", strlen(path) + strlen(name) + 2);
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1061
        return NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1062
    }
1063
1064
    sprintf(full_name, "%s/%s", path, name);
1065
379 by Suren A. Chilingaryan
Support XML configuration of device models
1066
    doc = xmlCtxtReadFile(parser, full_name, NULL, 0);
303 by Suren A. Chilingaryan
Initial integration of XML support
1067
    if (!doc) {
379 by Suren A. Chilingaryan
Support XML configuration of device models
1068
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1069
        if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
1070
        else pcilib_error("Error parsing %s", full_name);
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1071
        return NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1072
    }
1073
379 by Suren A. Chilingaryan
Support XML configuration of device models
1074
    err = xmlSchemaValidateDoc(validator, doc);
303 by Suren A. Chilingaryan
Initial integration of XML support
1075
    if (err) {
379 by Suren A. Chilingaryan
Support XML configuration of device models
1076
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1077
        xmlFreeDoc(doc);
1078
        if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
1079
        else pcilib_error("Error validating %s", full_name);
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1080
        return NULL;
1081
    }
1082
1083
    return doc;
303 by Suren A. Chilingaryan
Initial integration of XML support
1084
}
1085
379 by Suren A. Chilingaryan
Support XML configuration of device models
1086
static xmlDocPtr pcilib_xml_load_model_file(pcilib_t *ctx, const char *path, const char *name) {
1087
    return pcilib_xml_load_file(ctx, ctx->xml.parser, ctx->xml.parts_validator, path, name);
1088
}
1089
1090
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1091
static int pcilib_process_xml_internal(pcilib_t *ctx, const char *model, const char *location) {
303 by Suren A. Chilingaryan
Initial integration of XML support
1092
    int err;
1093
1094
    DIR *rep;
1095
    struct dirent *file = NULL;
1096
    char *model_dir, *model_path;
1097
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1098
    xmlDocPtr doc = NULL;
1099
    xmlNodePtr root = NULL;
1100
    xmlXPathContextPtr xpath;
1101
1102
    if (ctx->xml.num_files == PCILIB_MAX_MODEL_FILES) {
1103
        pcilib_error("Too many XML locations for a model, only up to %zu are supported", PCILIB_MAX_MODEL_FILES);
1104
        return PCILIB_ERROR_TOOBIG;
1105
    }
1106
303 by Suren A. Chilingaryan
Initial integration of XML support
1107
    model_dir = getenv("PCILIB_MODEL_DIR");
1108
    if (!model_dir) model_dir = PCILIB_MODEL_DIR;
1109
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1110
    if (!model) model = ctx->model;
1111
    if (!location) location = "";
1112
1113
    model_path = (char*)alloca(strlen(model_dir) + strlen(model) + strlen(location) + 3);
303 by Suren A. Chilingaryan
Initial integration of XML support
1114
    if (!model_path) return PCILIB_ERROR_MEMORY;
1115
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1116
    sprintf(model_path, "%s/%s/%s", model_dir, model, location);
303 by Suren A. Chilingaryan
Initial integration of XML support
1117
1118
    rep = opendir(model_path);
1119
    if (!rep) return PCILIB_ERROR_NOTFOUND;
1120
1121
    while ((file = readdir(rep)) != NULL) {
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1122
        xmlDocPtr newdoc;
1123
        
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1124
        size_t len = strlen(file->d_name);
1125
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
1126
        if (file->d_type != DT_REG) continue;
1127
379 by Suren A. Chilingaryan
Support XML configuration of device models
1128
        newdoc = pcilib_xml_load_model_file(ctx, model_path, file->d_name);
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1129
        if (!newdoc) {
1130
            pcilib_error("Error processing XML file %s", file->d_name);
1131
            continue;
1132
        }
1133
1134
        if (doc) {
1135
            xmlNodePtr node;
1136
1137
            node = xmlDocGetRootElement(newdoc);
1138
            if (node) node = xmlFirstElementChild(node);
1139
            if (node) node = xmlDocCopyNodeList(doc, node);
1140
            xmlFreeDoc(newdoc);
1141
1142
            if ((!node)||(!xmlAddChildList(root, node))) {
1143
                xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
1144
                if (node) xmlFreeNode(node);
1145
                if (xmlerr) pcilib_error("Error manipulating XML tree of %s, libXML2 reported error %d - %s", file->d_name, xmlerr->code, xmlerr->message);
1146
                else pcilib_error("Error manipulating XML tree of %s", file->d_name);
1147
                continue;
1148
            }
1149
        } else {
1150
            root = xmlDocGetRootElement(newdoc);
1151
            if (!root) {
1152
                xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
1153
                xmlFreeDoc(newdoc);
1154
                if (xmlerr) pcilib_error("Error manipulating XML tree of %s, libXML2 reported error %d - %s", file->d_name, xmlerr->code, xmlerr->message);
1155
                else pcilib_error("Error manipulating XML tree of %s", file->d_name);
1156
                continue;
1157
            }
1158
            doc = newdoc;
1159
                // This is undocumented, but should be fine...
1160
            if (doc->URL) xmlFree((xmlChar*)doc->URL);
1161
            doc->URL = xmlStrdup(BAD_CAST model_path);
1162
        }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1163
    }
303 by Suren A. Chilingaryan
Initial integration of XML support
1164
    closedir(rep);
1165
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1166
    if (!doc)
1167
        return 0;
1168
1169
    err = xmlSchemaValidateDoc(ctx->xml.validator, doc);
1170
    if (err) {
1171
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
1172
        xmlFreeDoc(doc);
1173
        if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", model_path, xmlerr->code, xmlerr->message);
1174
        else pcilib_error("Error validating %s", model_path);
1175
        return PCILIB_ERROR_VERIFY;
1176
    }
1177
1178
    xpath = xmlXPathNewContext(doc);
1179
    if (!xpath) {
1180
        xmlErrorPtr xmlerr = xmlGetLastError();
1181
        xmlFreeDoc(doc);
1182
        if (xmlerr) pcilib_error("Document %s: xmlXpathNewContext reported error %d - %s for document %s", model_path, xmlerr->code, xmlerr->message);
1183
        else pcilib_error("Error creating XPath context for %s", model_path);
1184
        return PCILIB_ERROR_FAILED;
1185
    }
1186
1187
        // This can only partially fail... Therefore we need to keep XML and just return the error...
1188
    err = pcilib_xml_process_document(ctx, doc, xpath);
1189
1190
    ctx->xml.docs[ctx->xml.num_files] = doc;
1191
    ctx->xml.xpath[ctx->xml.num_files] = xpath;
1192
    ctx->xml.num_files++;
1193
1194
    return err;
1195
}
1196
1197
int pcilib_process_xml(pcilib_t *ctx, const char *location) {
1198
    return pcilib_process_xml_internal(ctx, NULL, location);
1199
}
1200
303 by Suren A. Chilingaryan
Initial integration of XML support
1201
int pcilib_init_xml(pcilib_t *ctx, const char *model) {
1202
    int err;
1203
1204
    char *model_dir;
1205
1206
    model_dir = getenv("PCILIB_MODEL_DIR");
1207
    if (!model_dir) model_dir = PCILIB_MODEL_DIR;
1208
1209
    ctx->xml.parser = xmlNewParserCtxt();
1210
    if (!ctx->xml.parser) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1211
        xmlErrorPtr xmlerr = xmlGetLastError();
1212
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
1213
        else pcilib_error("Failed to create an XML parser context");
1214
        return PCILIB_ERROR_FAILED;
303 by Suren A. Chilingaryan
Initial integration of XML support
1215
    }
1216
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1217
    err = pcilib_xml_load_xsd(ctx, model_dir);
303 by Suren A. Chilingaryan
Initial integration of XML support
1218
    if (err) return err;
1219
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1220
    return pcilib_process_xml_internal(ctx, model, NULL);
303 by Suren A. Chilingaryan
Initial integration of XML support
1221
}
1222
1223
void pcilib_free_xml(pcilib_t *ctx) {
1224
    int i;
1225
1226
    memset(ctx->xml.bank_nodes, 0, sizeof(ctx->xml.bank_nodes));
1227
    for (i = 0; i < ctx->num_banks; i++) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1228
        if (ctx->bank_ctx[i])
1229
            ctx->bank_ctx[i]->xml = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1230
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1231
303 by Suren A. Chilingaryan
Initial integration of XML support
1232
    for (i = 0; i < ctx->num_reg; i++) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1233
        ctx->register_ctx[i].xml = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1234
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1235
303 by Suren A. Chilingaryan
Initial integration of XML support
1236
    for (i = 0; i < ctx->xml.num_files; i++) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1237
        if (ctx->xml.docs[i]) {
1238
            xmlFreeDoc(ctx->xml.docs[i]);
1239
            ctx->xml.docs[i] = NULL;
1240
        }
1241
        if (ctx->xml.xpath[i]) {
1242
            xmlXPathFreeContext(ctx->xml.xpath[i]);
1243
            ctx->xml.xpath[i] = NULL;
1244
        }
303 by Suren A. Chilingaryan
Initial integration of XML support
1245
    }
1246
    ctx->xml.num_files = 0;
1247
1248
    if (ctx->xml.validator) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1249
        xmlSchemaFreeValidCtxt(ctx->xml.validator);
1250
        ctx->xml.validator = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1251
    }
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1252
303 by Suren A. Chilingaryan
Initial integration of XML support
1253
    if (ctx->xml.schema) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1254
        xmlSchemaFree(ctx->xml.schema);
1255
        ctx->xml.schema = NULL;
322 by Suren A. Chilingaryan
Support multiple XML files per folder
1256
    }
1257
1258
    if (ctx->xml.parts_validator) {
1259
        xmlSchemaFreeValidCtxt(ctx->xml.parts_validator);
1260
        ctx->xml.parts_validator = NULL;
1261
    }
1262
1263
    if (ctx->xml.parts_schema) {
1264
        xmlSchemaFree(ctx->xml.parts_schema);
1265
        ctx->xml.parts_schema = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1266
    }
1267
1268
    if (ctx->xml.parser) {
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1269
        xmlFreeParserCtxt(ctx->xml.parser);
1270
        ctx->xml.parser = NULL;
303 by Suren A. Chilingaryan
Initial integration of XML support
1271
    }
311 by Suren A. Chilingaryan
Implement enum view
1272
307 by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far)
1273
    /*
1274
        xmlSchemaCleanupTypes();
1275
        xmlCleanupParser();
1276
        xmlMemoryDump();
1277
    */
277.2.16 by zilio nicolas
end of modifications
1278
}
379 by Suren A. Chilingaryan
Support XML configuration of device models
1279
1280
1281
char *pcilib_detect_xml_model(pcilib_t *ctx, unsigned int vendor_id, unsigned int device_id) {
1282
    int err;
1283
    char *model = NULL;
1284
    xmlSchemaPtr schema;  				/**< Pointer to the parsed xsd schema */
1285
    xmlSchemaValidCtxtPtr validator;       		/**< Pointer to the XML validation context */
1286
    xmlParserCtxtPtr parser;				/**< Pointer to the XML parser context */
1287
1288
    DIR *rep;
1289
    struct dirent *file = NULL;
1290
    struct stat st;
1291
    const char *data_dir;
1292
    char *xsd_path, *xml_path;
1293
1294
    xmlXPathObjectPtr nodes;
1295
    xmlChar xpath_query[64];
1296
384 by Suren A. Chilingaryan
Fix device detection code
1297
    xmlStrPrintf(xpath_query, sizeof(xpath_query), (xmlChar*)"/devices/device[@vendor=\"%04x\" and @device=\"%04x\"]/@model", vendor_id, device_id);
379 by Suren A. Chilingaryan
Support XML configuration of device models
1298
1299
    data_dir = getenv("PCILIB_DATA_DIR");
1300
    if (!data_dir) data_dir = PCILIB_DATA_DIR;
1301
1302
    xsd_path = (char*)alloca(strlen(data_dir) + 32);
1303
    xml_path = (char*)alloca(strlen(data_dir) + 32);
1304
    if ((!xsd_path)||(!xml_path)) {
1305
	pcilib_error("Error allocating stack memory");
1306
	return NULL;
1307
    }
1308
1309
    sprintf(xsd_path, "%s/devices.xsd", data_dir);
1310
    sprintf(xml_path, "%s/devices", data_dir);
1311
    if (stat(xsd_path, &st)||stat(xml_path, &st)) {
1312
        pcilib_info("No XML devices are defined, missing devices schema or list");
1313
        return NULL;
1314
    }
1315
1316
    parser = xmlNewParserCtxt();
1317
    if (!parser) {
1318
        xmlErrorPtr xmlerr = xmlGetLastError();
1319
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
1320
        else pcilib_error("Failed to create an XML parser context");
1321
        return NULL;
1322
    }
1323
1324
    err = pcilib_xml_load_xsd_file(ctx, xsd_path, &schema, &validator);
1325
    if (err) {
1326
	xmlFreeParserCtxt(parser);
1327
	pcilib_error("Error (%i) parsing the device schema (%s)", err, xsd_path);
1328
	return NULL;
1329
    }
1330
1331
    rep = opendir(xml_path);
1332
    if (!rep) goto cleanup;
1333
1334
    while ((model == NULL)&&((file = readdir(rep)) != NULL)) {
1335
	xmlDocPtr doc;
1336
        
1337
        size_t len = strlen(file->d_name);
1338
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
1339
        if (file->d_type != DT_REG) continue;
1340
1341
	doc = pcilib_xml_load_file(ctx, parser, validator, xml_path, file->d_name);
1342
	if (!doc) continue;
1343
1344
	nodes = pcilib_xml_eval_xpath_expression(ctx, doc, xpath_query);
1345
	if (!nodes) {
1346
	    xmlFreeDoc(doc);
1347
	    continue;
1348
	}
1349
1350
	if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) {
1351
	    xmlNodePtr node = nodes->nodesetval->nodeTab[0];
1352
	    model = strdup((char*)node->children->content);
1353
	}
1354
1355
	xmlXPathFreeObject(nodes);
1356
	xmlFreeDoc(doc);
1357
    }
1358
    closedir(rep);
1359
1360
cleanup:    
1361
    xmlSchemaFree(schema);
1362
    xmlSchemaFreeValidCtxt(validator);
1363
    xmlFreeParserCtxt(parser);
1364
1365
    return model;
1366
}