/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to pcilib/xml.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-09-24 02:28:45 UTC
  • mfrom: (305.1.19 views)
  • Revision ID: csa@suren.me-20150924022845-p7hc8lh8v0q48g0r
Finalyze XML support and provide initial support for views (only descriptions so far)

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#include "register.h"
40
40
#include "xml.h"
41
41
#include "error.h"
42
 
 
43
 
#define BANKS_PATH ((xmlChar*)"/model/banks/bank/bank_description")                                             /**< path to complete nodes of banks.*/
44
 
//#define REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register")                                     /**< all standard registers nodes.*/
45
 
//#define BIT_REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register/registers_bits/register_bits")    /**< all bits registers nodes.*/
46
 
#define REGISTERS_PATH ((xmlChar*)"../registers/register")                      /**< all standard registers nodes.*/
47
 
#define BIT_REGISTERS_PATH ((xmlChar*)"./registers_bits/register_bits")         /**< all bits registers nodes.*/
48
 
 
49
 
static char *pcilib_xml_bank_default_format = "0x%lx";
 
42
#include "view.h"
 
43
#include "views/enum.h"
 
44
#include "views/transform.h"
 
45
 
 
46
 
 
47
#define BANKS_PATH ((xmlChar*)"/model/bank")                                    /**< path to complete nodes of banks */
 
48
#define REGISTERS_PATH ((xmlChar*)"./register")                                 /**< all standard registers nodes */
 
49
#define BIT_REGISTERS_PATH ((xmlChar*)"./field")                                /**< all bits registers nodes */
 
50
#define REGISTER_VIEWS_PATH ((xmlChar*)"./view")                                /**< supported register & field views */
 
51
#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform")                     /**< path to complete nodes of views */
 
52
#define ENUM_VIEWS_PATH ((xmlChar*)"/model/enum")                               /**< path to complete nodes of views */
 
53
#define ENUM_ELEMENTS_PATH ((xmlChar*)"./name")                                 /**< all elements in the enum */
 
54
#define UNITS_PATH ((xmlChar*)"/model/unit")                                    /**< path to complete nodes of units */
 
55
#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform")                          /**< all transforms of the unit */
 
56
 
 
57
 
 
58
 
 
59
static const char *pcilib_xml_bank_default_format = "0x%lx";
 
60
static const char *pcilib_xml_enum_view_unit = "name";
50
61
 
51
62
typedef struct {
52
63
    pcilib_register_description_t base;
59
70
    bank_node = node->parent->parent;
60
71
        // bank_description is always a first node according to the XSD schema
61
72
    return xmlFirstElementChild(bank_node);
62
 
    
 
73
 
63
74
}
64
75
 
65
76
static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr node) {
67
78
}
68
79
*/
69
80
 
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) {
 
82
    xmlAttr *cur;
 
83
    char *value, *name;
 
84
 
 
85
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
86
        if(!cur->children) continue;
 
87
        if(!xmlNodeIsText(cur->children)) continue;
 
88
 
 
89
        name = (char*)cur->name;
 
90
        value = (char*)cur->children->content;
 
91
 
 
92
        if (!strcasecmp(name, "name")) {
 
93
            desc->name = value;
 
94
        } else if (!strcasecmp(name, "view")) {
 
95
            desc->view = value;
 
96
        }
 
97
    }
 
98
 
 
99
    if (!desc->name)
 
100
        desc->name = desc->view;
 
101
 
 
102
    return 0;
 
103
}
 
104
 
 
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) {
 
106
    int err;
71
107
    pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc;
72
108
 
73
 
    xmlNodePtr cur;
 
109
    xmlXPathObjectPtr nodes;
 
110
    xmlNodeSetPtr nodeset;
 
111
 
 
112
    xmlAttrPtr cur;
74
113
    char *value, *name;
75
114
    char *endptr;
76
115
 
77
 
    for (cur = node->children; cur != NULL; cur = cur->next) {
78
 
        if (!cur->children) continue;
79
 
        if (!xmlNodeIsText(cur->children)) continue;
80
 
        
81
 
        name = (char*)cur->name;
 
116
 
 
117
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
118
        if (!cur->children) continue;
 
119
        if (!xmlNodeIsText(cur->children)) continue;
 
120
 
 
121
        name = (char*)cur->name;
82
122
        value = (char*)cur->children->content;
83
123
        if (!value) continue;
84
 
        
 
124
 
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;
90
 
            }
 
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;
 
130
            }
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;
97
 
            }
 
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;
 
