/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: zilio nicolas
  • Date: 2015-09-07 08:35:48 UTC
  • mto: This revision was merged to the branch mainline in revision 303.
  • Revision ID: nicolas.zilio@kit.edu-20150907083548-wcckckjtm0l84hsw
further modifications

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * 
5
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
6
6
 * 
7
 
 * @details this code was meant to be evolutive as the XML files evolute. In this meaning, most of the xml parsing is realized with XPath expressions(when it was possible), so that changing the xml xould result mainly in changing the XPAth pathes present in the header file. In a case of a change in xml file, variables that need to be changed other than xpathes, will be indicated in the description of the function.
8
 
 
 
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
 
9
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
10
 
11
 
 In case the performance is not good enough, please consider the following : no more configuration file indicating where the files required are, hard code of formulas, and go to complete non evolutive code : get 1 access to xml file and context, and then make recursive descent to get all you need(investigation of libxml2 source code would be so needed to prove it's better to go recursive than just xpath).
 
11
 In case the performance is not good enough, please consider the following : hard code of formulas
12
12
 */
13
13
#define _XOPEN_SOURCE 700
14
14
 
33
33
#include <libxml/xpathInternals.h>
34
34
#include <dirent.h>
35
35
#include <errno.h>
 
36
#include "config.h"
 
37
 
 
38
typedef enum{
 
39
  type_standard,
 
40
  type_bits,
 
41
  type_fifo
 
42
}pcilib_type_register_t;
 
43
 
36
44
 
37
45
/** pcilib_xml_get_nodeset_from_xpath
38
46
 * this function takes a context from an AST and an XPath expression, to produce an object containing the nodes corresponding to the xpath expression
59
67
}
60
68
 
61
69
 
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
66
 
 */
67
 
static xmlNodePtr
68
 
pcilib_xml_get_bank_node_from_register_node(xmlNodePtr mynode){
69
 
  return xmlFirstElementChild(xmlFirstElementChild(mynode->parent->parent));
70
 
}
71
 
 
72
 
 
73
 
 
74
70
/** pcilib_xml_validate
75
71
 * function to validate the xml file against the xsd
76
72
 * @param[in] xml_filename path to the xml file
125
121
 * @param[in] doc the AST of the xml file, used for used lixbml functions
126
122
 */
127
123
static void
128
 
pcilib_xml_create_bank(pcilib_register_bank_description_t *mybank, xmlNodePtr mynode, xmlDocPtr doc, pcilib_t* pci){
 
124
pcilib_xml_create_bank(pcilib_register_bank_description_t *mybank, xmlNodePtr mynode, xmlDocPtr doc, pcilib_t* pci, int err){
129
125
                
130
126
    char* ptr;
131
127
    xmlNodePtr cur;
132
128
    xmlChar *value;
133
 
    static int i=0;
134
129
    int bar_ok=0;
135
 
    int k=0, name_found=0;
 
130
    int k=0;
136
131
 
137
132
    cur=mynode->children; /** we place ourselves in the childrens of the bank node*/
138
133
 
149
144
            mybank->size=(size_t)strtol((char*)value,&ptr,0);
150
145
        
151
146
        }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;
155
 
              break;
156
 
              k++;
157
 
            }
 
147
          if((mybank->protocol=pcilib_find_register_protocol_by_name(pci,(char*)value))==PCILIB_REGISTER_PROTOCOL_INVALID){
 
148
            mybank->protocol=PCILIB_REGISTER_PROTOCOL_DEFAULT;
158
149
          }
159
150
 
160
151
        }else if(strcasecmp((char*)cur->name,"read_address")==0){               
190
181
    }
191
182
 
192
183
    if(bar_ok==0) mybank->bar=PCILIB_BAR_NOBAR;
193
 
  
194
 
    while(pci->banks[k].name!=NULL){
195
 
        if(strcasecmp(pci->banks[k].name,mybank->name)==0){
196
 
          mybank->addr=pci->banks[k].addr;
197
 
          name_found++;
198
 
          break;
 
184
 
 
185
        k=(int)pcilib_find_register_bank_by_name(pci,mybank->name);
 
186
        if(k==PCILIB_REGISTER_BANK_INVALID){
 
187
              mybank->addr=PCILIB_REGISTER_BANK_DYNAMIC + pci->xml_ctx->nb_new_banks;
 
188
              pci->xml_ctx->nb_new_banks++;
 
189
                  k=pci->num_banks+1;
199
190
        }
200
 
        k++;
201
 
    }
202
 
    if(name_found==0) {
203
 
      mybank->addr=PCILIB_REGISTER_BANK_DYNAMIC + i;
204
 
      i++;
205
 
    }
206
 
    pci->xml_banks[k]=mynode;
 
191
        else mybank->addr=pci->banks[k].addr;
 
192
   
 
193
    if(err==0){
 
194
            pci->xml_ctx->xml_banks[k]=mynode;
 
195
    }
 
196
 
 
197
        char buffer[66];
 
198
    sprintf(buffer,"%i",mybank->addr);
 
199
    printf("buffer %s \n",buffer);
 
200
    xmlNewChild(mynode,NULL, BAD_CAST "address", BAD_CAST buffer);
207
201
}
208
202
                  
