25
31
#include <libxml/parser.h>
26
32
#include <libxml/xpath.h>
27
33
#include <libxml/xpathInternals.h>
29
34
#include <dirent.h>
33
* this function takes a string and will create an abtract syntax tree from the xml file represented by the string
34
* @param[in] filename the the name of the xml file containing registers and banks
37
pcilib_xml_getdoc(char* filename){
39
doc=xmlParseFile(filename); /**<the creation of the AST from a libxml2 funtion*/
42
pcilib_error("xml document not parsed successfully");
49
/** pcilib_xml_getsetproperty
37
/** pcilib_xml_get_nodeset_from_xpath
50
38
* this function takes a context from an AST and an XPath expression, to produce an object containing the nodes corresponding to the xpath expression
51
39
* @param[in] doc the AST of the xml file
52
40
* @param[in] xpath the xpath expression that will be evaluated
41
*@return the nodeset from AST and xpath expression evaluation of the xml file
54
43
static xmlXPathObjectPtr
55
pcilib_xml_getsetproperty(xmlXPathContextPtr doc, xmlChar *xpath){
44
pcilib_xml_get_nodeset_from_xpath(xmlXPathContextPtr doc, xmlChar *xpath){
56
45
xmlXPathObjectPtr result;
57
46
result=xmlXPathEvalExpression(xpath, doc); /**<the creation of the resulting object*/
48
pcilib_error("can't parse xpath expression %s",(char*)xpath);
62
52
if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
63
xmlXPathFreeObject(result);
53
pcilib_warning("the parsing of %s xpath expression resulted in an empty nodeset",(char*)xpath);
54
xmlXPathFreeObject(result);
70
/** pcilib_xml_getcontext.
71
* this function create a context in an AST (ie initialize XPAth for the AST).
72
* @param[in] doc the AST of the xml file.
62
/**pcilib_xml_get_bank_node_from_register_node
63
* this function get the bank xml node from a standards register xml node in the xml file
64
*@param[in] mynode the register node we want to know the bank
65
*@return the bank node
74
static xmlXPathContextPtr
75
pcilib_xml_getcontext(xmlDocPtr doc){
76
xmlXPathContextPtr context;
77
context= xmlXPathNewContext(doc); /**<the creation of the context using a libxml2's function */
79
pcilib_error("warning : no context obtained for the xml document");
68
pcilib_xml_get_bank_node_from_register_node(xmlNodePtr mynode){
69
return xmlFirstElementChild(xmlFirstElementChild(mynode->parent->parent));
74
/** pcilib_xml_validate
87
75
* function to validate the xml file against the xsd
88
76
* @param[in] xml_filename path to the xml file
89
77
* @param[in] xsd_filename path to the xsd file
78
*@return an error code
92
validation(char* xml_filename, char* xsd_filename)
81
pcilib_xml_validate(char* xml_filename, char* xsd_filename)
95
84
xmlSchemaPtr schema = NULL;
149
141
/** we get each time the name of the node, corresponding to one property, and the value of the node*/
150
142
value=xmlNodeListGetString(doc,cur->children,1);
152
if(strcmp((char*)cur->name,"adress")==0){
153
if (strcmp((char*)value,"bank 0")==0){
154
mybank->addr=PCILIB_REGISTER_BANK0;
155
}else if (strcmp((char*)value,"bank 1")==0){
156
mybank->addr=PCILIB_REGISTER_BANK1;
157
}else if (strcmp((char*)value,"bank 2")==0){
158
mybank->addr=PCILIB_REGISTER_BANK2;
159
}else if (strcmp((char*)value,"bank 3")==0){
160
mybank->addr=PCILIB_REGISTER_BANK3;
161
}else if (strcmp((char*)value,"DMA bank")==0){
162
mybank->addr=PCILIB_REGISTER_BANK_DMA;
163
}else if (strcmp((char*)value,"DMAconf bank")==0){
164
mybank->addr=PCILIB_REGISTER_BANK_DMACONF;
165
}else if (strcmp((char*)value,"dynamic bank")==0){
166
mybank->addr=PCILIB_REGISTER_BANK_DYNAMIC;
168
mybank->addr=PCILIB_REGISTER_BANK_INVALID;
144
if(strcasecmp((char*)cur->name,"bar")==0){
145
mybank->bar=(pcilib_bar_t)(value[0]-'0');
171
}else if(strcmp((char*)cur->name,"bar")==0){
172
if(strcmp((char*)value,"0")==0){
173
mybank->bar=PCILIB_BAR0;
174
}else if(strcmp((char*)value,"1")==0){
175
mybank->bar=PCILIB_BAR1;
176
}else if(strcmp((char*)value,"no_bar")==0){
177
mybank->bar=PCILIB_BAR_NOBAR;
179
mybank->bar=PCILIB_BAR_INVALID;
181
mybank->bar=(pcilib_bar_t)strtol((char*)value,&ptr,0);
183
}else if(strcmp((char*)cur->name,"size")==0){
148
}else if(strcasecmp((char*)cur->name,"size")==0){
184
149
mybank->size=(size_t)strtol((char*)value,&ptr,0);
186
}else if(strcmp((char*)cur->name,"protocol")==0){
187
if(strcmp((char*)value,"default")==0){
188
mybank->protocol=PCILIB_REGISTER_PROTOCOL_DEFAULT;
189
}else if(strcmp((char*)value,"0")==0){
190
mybank->protocol=PCILIB_REGISTER_PROTOCOL0;
191
}else if(strcmp((char*)value,"dma")==0){
192
mybank->protocol=PCILIB_REGISTER_PROTOCOL_DMA;
193
}else if(strcmp((char*)value,"dynamic")==0){
194
mybank->protocol=PCILIB_REGISTER_PROTOCOL_DYNAMIC;
195
}else if (strcmp((char*)value,"software")==0){
196
mybank->protocol=PCILIB_REGISTER_PROTOCOL_SOFTWARE;
197
}else mybank->protocol=PCILIB_REGISTER_PROTOCOL_INVALID;
199
}else if(strcmp((char*)cur->name,"read_adress")==0){
151
}else if(strcasecmp((char*)cur->name,"protocol")==0){
152
while(pci->protocols[k].name!=NULL){
153
if(strcasecmp(pci->protocols[k].name,(char*)value)==0){
154
mybank->protocol=pci->protocols[k].addr;
160
}else if(strcasecmp((char*)cur->name,"read_address")==0){
200
161
mybank->read_addr=(uintptr_t)strtol((char*)value,&ptr,0);
202
}else if(strcmp((char*)cur->name,"write_adress")==0){
163
}else if(strcasecmp((char*)cur->name,"write_address")==0){
203
164
mybank->write_addr=(uintptr_t)strtol((char*)value,&ptr,0);
205
}else if(strcmp((char*)cur->name,"word_size")==0){
166
}else if(strcasecmp((char*)cur->name,"word_size")==0){
206
167
mybank->access=(uint8_t)strtol((char*)value,&ptr,0);
208
}else if(strcmp((char*)cur->name,"endianess")==0){
209
if(strcmp((char*)value,"little")==0){
169
}else if(strcasecmp((char*)cur->name,"endianess")==0){
170
if(strcasecmp((char*)value,"little")==0){
210
171
mybank->endianess=PCILIB_LITTLE_ENDIAN;
211
}else if(strcmp((char*)value,"big")==0){
172
}else if(strcasecmp((char*)value,"big")==0){
212
173
mybank->endianess=PCILIB_BIG_ENDIAN;
213
}else if(strcmp((char*)value,"host")==0){
174
}else if(strcasecmp((char*)value,"host")==0){
214
175
mybank->endianess=PCILIB_HOST_ENDIAN;
216
177
mybank->raw_endianess=mybank->endianess;
218
}else if(strcmp((char*)cur->name,"format")==0){
179
}else if(strcasecmp((char*)cur->name,"format")==0){
219
180
mybank->format=(char*)value;
221
}else if(strcmp((char*)cur->name,"name")==0){
182
}else if(strcasecmp((char*)cur->name,"name")==0){
222
183
mybank->name=(char*)value;
224
}else if(strcmp((char*)cur->name,"description")==0){
185
}else if(strcasecmp((char*)cur->name,"description")==0){
225
186
mybank->description=(char*)value;
192
if(bar_ok==0) mybank->bar=PCILIB_BAR_NOBAR;
194
while(pci->banks[k].name!=NULL){
195
if(strcasecmp(pci->banks[k].name,mybank->name)==0){
196
mybank->addr=pci->banks[k].addr;
203
mybank->addr=PCILIB_REGISTER_BANK_DYNAMIC + i;
206
pci->xml_banks[k]=mynode;
242
219
pcilib_xml_initialize_banks(pcilib_t* pci,xmlDocPtr doc){
243
220
pcilib_register_bank_description_t mybank;
245
xmlNodeSetPtr nodesetadress=NULL;
222
xmlNodeSetPtr nodesetaddress=NULL;
246
223
xmlNodePtr mynode;
247
224
xmlXPathContextPtr context;
250
227
mynode=malloc(sizeof(xmlNode));
251
context=pcilib_xml_getcontext(doc);
228
if(!(context= xmlXPathNewContext(doc))){
229
pcilib_error("can't get an AST from an xml file");
253
232
/** we get the bank nodes using xpath expression*/
254
nodesetadress=pcilib_xml_getsetproperty(context,BANKS_PATH)->nodesetval;
255
if(nodesetadress->nodeNr==0) return;
233
nodesetaddress=pcilib_xml_get_nodeset_from_xpath(context,BANKS_PATH)->nodesetval;
234
if(!(nodesetaddress)) return;
235
if(nodesetaddress->nodeNr==0) return;
257
pci->banks_xml_nodes=calloc(nodesetadress->nodeNr,sizeof(xmlNodePtr));
258
if(!(pci->banks_xml_nodes)) pcilib_error("can't create bank xml nodes for pcilib_t struct");
237
pci->xml_banks=calloc(PCILIB_MAX_REGISTER_BANKS+1,sizeof(xmlNodePtr));
238
if(!(pci->xml_banks)) pcilib_error("can't create bank xml nodes for pcilib_t struct");
260
240
/** for each of the bank nodes, we create the associated structure, and push it in the pcilib environnement*/
261
for(i=0;i<nodesetadress->nodeNr;i++){
262
mynode=nodesetadress->nodeTab[i];
263
pcilib_xml_create_bank(&mybank,mynode,doc);
241
for(i=0;i<nodesetaddress->nodeNr;i++){
242
mynode=nodesetaddress->nodeTab[i];
243
pcilib_xml_create_bank(&mybank,mynode,doc, pci);
264
244
pcilib_add_register_banks(pci,1,&mybank);
265
pci->banks_xml_nodes[i]=mynode;
271
250
/** pcilib_xml_registers_compare
272
* function to compare registers by adress for sorting registers
251
* function to compare registers by address for sorting registers
273
252
* @param a one hypothetic register
274
253
* @param b one other hypothetic register
254
*@return the result of the comparison
277
257
pcilib_xml_compare_registers(void const *a, void const *b){
317
297
/* we iterate throug each children to get the associated property
318
298
note :the use of strtol permits to get as well hexadecimal and decimal values
320
if(strcmp((char*)cur->name,"adress")==0){
300
if(strcasecmp((char*)cur->name,"address")==0){
321
301
myregister->addr=(pcilib_register_addr_t)strtol((char*)value,&ptr,0);
323
}else if(strcmp((char*)cur->name,"offset")==0){
303
}else if(strcasecmp((char*)cur->name,"offset")==0){
324
304
myregister->offset=(pcilib_register_size_t)strtol((char*)value,&ptr,0);
326
}else if(strcmp((char*)cur->name,"size")==0){
306
}else if(strcasecmp((char*)cur->name,"size")==0){
327
307
myregister->bits=(pcilib_register_size_t)strtol((char*)value,&ptr,0);
329
}else if(strcmp((char*)cur->name,"default")==0){
309
}else if(strcasecmp((char*)cur->name,"default")==0){
330
310
myregister->defvalue=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
332
}else if(strcmp((char*)cur->name,"rwmask")==0){
333
if(strcmp((char*)value,"all bits")==0){
312
}else if(strcasecmp((char*)cur->name,"rwmask")==0){
313
if(strcasecmp((char*)value,"all bits")==0){
334
314
myregister->rwmask=PCILIB_REGISTER_ALL_BITS;
335
}else if(strcmp((char*)value,"0")==0){
315
}else if(strcasecmp((char*)value,"0")==0){
336
316
myregister->rwmask=0;
338
318
myregister->rwmask=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
341
}else if(strcmp((char*)cur->name,"mode")==0){
342
if(strcmp((char*)value,"R")==0){
321
}else if(strcasecmp((char*)cur->name,"mode")==0){
322
if(strcasecmp((char*)value,"R")==0){
343
323
myregister->mode=PCILIB_REGISTER_R;
344
}else if(strcmp((char*)value,"W")==0){
324
}else if(strcasecmp((char*)value,"W")==0){
345
325
myregister->mode=PCILIB_REGISTER_W;
346
}else if(strcmp((char*)value,"RW")==0){
326
}else if(strcasecmp((char*)value,"RW")==0){
347
327
myregister->mode=PCILIB_REGISTER_RW;
348
}else if(strcmp((char*)value,"W")==0){
328
}else if(strcasecmp((char*)value,"W")==0){
349
329
myregister->mode=PCILIB_REGISTER_W;
350
}else if(strcmp((char*)value,"RW1C")==0){
330
}else if(strcasecmp((char*)value,"RW1C")==0){
351
331
myregister->mode=PCILIB_REGISTER_RW1C;
352
}else if(strcmp((char*)value,"W1C")==0){
332
}else if(strcasecmp((char*)value,"W1C")==0){
353
333
myregister->mode=PCILIB_REGISTER_W1C;
356
}else if(strcmp((char*)cur->name,"name")==0){
336
}else if(strcasecmp((char*)cur->name,"name")==0){
357
337
myregister->name=(char*)value;
359
}else if(strcmp((char*)cur->name,"value_min")==0){
339
}else if(strcasecmp((char*)cur->name,"value_min")==0){
360
340
/* not implemented yet*/ // myregister->value_min=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
362
}else if(strcmp((char*)cur->name,"value_max")==0){
342
}else if(strcasecmp((char*)cur->name,"value_max")==0){
363
343
/* not implemented yet*/ // myregister->value_max=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
365
}else if(strcmp((char*)cur->name,"description")==0){
345
}else if(strcasecmp((char*)cur->name,"description")==0){
367
347
myregister->description=(char*)value;
377
357
/** we then get properties that can not be parsed as the previous ones*/
378
if(strcmp((char*)type,"standard")==0){
358
if(strcasecmp((char*)type,"standard")==0){
379
359
myregister->type=PCILIB_REGISTER_STANDARD;
380
bank=xmlNodeListGetString(doc,xmlFirstElementChild(xmlFirstElementChild(mynode->parent->parent))->xmlChildrenNode,1); /**<we get the bank adress node*/
382
}else if(strcmp((char*)type,"bits")==0){
360
bank=pcilib_xml_get_bank_node_from_register_node(mynode);
362
value=xmlNodeListGetString(doc,bank->children,1);
363
if(strcasecmp((char*)bank->name,"name")==0){
371
while(pci->banks[k].name!=NULL){
372
printf("name %s\n",pci->banks[k].name);
373
if(strcasecmp(pci->banks[k].name,(char*)value)==0){
374
myregister->bank=pci->banks[k].addr;
381
}else if(strcasecmp((char*)type,"bits")==0){
383
382
myregister->type=PCILIB_REGISTER_BITS;
384
bank=xmlNodeListGetString(doc,xmlFirstElementChild(xmlFirstElementChild(mynode->parent->parent->parent->parent))->xmlChildrenNode,1);/**<we get the bank adress node*/
386
/* we then get the properties from the parent standard regsiter, and that are not present for the bit register*/
387
cur=mynode->parent->parent->children; /**<get the parent standard register*/
389
value=xmlNodeListGetString(doc,cur->children,1);
390
if(strcmp((char*)cur->name,"adress")==0){
391
myregister->addr=(pcilib_register_addr_t)strtol((char*)value,&ptr,0);
392
}else if(strcmp((char*)cur->name,"default")==0){
393
myregister->defvalue=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
394
}else if(strcmp((char*)cur->name,"rwmask")==0){
395
if(strcmp((char*)value,"all bits")==0){
396
myregister->rwmask=PCILIB_REGISTER_ALL_BITS;
397
}else if(strcmp((char*)value,"0")==0){
398
myregister->rwmask=0;
400
myregister->rwmask=(pcilib_register_value_t)strtol((char*)value,&ptr,0);
406
}else if(strcmp((char*)type,"fifo")==0){
384
}else if(strcasecmp((char*)type,"fifo")==0){
407
385
/* not implemented yet*/ myregister->type=PCILIB_REGISTER_FIFO;
410
if(strcmp((char*)bank,"bank 0")==0){
411
myregister->bank=PCILIB_REGISTER_BANK0;
412
}else if(strcmp((char*)bank,"bank 1")==0){
413
myregister->bank=PCILIB_REGISTER_BANK1;
414
}else if(strcmp((char*)bank,"bank 2")==0){
415
myregister->bank=PCILIB_REGISTER_BANK2;
416
}else if(strcmp((char*)bank,"bank 3")==0){
417
myregister->bank=PCILIB_REGISTER_BANK3;
418
}else if(strcmp((char*)bank,"DMA bank")==0){
419
myregister->bank=PCILIB_REGISTER_BANK_DMA;
420
}else if (strcmp((char*)bank,"dynamic bank")==0){
421
myregister->addr=PCILIB_REGISTER_BANK_DYNAMIC;
423
myregister->bank=PCILIB_REGISTER_BANK_INVALID;
427
391
/** pcilib_xml_initialize_registers
429
393
* this function create a list of registers from an abstract syntax tree
431
* variables who need change if xml structure change : bank,description, sub_description, sub_adress, sub_bank, sub_rwmask (we consider it to be equal to the standard register), sub_defvalue(same to standard register normally)
395
* variables who need change if xml structure change : bank,description, sub_description, sub_address, sub_bank, sub_rwmask (we consider it to be equal to the standard register), sub_defvalue(same to standard register normally)
432
396
* @param[in] doc the xpath context of the xml file.
433
397
* @param[in] pci the pcilib_t struct running, that will get filled
435
399
void pcilib_xml_initialize_registers(pcilib_t* pci,xmlDocPtr doc){
437
xmlNodeSetPtr nodesetadress=NULL, nodesetsubadress=NULL;
401
xmlNodeSetPtr nodesetaddress=NULL, nodesetsubaddress=NULL;
439
402
xmlNodePtr mynode;
440
403
xmlXPathContextPtr context;
441
404
pcilib_register_description_t *registers=NULL;
442
405
pcilib_register_description_t myregister;
445
context=pcilib_xml_getcontext(doc);
408
context= xmlXPathNewContext(doc);
409
if(!(context= xmlXPathNewContext(doc))){
410
pcilib_error("can't get an AST from an xml file");
447
414
/** we first get the nodes of standard and bits registers*/
448
nodesetadress=pcilib_xml_getsetproperty(context,REGISTERS_PATH)->nodesetval;
449
nodesetsubadress=pcilib_xml_getsetproperty(context,BITS_REGISTERS_PATH)->nodesetval;
450
if(nodesetadress->nodeNr>0)registers=calloc(nodesetadress->nodeNr+nodesetsubadress->nodeNr,sizeof(pcilib_register_description_t));
415
nodesetaddress=pcilib_xml_get_nodeset_from_xpath(context,REGISTERS_PATH)->nodesetval;
416
nodesetsubaddress=pcilib_xml_get_nodeset_from_xpath(context,BITS_REGISTERS_PATH)->nodesetval;
417
if(!(nodesetaddress)) return;
418
if(nodesetaddress->nodeNr>0)registers=calloc(nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,sizeof(pcilib_register_description_t));
453
pci->registers_xml_nodes=calloc(nodesetadress->nodeNr+nodesetsubadress->nodeNr,sizeof(xmlNodePtr));
454
if(!(pci->registers_xml_nodes)) pcilib_warning("can't create registers xml nodes in pcilib_t struct");
421
pci->xml_registers=calloc(nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,sizeof(xmlNodePtr));
422
if(!(pci->xml_registers)) pcilib_warning("can't create registers xml nodes in pcilib_t struct");
456
424
/** we then iterate through standard registers nodes to create registers structures*/
457
for(i=0;i<nodesetadress->nodeNr;i++){
458
type=(xmlChar*)"standard";
459
mynode=nodesetadress->nodeTab[i];
460
pcilib_xml_create_register(&myregister,mynode,doc,type);
425
for(i=0;i<nodesetaddress->nodeNr;i++){
426
mynode=nodesetaddress->nodeTab[i];
427
pcilib_xml_create_register(&myregister,mynode,doc,(xmlChar*)"standard",pci);
461
428
registers[i]=myregister;
462
pci->registers_xml_nodes[i]=mynode;
429
pci->xml_registers[i]=mynode;
433
if(!(nodesetsubaddress)) return;
466
434
/** we then iterate through bits registers nodes to create registers structures*/
467
for(i=0;i<nodesetsubadress->nodeNr;i++){
468
type=(xmlChar*)"bits";
469
mynode=nodesetsubadress->nodeTab[i];
470
pcilib_xml_create_register(&myregister,mynode,doc,type);
435
for(i=0;i<nodesetsubaddress->nodeNr;i++){
436
mynode=nodesetsubaddress->nodeTab[i];
437
pcilib_xml_create_register(&myregister,mynode->parent->parent,doc,(xmlChar*)"standard",pci);
438
pcilib_xml_create_register(&myregister,mynode,doc,(xmlChar*)"bits",pci);
471
439
registers[i+j]=myregister;
472
pci->registers_xml_nodes[i+j]=mynode;
440
pci->xml_registers[i+j]=mynode;
475
443
/**we arrange the register for them to be well placed for pci-l*/
476
pcilib_xml_arrange_registers(registers,nodesetadress->nodeNr+nodesetsubadress->nodeNr);
444
pcilib_xml_arrange_registers(registers,nodesetaddress->nodeNr+nodesetsubaddress->nodeNr);
477
445
/**we fille the pcilib_t struct*/
478
pcilib_add_registers(pci,nodesetadress->nodeNr+nodesetsubadress->nodeNr,registers);
446
pcilib_add_registers(pci,nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,registers);
482
450
/** pcilib_init_xml
483
451
* this function will initialize the registers and banks from the xml files
484
452
* @param[in,out] ctx the pciilib_t running that gets filled with structures
453
* @param[in] model the current model of ctx
454
* @return an error code
487
int pcilib_init_xml(pcilib_t* ctx){
457
int pcilib_init_xml(pcilib_t* ctx, char* model){
488
458
char *path,*pwd, **line, *line_xsd=NULL;