137
            }
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;
104
 
            }
 
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;
 
144
            }
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;
111
 
            }
 
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;
 
151
            }
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;
118
 
            }
119
 
            xml_desc->min = min;
 
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;
 
158
            }
 
159
            xml_desc->min = min;
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;
125
 
            }
126
 
            xml_desc->max = max;
 
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;
 
165
            }
 
166
            xml_desc->max = max;
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;
132
172
            } else {
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;
137
 
                }
138
 
                desc->rwmask = mask;
139
 
            }
 
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;
 
177
                }
 
178
                desc->rwmask = mask;
 
179
            }
140
180
        } else if (!strcasecmp(name, "mode")) {
141
181
            if (!strcasecmp(value, "R")) {
142
182
                desc->mode = PCILIB_REGISTER_R;
151
191
            } else if (!strcasecmp(value, "W1C")) {
152
192
                desc->mode = PCILIB_REGISTER_W1C;
153
193
            } else {
154
 
                pcilib_error("Invalid access mode (%s) is specified in the XML register description", value);
155
 
                return PCILIB_ERROR_INVALID_DATA;
 
194
                pcilib_error("Invalid access mode (%s) is specified in the XML register description", value);
 
195
                return PCILIB_ERROR_INVALID_DATA;
156
196
            }
157
197
        } else if (!strcasecmp(name, "type")) {
158
198
            if (!strcasecmp(value, "fifo")) {
159
199
                desc->type = PCILIB_REGISTER_FIFO;
160
200
            } else {
161
 
                pcilib_error("Invalid register type (%s) is specified in the XML register description", value);
162
 
                return PCILIB_ERROR_INVALID_DATA;
 
201
                pcilib_error("Invalid register type (%s) is specified in the XML register description", value);
 
202
                return PCILIB_ERROR_INVALID_DATA;
163
203
            }
164
204
        } else if (!strcasecmp(name,"name")) {
165
205
            desc->name = value;
168
208
        }
169
209
    }
170
210
 
 
211
    xpath->node = node;
 
212
    nodes = xmlXPathEvalExpression(REGISTER_VIEWS_PATH, xpath);
 
213
    xpath->node = NULL;
 
214
 
 
215
    if (!nodes) {
 
216
        xmlErrorPtr xmlerr = xmlGetLastError();
 
217
 
 
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;
 
221
    }
 
222
 
 
223
 
 
224
    nodeset = nodes->nodesetval;
 
225
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
 
226
        int i;
 
227
 
 
228
        desc->views = (pcilib_view_reference_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t));
 
229
        if (!desc->views) {
 
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;
 
233
        }
 
234
 
 
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]);
 
238
            if (err) {
 
239
                xmlXPathFreeObject(nodes);
 
240
                return err;
 
241
            }
 
242
        }
 
243
    }
 
244
    xmlXPathFreeObject(nodes);
 
245
 
171
246
    return 0;
172
247
}
173
248
 
174
249
static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
175
250
    int err;
176
 
    
177
251
    xmlXPathObjectPtr nodes;
178
252
    xmlNodeSetPtr nodeset;
179
253
 
180
254
    pcilib_xml_register_description_t desc = {{0}};
181
255
    pcilib_xml_register_description_t fdesc;
182
 
    
 
256
 
183
257
    pcilib_register_t reg;
184
 
    
 
258
 
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;
189
 
    
190
 
    err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank]);
 
263
 
 
264
    err = pcilib_xml_parse_register(ctx, &desc, xpath, doc, node, &ctx->banks[bank]);
191
265
    if (err) {
192
 
        pcilib_error("Error (%i) parsing an XML register", err);
193
 
        return err;
 
266
        pcilib_error("Error (%i) parsing an XML register", err);
 
267
        return err;
194
268
    }
195
 
    
 
269
 
196
270
    err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &desc.base, &reg);
197
271
    if (err) {
198
 
        pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name);
199
 
        return err;
 
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);
 
274
        return err;
200
275
    }
201
276
 
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;
 
281
 
205
282
 
206
283
    xpath->node = node;
207
284
    nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath);
208
285
    xpath->node = NULL;
209
 
    
 