209
203
        
222
216
        xmlNodeSetPtr nodesetaddress=NULL;
223
217
        xmlNodePtr mynode;      
224
218
        xmlXPathContextPtr context;
225
 
        int i;
 
219
        int i,err=0;
226
220
 
227
221
        mynode=malloc(sizeof(xmlNode));
228
222
        if(!(context= xmlXPathNewContext(doc))){
234
228
        if(!(nodesetaddress)) return;
235
229
        if(nodesetaddress->nodeNr==0) return;
236
230
 
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");
 
231
        pci->xml_ctx->xml_banks=calloc(PCILIB_MAX_REGISTER_BANKS+1,sizeof(xmlNodePtr));
 
232
        if(!(pci->xml_ctx->xml_banks)){
 
233
          pcilib_error("can't create bank xml nodes for pcilib_t struct");
 
234
          err++;
 
235
        }
239
236
 
240
237
        /** for each of the bank nodes, we create the associated structure, and  push it in the pcilib environnement*/
241
238
        for(i=0;i<nodesetaddress->nodeNr;i++){
242
239
          mynode=nodesetaddress->nodeTab[i];
243
 
          pcilib_xml_create_bank(&mybank,mynode,doc, pci);
 
240
          pcilib_xml_create_bank(&mybank,mynode,doc, pci, err);
244
241
          pcilib_add_register_banks(pci,1,&mybank);
245
242
        }
246
243
 
267
264
 * @param[in,out] registers the list of registers in : not ranged out: ranged.
268
265
 * @param[in] size the number of registers. 
269
266
 */
270
 
void pcilib_xml_arrange_registers(pcilib_register_description_t *registers,int size){
 
267
static void
 
268
pcilib_xml_arrange_registers(pcilib_register_description_t *registers,int size){
271
269
        pcilib_register_description_t* temp;
272
270
        temp=malloc(size*sizeof(pcilib_register_description_t));
273
271
        qsort(registers,size,sizeof(pcilib_register_description_t),pcilib_xml_compare_registers);
274
272
        free(temp);
275
273
}
276
274
 
 
275
/**pcilib_get_bank_address_from_register_node
 
276
 *@param[in] node the current register node
 
277
 */
 
278
static xmlChar*
 
279
pcilib_get_bank_address_from_register_node(xmlDocPtr doc, xmlNodePtr node){
 
280
  xmlChar* temp= xmlNodeListGetString(doc,xmlGetLastChild(xmlFirstElementChild(node->parent->parent))->children,1);
 
281
        return temp;
 
282
}           
 
283
 
 
284
 
277
285
/** pcilib_xml_create_register.
278
286
 * this function create a register structure from a xml register node.
279
287
 * @param[out] myregister the register we want to create
281
289
 * @param[in] doc the AST of the xml file, required for some ibxml2 sub-fonctions
282
290
 * @param[in] mynode the xml node to create register from
283
291
 */
284
 
void pcilib_xml_create_register(pcilib_register_description_t *myregister,xmlNodePtr mynode, xmlDocPtr doc, xmlChar* type, pcilib_t* pci){
 
292
void pcilib_xml_create_register(pcilib_register_description_t *myregister,xmlNodePtr mynode, xmlDocPtr doc,pcilib_register_type_t type, pcilib_t* pci){
285
293
                
286
294
    char* ptr;
287
295
    xmlNodePtr cur;
288
296
    xmlChar *value=NULL;
289
 
    xmlNodePtr bank=NULL;
290
297
    int i=0;
291
298
 
292
299
    /**we get the children of the register xml nodes, that contains the properties for it*/
299
306
                */
300
307
        if(strcasecmp((char*)cur->name,"address")==0){  
301
308
                myregister->addr=(pcilib_register_addr_t)strtol((char*)value,&ptr,0);
302
 
 
 
309
                
303
310
        }else if(strcasecmp((char*)cur->name,"offset")==0){
304
311
                myregister->offset=(pcilib_register_size_t)strtol((char*)value,&ptr,0);
305
312
 
352
359
 
353
360
    /** make sure we don't get the description from previous registers*/
354
361
    if(i==0) myregister->description=NULL;
355
 
    
356
362
 
357
363
    /** we then get properties that can not be parsed as the previous ones*/
358
 
        if(strcasecmp((char*)type,"standard")==0){
 
364
        if((int)type==(int)type_standard){
359
365
          myregister->type=PCILIB_REGISTER_STANDARD;
360
 
          bank=pcilib_xml_get_bank_node_from_register_node(mynode);
361
 
          while(bank!=NULL){
362
 
            value=xmlNodeListGetString(doc,bank->children,1);
363
 
            if(strcasecmp((char*)bank->name,"name")==0){
364
 
              break;
365
 
            }
366
 
            bank=bank->next;
367
 
          }
368
 
 
369
 
          int k=0;
370
 
 
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;
375
 
              printf("ok\n");
376
 
              break;
377
 
            }
378
 
            k++;
379
 
          }
380
 
 
381
 
        }else if(strcasecmp((char*)type,"bits")==0){
 
366
          myregister->bank=(pcilib_register_bank_addr_t)strtol((char*)pcilib_get_bank_address_from_register_node(doc,mynode),&ptr,0);
 
367
          
 
368
        }else if((int)type==(int)type_bits){
382
369
          myregister->type=PCILIB_REGISTER_BITS;
383
 
 
384
 
        }else if(strcasecmp((char*)type,"fifo")==0){
 
370
        
 
371
        }else if((int)type==(int)type_fifo){
385
372
  /* not implemented yet*/        myregister->type=PCILIB_REGISTER_FIFO;
386
373
        }
387
 
      
 
374
     
388
375
        
389
376
}       
390
377
 
403
390
        xmlXPathContextPtr context;
404
391
        pcilib_register_description_t *registers=NULL;
405
392
        pcilib_register_description_t myregister;
406
 
        int i,j;
 
393
        int i,j,err=0;
407
394
 
408
395
        context= xmlXPathNewContext(doc);
409
396
        if(!(context= xmlXPathNewContext(doc))){
418
405
        if(nodesetaddress->nodeNr>0)registers=calloc(nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,sizeof(pcilib_register_description_t));
419
406
        else return;
420
407
        
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");
 
408
        if(pci->xml_ctx->nb_registers==0)
 
409
          pci->xml_ctx->xml_registers=calloc(nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,sizeof(xmlNodePtr));
 
410
        else 
 
411
          pci->xml_ctx->xml_registers=realloc(pci->xml_ctx->xml_registers,(pci->xml_ctx->nb_registers+nodesetaddress->nodeNr+nodesetsubaddress->nodeNr)*sizeof(xmlNodePtr));
 
412
        
 
413
        if(!(pci->xml_ctx->xml_registers)){
 
414
          pcilib_warning("can't create registers xml nodes in pcilib_t struct: memory allocation failed");
 
415
          err++;
 
416
        }
423
417
                
424
418
        /** we then iterate through standard registers nodes to create registers structures*/
425
419
        for(i=0;i<nodesetaddress->nodeNr;i++){
426
420
                mynode=nodesetaddress->nodeTab[i];
427
 
                pcilib_xml_create_register(&myregister,mynode,doc,(xmlChar*)"standard",pci);
 
421
                pcilib_xml_create_register(&myregister,mynode,doc,type_standard,pci);
428
422
                registers[i]=myregister;
429
 
                pci->xml_registers[i]=mynode;
 
423
                if(err==0) pci->xml_ctx->xml_registers[pci->xml_ctx->nb_registers+i]=mynode;
430
424
        }
431
425
        
432
426
        j=i;
434
428
        /** we then iterate through bits  registers nodes to create registers structures*/
435
429
        for(i=0;i<nodesetsubaddress->nodeNr;i++){
436
430
                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);
 
431
                pcilib_xml_create_register(&myregister,mynode->parent->parent,doc,type_standard,pci);
 
432
                pcilib_xml_create_register(&myregister,mynode,doc,type_bits,pci);
439
433
                registers[i+j]=myregister;
440
 
                pci->xml_registers[i+j]=mynode;
 
434
                if(err==0) pci->xml_ctx->xml_registers[pci->xml_ctx->nb_registers+i+j]=mynode;
441
435
        }
442
436
        
443
437
        /**we arrange the register for them to be well placed for pci-l*/
444
438
        pcilib_xml_arrange_registers(registers,nodesetaddress->nodeNr+nodesetsubaddress->nodeNr);
445
439
        /**we fille the pcilib_t struct*/
446
440
        pcilib_add_registers(pci,nodesetaddress->nodeNr+nodesetsubaddress->nodeNr,registers);
 
441
        pci->xml_ctx->nb_registers+=nodesetaddress->nodeNr+nodesetsubaddress->nodeNr;
447
442
}
448
443
 
449
444
 
460
455
    xmlDocPtr* docs;
461
456
    DIR* rep=NULL;
462
457
    struct dirent* file=NULL;
463
 
    int err;
 
458
    int err, err_count=0;
464
459
 
465
460
    path=malloc(sizeof(char*));
466
461
    line=malloc(sizeof(char*));
469
464
    /** we first get the env variable corresponding to the place of the xml files*/
470
465
    path=getenv("PCILIB_MODEL_DIR");
471
466
    if(path==NULL){
472
 
      pcilib_warning("can't find environment variable for xml files");
473
 
      return 1;
 
467
      path=PCILIB_MODEL_DIR;
474
468
    }
475
469
    
476
470
    /** we then open the directory corresponding to the ctx model*/
478
472
    sprintf(pwd,"%s%s/",path,model);
479
473
    if((rep=opendir(pwd))==NULL){
480
474
      pcilib_warning("could not open the directory for xml files: error %i\n",errno);
481
 
      return 1;
 
475
      return PCILIB_ERROR_NOTINITIALIZED;
482
476
    }
483
477
 
484
478
    /** we iterate through the files of the directory, to get the xml files and the xsd file*/
497
491
 
498
492
    if(line_xsd==NULL){
499
493
      pcilib_warning("no xsd file found");
500
 
      return 1;
 
494
      return PCILIB_ERROR_NOTINITIALIZED;
501
495
    }
502
496
 
503
497
    if(line[0]==NULL){
504
498
      pcilib_warning("no xml file found");
505
 
      return 1;
 
499
      return PCILIB_ERROR_NOTINITIALIZED;
506
500
    }
507
501
    
508
502
    /** for each xml file, we validate it, and get the registers and the banks*/
509
503
    docs=malloc((i-1)*sizeof(xmlDocPtr));
 
504
    ctx->xml_ctx=malloc(sizeof(pcilib_xml_context_t));
 
505
    ctx->xml_ctx->docs=malloc(sizeof(xmlDocPtr)*(i-1));
 
506
    ctx->xml_ctx->nb_registers=0;
 
507
    ctx->xml_ctx->nb_new_banks=0;
 
508
 
 
509
    if(!(ctx->xml_ctx) || !(ctx->xml_ctx->docs))
 
510
      return  PCILIB_ERROR_MEMORY;
 
511
 
 
512
    
510
513
    for(k=0;k<i-1;k++){
511
514
      if((err=pcilib_xml_validate(line[k],line_xsd))==0){
512
515
        if((docs[k]=xmlParseFile(line[k]))){
513
516
          pcilib_xml_initialize_banks(ctx,docs[k]);
514
 
            pcilib_xml_initialize_registers(ctx,docs[k]);
515
 
        }
516
 
        else pcilib_error("xml document %s not parsed successdfullly\n",line[k]);
 
517
          pcilib_xml_initialize_registers(ctx,docs[k]);
 
518
        }
 
519
        else{
 
520
          pcilib_error("xml document %s not parsed successdfullly\n",line[k]);
 
521
          err_count++;
 
522
        }
517
523
      }
518
524
    }  
519
 
    ctx->xml_context=malloc(sizeof(pcilib_xml_context_t));
520
 
    ctx->xml_context->docs=malloc(sizeof(xmlDocPtr)*(i-1));
521
 
    ctx->xml_context->docs=docs;
 
525
    
 
526
    ctx->xml_ctx->docs=docs;
522
527
 
523
528
    free(pwd);
524
529
    free(line);
525
530
    free(line_xsd);
526
531
 
 
532
    if(err_count>0) return PCILIB_ERROR_NOTINITIALIZED;
527
533
    return 0;
528
534
}  
529
535
 
531
537
 * this function free the xml parts of the pcilib_t running, and some libxml ashes
532
538
 * @param[in] pci the pcilib_t running
533
539
*/
534
 
void pcilib_clean_xml(pcilib_t* pci){
 
540
void pcilib_free_xml(pcilib_t* pci){
535
541
 
536
 
  free(pci->xml_banks);
537
 
  free(pci->xml_registers);
538
 
  free(pci->xml_context);
 
542
  free(pci->xml_ctx->xml_banks);
 
543
  free(pci->xml_ctx->xml_registers);
 
544
  pci->xml_ctx->xml_banks=NULL;
 
545
  pci->xml_ctx->xml_registers=NULL;
 
546
  free(pci->xml_ctx);
 
547
  pci->xml_ctx=NULL;
 
548
  
539
549
  xmlCleanupParser();
540
550
  xmlMemoryDump();
541
551