286
 
210
287
    if (!nodes) {
211
 
        xmlErrorPtr xmlerr = xmlGetLastError();
 
288
        xmlErrorPtr xmlerr = xmlGetLastError();
212
289
 
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;
216
293
    }
217
294
 
218
295
    nodeset = nodes->nodesetval;
219
296
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
220
 
        int i;
221
 
        
222
 
        for (i = 0; i < nodeset->nodeNr; i++) {
223
 
            memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t));
224
 
 
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;
230
 
            
231
 
            err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank]);
232
 
            if (err) {
233
 
                pcilib_error("Error parsing field in the XML register %s", desc.base.name);
234
 
                continue;
235
 
            }
236
 
            
237
 
            err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, &reg);
238
 
            if (err) {
239
 
                pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name);
240
 
                continue;
241
 
            }
242
 
            
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;
246
 
        }
 
297
        int i;
 
298
 
 
299
        for (i = 0; i < nodeset->nodeNr; i++) {
 
300
            memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t));
 
301
 
 
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;
 
307
 
 
308
            err = pcilib_xml_parse_register(ctx, &fdesc, xpath, doc, nodeset->nodeTab[i], &ctx->banks[bank]);
 
309
            if (err) {
 
310
                pcilib_error("Error parsing field in the XML register %s", desc.base.name);
 
311
                continue;
 
312
            }
 
313
 
 
314
            err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, &reg);
 
315
            if (err) {
 
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);
 
318
                continue;
 
319
            }
 
320
 
 
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;
 
325
        }
247
326
    }
248
327
    xmlXPathFreeObject(nodes);
249
328
 
252
331
 
253
332
static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
254
333
    int err;
255
 
    
 
334
 
256
335
    int override = 0;
257
336
    pcilib_register_bank_description_t desc = {0};
258
337
    pcilib_register_bank_t bank;
259
 
    xmlNodePtr cur;
 
338
    xmlAttrPtr cur;
260
339
    char *value, *name;
261
340
    char *endptr;
262
341
 
273
352
    desc.endianess = PCILIB_HOST_ENDIAN;
274
353
    desc.raw_endianess = PCILIB_HOST_ENDIAN;
275
354
 
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;
280
 
        
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;
 
359
 
 
360
        name = (char*)cur->name;
282
361
        value = (char*)cur->children->content;
283
362
        if (!value) continue;
284
 
        
 
363
 
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;
290
 
            }
 
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;
 
369
            }
291
370
            desc.bar = (pcilib_bar_t)bar;
292
371
            override = 1;
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;
298
 
            }
 
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;
 
377
            }
299
378
            desc.size = (size_t)size;
300
379
            override = 1;
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;
306
 
            }
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;
 
385
            }
 
386
            desc.protocol = ctx->protocols[protocol].addr;
308
387
            override = 1;
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;
314
 
            }
 
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;
 
393
            }
315
394
            desc.read_addr = addr;
316
395
            desc.write_addr = addr;
317
396
            override = 1;
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;
323
 
            }
 
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;
 
402
            }
324
403
            desc.read_addr = addr;
325
404
            override = 1;
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;
331
 
            }
 
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;
 
410
            }
332
411
            desc.write_addr = addr;
333
412
            override = 1;
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;
339
 
            }
 
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;
 
418
            }
340
419
            desc.access = access;
341
420
            override = 1;
342
421
        } else if (!strcasecmp(name,"endianess")) {
344
423
            else if (!strcasecmp(value,"big")) desc.endianess = PCILIB_BIG_ENDIAN;
345
424
            else if (!strcasecmp(value,"host")) desc.endianess = PCILIB_HOST_ENDIAN;
346
425
            else {
347
 
                pcilib_error("Invalid endianess (%s) is specified in the XML bank description", value);
348
 
                return PCILIB_ERROR_INVALID_DATA;        
 
426
                pcilib_error("Invalid endianess (%s) is specified in the XML bank description", value);
 
427
                return PCILIB_ERROR_INVALID_DATA;
349
428
            }
350
429
            override = 1;
351
430
        } else if (!strcasecmp(name,"format")) {
357
436
            desc.description = value;
358
437
            override = 1;
359
438
        } else if (!strcasecmp((char*)name,"override")) {
360
 
            override = 1;
 
439
            override = 1;
361
440
        }
362
441
    }
363
442
 
369
448
 
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;
373
452
    }
374
453
 
375
454
    xpath->node = node;
376
455
    nodes = xmlXPathEvalExpression(REGISTERS_PATH, xpath);
377
456
    xpath->node = NULL;
 
457
 
 
458
    if (!nodes) {
 
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;
 
463
    }
 
464
 
 
465
    nodeset = nodes->nodesetval;
 
466
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
 
467
        int i;
 
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);
 
471
        }
 
472
    }
 
473
    xmlXPathFreeObject(nodes);
 
474
 
 
475
    return 0;
 
476
}
 
477
 
 
478
static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_view_description_t *desc) {
 
479
    xmlAttrPtr cur;
 
480
    const char *value, *name;
 
481
 
 
482
    desc->type = PCILIB_TYPE_STRING;
 
483
 
 
484
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
485
        if (!cur->children) continue;
 
486
        if (!xmlNodeIsText(cur->children)) continue;
 
487
 
 
488
        name = (char*)cur->name;
 
489
        value = (char*)cur->children->content;
 
490
        if (!value) continue;
 
491
 
 
492
        if (!strcasecmp(name, "name")) {
 
493
            desc->name = value;
 
494
        } else if (!strcasecmp((char*)name, "description")) {
 
495
            desc->description = value;
 
496
        } else if (!strcasecmp((char*)name, "unit")) {
 
497
            desc->unit = value;
 
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;
 
502
            else {
 
503
                pcilib_error("Invalid type (%s) of register view is specified in the XML bank description", value);
 
504
                return PCILIB_ERROR_INVALID_DATA;
 
505
            }
 
506
        }
 
507
    }
 
508
 
 
509
    return 0;
 
510
}
 
511
 
 
512
static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
 
513
    int err;
 
514
    xmlAttrPtr cur;
 
515
    const char *value, *name;
 
516
 
 
517
    pcilib_transform_view_description_t desc = {0};
 
518
 
 
519
    desc.base.api = &pcilib_enum_view_xml_api;
 
520
 
 
521
    err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
 
522
    if (err) return err;
 
523
 
 
524
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
525
        if (!cur->children) continue;
 
526
        if (!xmlNodeIsText(cur->children)) continue;
 
527
 
 
528
        name = (char*)cur->name;
 
529
        value = (char*)cur->children->content;
 
530
        if (!value) continue;
 
531
 
 
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;
 
536
        } 
 
537
    }
 
538
 
 
539
 
 
540
    return pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
 
541
}
 
542
 
 
543
 
 
544
static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_value_name_t *desc) {
 
545
    xmlAttr *cur;
 
546
    char *value, *name;
 
547
    char *endptr;
 
548
 
 
549
    int min_set = 0, max_set = 0;
 
550
    pcilib_register_value_t val;
378
551
    
379
 
    if (!nodes) {
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;
 
555
 
 
556
        name = (char*)cur->name;
 
557
        value = (char*)cur->children->content;
 
558
 
 
559
        if (!strcasecmp(name, "name")) {
 
560
            desc->name = value;
 
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;
 
566
            }
 
567
            desc->value = val;
 
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;
 
573
            }
 
574
            desc->min = val;
 
575
            min_set = 1;
 
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;
 
581
            }
 
582
            desc->max = val;
 
583
            max_set = 1;
 
584
        }
 
585
    }
 
586
 
 
587
    if ((!min_set)&&(!max_set)) {
 
588
        desc->min = desc->value;
 
589
        desc->max = desc->value;
 
590
    } else if (max_set) {
 
591
        desc->min = 0;
 
592
    } else if (min_set) {
 
593
        desc->max = (pcilib_register_value_t)-1;
 
594
    }
 
595
 
 
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;
 
599
    }
 
600
 
 
601
    return 0;
 
602
}
 
603
 
 
604
static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
 
605
    int i;
 
606
    int err;
 
607
 
 
608
    xmlXPathObjectPtr nodes;
 
609
    xmlNodeSetPtr nodeset;
 
610
 
 
611
    pcilib_enum_view_description_t desc = {0};
 
612
 
 
613
    desc.base.unit = pcilib_xml_enum_view_unit;
 
614
    desc.base.api = &pcilib_enum_view_xml_api;
 
615
 
 
616
    err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);
 
617
    if (err) return err;
 
618
 
 
619
 
 
620
    xpath->node = node;
 
621
    nodes = xmlXPathEvalExpression(ENUM_ELEMENTS_PATH, xpath);
 
622
    xpath->node = NULL;
 
623
 
 
624
    if (!nodes) {
 
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;
 
629
    }
 
630
 
 
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; 
 
636
    }
 
637
 
 
638
    desc.names = (pcilib_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_value_name_t));
 
639
    if (!desc.names) {
 
640
        xmlXPathFreeObject(nodes);
 
641
        pcilib_error("No names is defined for enum view (%s)", desc.base.name);
 
642
        return PCILIB_ERROR_INVALID_DATA; 
 
643
    }
 
644
 
 
645
 
 
646
    for (i = 0; i < nodeset->nodeNr; i++) {
 
647
        err = pcilib_xml_parse_value_name(ctx, xpath, doc, nodeset->nodeTab[i], &desc.names[i]);
 
648
        if (err) {
 
649
            xmlXPathFreeObject(nodes);
 
650
            free(desc.names);
 
651
            return err;
 
652
        }
 
653
    }
 
654
    memset(&desc.names[nodeset->nodeNr], 0, sizeof(pcilib_value_name_t));
 
655
 
 
656
    xmlXPathFreeObject(nodes);
 
657
 
 
658
 
 
659
    err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
 
660
    if (err) free(desc.names);
 
661
    return err;
 
662
}
 
663
 
 
664
static int pcilib_xml_parse_unit_transform(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_unit_transform_t *desc) {
 
665
    xmlAttrPtr cur;
 
666
    char *value, *name;
 
667
 
 
668
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
669
        if (!cur->children) continue;
 
670
        if (!xmlNodeIsText(cur->children)) continue;
 
671
 
 
672
        name = (char*)cur->name;
 
673
        value = (char*)cur->children->content;
 
674
 
 
675
        if (!strcasecmp(name, "unit")) {
 
676
            desc->unit = value;
 
677
        } else if (!strcasecmp(name, "transform")) {
 
678
            desc->transform = value;
 
679
        }
 
680
    }
 
681
 
 
682
    return 0;
 
683
}
 
684
 
 
685
/**
 
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
 
692
 */
 
693
static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {
 
694
    int err;
 
695
 
 
696
    pcilib_unit_description_t desc = {0};
 
697
 
 
698
    xmlXPathObjectPtr nodes;
 
699
    xmlNodeSetPtr nodeset;
 
700
 
 
701
    xmlAttrPtr cur;
 
702
    char *value, *name;
 
703
 
 
704
    for (cur = node->properties; cur != NULL; cur = cur->next) {
 
705
        if (!cur->children) continue;
 
706
        if (!xmlNodeIsText(cur->children)) continue;
 
707
 
 
708
        name = (char*)cur->name;
 
709
        value = (char*)cur->children->content;
 
710
        if (!strcasecmp(name, "name")) {
 
711
            desc.name = value;
 
712
        }
 
713
    }
 
714
 
 
715
    xpath->node = node;
 
716
    nodes = xmlXPathEvalExpression(UNIT_TRANSFORMS_PATH, xpath);
 
717
    xpath->node = NULL;
 
718
 
 
719
    if (!nodes) {
 
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;
384
724
    }
385
725
 
386
726
    nodeset = nodes->nodesetval;
387
727
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
388
728
        int i;
 
729
    
 
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;
 
734
        }
 
735
        
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]);
 
738
            if (err) {
 
739
                xmlXPathFreeObject(nodes);
 
740
                return err;
 
741
            }
392
742
        }
393
743
    }
394
744
    xmlXPathFreeObject(nodes);
395
745
 
396
 
    return 0;
 
746
    return pcilib_add_units(ctx, 1, &desc);
397
747
}
398
748
 
399
749
 
405
755
 * @param[in] pci the pcilib_t running, which will be filled
406
756
 */
407
757
static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) {
408
 
    xmlXPathObjectPtr bank_nodes;
 
758
    int err;
 
759
    xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL;
409
760
    xmlNodeSetPtr nodeset;
410
 
 
411
 
    bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); 
412
 
    if (!bank_nodes) {
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;
417
 
    }
418
 
 
 
761
    int i;
 
762
 
 
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);
 
767
 
 
768
    if (!unit_nodes) {
 
769
        const unsigned char *expr = (enum_nodes?UNITS_PATH:(transform_nodes?ENUM_VIEWS_PATH:(bank_nodes?TRANSFORM_VIEWS_PATH:BANKS_PATH)));
 
770
 
 
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;
 
778
    }
 
779
 
 
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);
 
785
        }
 
786
    }
 
787
 
 
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);
 
793
        }
 
794
    }
 
795
 
 
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);
 
801
        }
 
802
    }
419
803
 
420
804
    nodeset = bank_nodes->nodesetval;
421
805
    if (!xmlXPathNodeSetIsEmpty(nodeset)) {
422
 
        int i;
423
 
        for (i = 0; i < nodeset->nodeNr; i++) {
424
 
            pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]);
425
 
        }
 
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);
 
809
        }
426
810
    }
 
811
 
 
812
 
 
813
    xmlXPathFreeObject(unit_nodes);
 
814
    xmlXPathFreeObject(enum_nodes);
 
815
    xmlXPathFreeObject(transform_nodes);
427
816
    xmlXPathFreeObject(bank_nodes);
428
 
    
 
817
 
429
818
    return 0;
430
819
}
431
820
 
432
821
static int pcilib_xml_load_xsd(pcilib_t *ctx, char *xsd_filename) {
433
822
    int err;
434
 
    
 
823
 
435
824
    xmlSchemaParserCtxtPtr ctxt;
436
825
 
437
826
    /** we first parse the xsd file for AST with validation*/
438
827
    ctxt = xmlSchemaNewParserCtxt(xsd_filename);
439
828
    if (!ctxt) {
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;
444
833
    }
445
 
    
 
834
 
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;
453
842
    }
454
 
    
 
843
 
455
844
    xmlSchemaFreeParserCtxt(ctxt);
456
845
 
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;
463
852
    }
464
 
    
 
853
 
465
854
    err = xmlSchemaSetValidOptions(ctx->xml.validator, XML_SCHEMA_VAL_VC_I_CREATE);
466
855
    if (err) {
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;
471
860
    }
472
861
 
473
862
    return 0;
481
870
 
482
871
    full_name = (char*)alloca(strlen(path) + strlen(name) + 2);
483
872
    if (!name) {
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;
486
875
    }
487
876
 
488
877
    sprintf(full_name, "%s/%s", path, name);
489
878
 
490
879
    doc = xmlCtxtReadFile(ctx->xml.parser, full_name, NULL, 0);
491
880
    if (!doc) {
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;
496
885
    }
497
886
 
498
887
    err = xmlSchemaValidateDoc(ctx->xml.validator, doc);
499
888
    if (err) {
500
 
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
501
 
        xmlFreeDoc(doc);
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);
 
890
        xmlFreeDoc(doc);
 
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;
505
894
    }
506
895
 
507
896
    xpath = xmlXPathNewContext(doc);
508
897
    if (!xpath) {
509
 
        xmlErrorPtr xmlerr = xmlGetLastError();
510
 
        xmlFreeDoc(doc);
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();
 
899
        xmlFreeDoc(doc);
 
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;
514
903
    }
515
904
 
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);
518
907
 
519
908
    if (ctx->xml.num_files == PCILIB_MAX_MODEL_FILES) {
520
 
        xmlFreeDoc(doc);
 
909
        xmlFreeDoc(doc);
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;
524
913
    }
525
914
 
526
915
    ctx->xml.docs[ctx->xml.num_files] = doc;
550
939
    if (!rep) return PCILIB_ERROR_NOTFOUND;
551
940
 
552
941
    while ((file = readdir(rep)) != NULL) {
553
 
        size_t len = strlen(file->d_name);
554
 
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
555
 
        if (file->d_type != DT_REG) continue;
556
 
        
557
 
        err = pcilib_xml_load_file(ctx, model_path, file->d_name);
558
 
        if (err) pcilib_error("Error processing XML file %s", file->d_name);
 
942
        size_t len = strlen(file->d_name);
 
943
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
 
944
        if (file->d_type != DT_REG) continue;
 
945
 
 
946
        err = pcilib_xml_load_file(ctx, model_path, file->d_name);
 
947
        if (err) pcilib_error("Error processing XML file %s", file->d_name);
559
948
    }
560
949
 
561
950
    closedir(rep);
586
975
 
587
976
    sprintf(xsd_path, "%s/model.xsd", model_dir);
588
977
    if (stat(xsd_path, &st)) {
589
 
        pcilib_info("XML models are not present");
590
 
        return PCILIB_ERROR_NOTFOUND;
 
978
        pcilib_info("XML models are not present");
 
979
        return PCILIB_ERROR_NOTFOUND;
591
980
    }
592
981
 
593
982
    ctx->xml.parser = xmlNewParserCtxt();
594
983
    if (!ctx->xml.parser) {
595
 
        xmlErrorPtr xmlerr = xmlGetLastError();
596
 
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
597
 
        else pcilib_error("Failed to create an XML parser context");
598
 
        return PCILIB_ERROR_FAILED;
 
984
        xmlErrorPtr xmlerr = xmlGetLastError();
 
985
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
 
986
        else pcilib_error("Failed to create an XML parser context");
 
987
        return PCILIB_ERROR_FAILED;
599
988
    }
600
989
 
601
990
    err = pcilib_xml_load_xsd(ctx, xsd_path);
613
1002
 
614
1003
    memset(ctx->xml.bank_nodes, 0, sizeof(ctx->xml.bank_nodes));
615
1004
    for (i = 0; i < ctx->num_banks; i++) {
616
 
        if (ctx->bank_ctx[i]) 
617
 
            ctx->bank_ctx[i]->xml = NULL;
 
1005
        if (ctx->bank_ctx[i])
 
1006
            ctx->bank_ctx[i]->xml = NULL;
618
1007
    }
619
 
    
 
1008
 
620
1009
    for (i = 0; i < ctx->num_reg; i++) {
621
 
        ctx->register_ctx[i].xml = NULL;
 
1010
        ctx->register_ctx[i].xml = NULL;
622
1011
    }
623
 
    
 
1012
 
624
1013
    for (i = 0; i < ctx->xml.num_files; i++) {
625
 
        if (ctx->xml.docs[i]) {
626
 
            xmlFreeDoc(ctx->xml.docs[i]);
627
 
            ctx->xml.docs[i] = NULL;
628
 
        }
629
 
        if (ctx->xml.xpath[i]) {
630
 
            xmlXPathFreeContext(ctx->xml.xpath[i]);
631
 
            ctx->xml.xpath[i] = NULL;
632
 
        }
 
1014
        if (ctx->xml.docs[i]) {
 
1015
            xmlFreeDoc(ctx->xml.docs[i]);
 
1016
            ctx->xml.docs[i] = NULL;
 
1017
        }
 
1018
        if (ctx->xml.xpath[i]) {
 
1019
            xmlXPathFreeContext(ctx->xml.xpath[i]);
 
1020
            ctx->xml.xpath[i] = NULL;
 
1021
        }
633
1022
    }
634
1023
    ctx->xml.num_files = 0;
635
1024
 
636
1025
    if (ctx->xml.validator) {
637
 
        xmlSchemaFreeValidCtxt(ctx->xml.validator);
638
 
        ctx->xml.validator = NULL;
 
1026
        xmlSchemaFreeValidCtxt(ctx->xml.validator);
 
1027
        ctx->xml.validator = NULL;
639
1028
    }
640
 
    
 
1029
 
641
1030
    if (ctx->xml.schema) {
642
 
        xmlSchemaFree(ctx->xml.schema);
643
 
        ctx->xml.schema = NULL;
644
 
    
 
1031
        xmlSchemaFree(ctx->xml.schema);
 
1032
        ctx->xml.schema = NULL;
 
1033
 
645
1034
    }
646
1035
 
647
1036
    if (ctx->xml.parser) {
648
 
        xmlFreeParserCtxt(ctx->xml.parser);
649
 
        ctx->xml.parser = NULL;
 
1037
        xmlFreeParserCtxt(ctx->xml.parser);
 
1038
        ctx->xml.parser = NULL;
650
1039
    }
651
 
/*
652
 
    xmlSchemaCleanupTypes();
653
 
    xmlCleanupParser();
654
 
    xmlMemoryDump();
655
 
*/
 
1040
    /*
 
1041
        xmlSchemaCleanupTypes();
 
1042
        xmlCleanupParser();
 
1043
        xmlMemoryDump();
 
1044
    */
656
1045
}