diff options
| author | zilio nicolas <nicolas.zilio@kit.edu> | 2015-09-10 20:40:15 +0200 | 
|---|---|---|
| committer | zilio nicolas <nicolas.zilio@kit.edu> | 2015-09-10 20:40:15 +0200 | 
| commit | 2722e76f513ba7be80e63f1f49f2095d39759f09 (patch) | |
| tree | f6658894864616633564c1fb0990edad9d677da4 | |
| parent | 9bcd0b7b98dfb10d054913dad34313391f6029f2 (diff) | |
| download | pcitool-2722e76f513ba7be80e63f1f49f2095d39759f09.tar.gz pcitool-2722e76f513ba7be80e63f1f49f2095d39759f09.tar.bz2 pcitool-2722e76f513ba7be80e63f1f49f2095d39759f09.tar.xz pcitool-2722e76f513ba7be80e63f1f49f2095d39759f09.zip  | |
more towards views
| -rw-r--r-- | pcilib/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | pcilib/pci.h | 5 | ||||
| -rw-r--r-- | pcilib/views.c | 67 | ||||
| -rw-r--r-- | pcilib/views.h | 16 | ||||
| -rw-r--r-- | pcilib/xml.c | 239 | 
5 files changed, 324 insertions, 10 deletions
diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index f75d7de..48363f6 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -8,9 +8,10 @@ include_directories(  )  set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h -xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h -debug.h env.h version.h config.h views.h) -add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c views.c) +views.h xml.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h +debug.h env.h version.h config.h ) +add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c +register.c views.c xml.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c )  target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT}  ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS}  ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) diff --git a/pcilib/pci.h b/pcilib/pci.h index 00528e1..657c335 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -62,6 +62,8 @@ struct pcilib_s {      size_t num_banks, num_protocols, num_ranges;					/**< Number of registered banks, protocols, and register ranges */      size_t num_engines;									/**< Number of configured DMA engines */      size_t dyn_banks;									/**< Number of configured dynamic banks */ +  size_t num_enum_views,alloc_enum_views;                                               /**< Number of configured and allocated  views of type enum*/ +  size_t num_formula_views,alloc_formula_views;                                         /**< Number of configured and allocated  views of type formula*/      pcilib_register_description_t *registers;						/**< List of currently defined registers (from all sources) */      pcilib_register_bank_description_t banks[PCILIB_MAX_REGISTER_BANKS + 1];		/**< List of currently defined register banks (from all sources) */ @@ -81,6 +83,9 @@ struct pcilib_s {      struct pcilib_locking_s locks;							/**< Context of locking subsystem */      struct pcilib_xml_s xml;                                                    	/**< XML context */ +  pcilib_view_enum2_t* enum_views;     /**< list of currently defined views of type enum*/ +  pcilib_view_formula_t* formula_views;     /**< list of currently defined views of type formula*/ +  #ifdef PCILIB_FILE_IO      int file_io_handle;  #endif /* PCILIB_FILE_IO */ diff --git a/pcilib/views.c b/pcilib/views.c index 38ce102..44392d9 100644 --- a/pcilib/views.c +++ b/pcilib/views.c @@ -2,7 +2,7 @@  #include "pci.h"  #include "pcilib.h"  #include <Python.h> -#include "views.h" +//#include "views.h"  #include "error.h"  #include <strings.h>  #include <stdlib.h> @@ -329,3 +329,68 @@ int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, cons    pcilib_warning("the view asked and the register do not correspond");    return PCILIB_ERROR_NOTAVAILABLE;   } + +/** + * function to populate ctx enum views, as we could do for registers or banks + */ +int pcilib_add_views_enum(pcilib_t *ctx, size_t n, const pcilib_view_enum2_t* views) { +	 +    pcilib_view_enum2_t *views_enum; +    size_t size; + +    if (!n) { +	for (n = 0; views[n].enums_list[0].value; n++); +    } + +    if ((ctx->num_enum_views + n + 1) > ctx->alloc_enum_views) { +	for (size = ctx->alloc_enum_views; size < 2 * (n + ctx->num_enum_views + 1); size<<=1); + +	views_enum = (pcilib_view_enum2_t*)realloc(ctx->enum_views, size * sizeof(pcilib_view_enum2_t)); +	if (!views_enum) return PCILIB_ERROR_MEMORY; + +	ctx->enum_views = views_enum; +	/* context + model part ????*/ +	ctx->alloc_enum_views = size; +    } + +    memcpy(ctx->enum_views + ctx->num_enum_views, views, n * sizeof(pcilib_view_enum2_t)); +    memset(ctx->enum_views + ctx->num_enum_views + n, 0, sizeof(pcilib_view_enum2_t)); + +    ctx->num_enum_views += n; +     + +    return 0; +} + + +/** + * function to populate ctx formula views, as we could do for registers or banks + */ +int pcilib_add_views_formula(pcilib_t *ctx, size_t n, const pcilib_view_formula_t* views) { +	 +    pcilib_view_formula_t *views_formula; +    size_t size; + +    if (!n) { +	for (n = 0; views[n].name[0]; n++); +    } + +    if ((ctx->num_formula_views + n + 1) > ctx->alloc_formula_views) { +	for (size = ctx->alloc_formula_views; size < 2 * (n + ctx->num_formula_views + 1); size<<=1); + +	views_formula = (pcilib_view_formula_t*)realloc(ctx->formula_views, size * sizeof(pcilib_view_formula_t)); +	if (!views_formula) return PCILIB_ERROR_MEMORY; + +	ctx->formula_views = views_formula; +	/* context + model part?????*/ +	ctx->alloc_formula_views = size; +    } + +    memcpy(ctx->formula_views + ctx->num_formula_views, views, n * sizeof(pcilib_view_formula_t)); +    memset(ctx->formula_views + ctx->num_formula_views + n, 0, sizeof(pcilib_view_formula_t)); + +    ctx->num_formula_views += n; +     + +    return 0; +} diff --git a/pcilib/views.h b/pcilib/views.h index bdae9f4..98e3dcd 100644 --- a/pcilib/views.h +++ b/pcilib/views.h @@ -7,6 +7,8 @@ typedef struct pcilib_view_enum_s pcilib_view_enum_t;  typedef struct pcilib_view_formula_s pcilib_view_formula_t; +typedef struct pcilib_view_enum2_s pcilib_view_enum2_t; +  /**   * new type to define an enum view   */ @@ -17,6 +19,15 @@ struct pcilib_view_enum_s {  /** + * complete type for an enum view : name will be changed after with the previous one + */ +struct pcilib_view_enum2_s { +  const char* name; +  pcilib_view_enum_t* enums_list; +}; + + +/**   * new type to define a formula view   */  struct pcilib_view_formula_s { @@ -36,4 +47,9 @@ int pcilib_read_view(pcilib_t *ctx, const char *bank, const char *regname, const   */  int pcilib_write_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view/*, const char *unit*/, size_t value_size, void *value); +int pcilib_add_views_enum(pcilib_t* ctx,size_t n, pcilib_view_enum2_t* views); + +int pcilib_add_views_formula(pcilib_t* ctx, size_t n, pcilib_view_formula_t* views); + +  #endif diff --git a/pcilib/xml.c b/pcilib/xml.c index 73a3deb..852f319 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -39,12 +39,15 @@  #include "register.h"  #include "xml.h"  #include "error.h" +#include "views.h"  #define BANKS_PATH ((xmlChar*)"/model/banks/bank/bank_description") 						/**< path to complete nodes of banks.*/  //#define REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register") 					/**< all standard registers nodes.*/  //#define BIT_REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register/registers_bits/register_bits") 	/**< all bits registers nodes.*/  #define REGISTERS_PATH ((xmlChar*)"../registers/register") 			/**< all standard registers nodes.*/  #define BIT_REGISTERS_PATH ((xmlChar*)"./registers_bits/register_bits") 	/**< all bits registers nodes.*/ +#define VIEWS_PATH ((xmlChar*)"/model/views/view") 						/**< path to complete nodes of views.*/ +  static char *pcilib_xml_bank_default_format = "0x%lx"; @@ -67,7 +70,74 @@ static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr  }  */ -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) { + +/** + * get the associated views of a register, to fill its register context + */ +static int +pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextPtr xpath,pcilib_register_t id){ +  char* VIEWS_NAME_PATH="/model/banks/bank/registers/register[@name=\"%s\"]/views/view"; +  char* path; +  xmlXPathObjectPtr nodes; +  xmlNodeSetPtr nodeset; +  char* view_name; + +  /*we get first the nodes corresponding to the given register*/ +  path=malloc(strlen(VIEWS_NAME_PATH)+strlen(reg_name)); +  if(!(path)){ +    pcilib_error("can't allocate memory for getting path to get associated views of %s",reg_name); +    return PCILIB_ERROR_MEMORY; +  } + +  sprintf(path,VIEWS_NAME_PATH,reg_name); +  nodes = xmlXPathEvalExpression((xmlChar*)path, xpath); +  nodeset = nodes->nodesetval; + +    if (!xmlXPathNodeSetIsEmpty(nodeset)) { +      int i,k,l; +      /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ +	for (i = 0; i < nodeset->nodeNr; i++) { +	  view_name=(char*)nodeset->nodeTab[i]->children->content; +	   +	  /* if the view name obtained is for an enum view, we get all pcilib_view_enum_t corresponding to the register*/ +	  for(k=0; ctx->enum_views[k].enums_list[0].value;k++){ +	    if(!(strcasecmp(view_name, ctx->enum_views[k].name))){ +	      ctx->register_ctx[id].enums=malloc(sizeof(pcilib_view_enum_t)); +	       +	      if(!(ctx->register_ctx[id].enums)){ +		pcilib_error("error allocating memory for enum views in register context %i",id); +		return PCILIB_ERROR_MEMORY; +	      } + +	      for(l=0; ctx->enum_views[k].enums_list[l].value;l++){ +		ctx->register_ctx[id].enums=realloc(ctx->register_ctx[id].enums,(l+1)*sizeof(pcilib_view_enum_t)); +		ctx->register_ctx[id].enums[l]=ctx->enum_views[k].enums_list[l]; +	      } +	    } +	  } + +	  /*here it is for formula, i assume we have only one formula view per register*/ +	  for(k=0; ctx->formula_views[k].name[0];k++){ +	    if(!(strcasecmp(view_name,ctx->formula_views[k].name))){ +	      ctx->register_ctx[id].formulas=malloc(sizeof(pcilib_view_formula_t)); +	      if(!(ctx->register_ctx[id].formulas)){ +		pcilib_error("error allocating memory for formula views in register context %i",id); +		return PCILIB_ERROR_MEMORY; +	      } + +	      ctx->register_ctx[id].formulas=&(ctx->formula_views[k]); +	    } +	  } + +	} +    } + +    xmlXPathFreeObject(nodes); +    return 0; +} + + +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, int* views_ok) {      pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc;      xmlNodePtr cur; @@ -166,6 +236,9 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript          } else if (!strcasecmp(name,"description")) {              desc->description = value;          } +	else if (!strcasecmp(name,"views")) { +            *views_ok=1; +        }      }      return 0; @@ -173,6 +246,7 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript  static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) {      int err; +    int views_ok=0;      xmlXPathObjectPtr nodes;      xmlNodeSetPtr nodeset; @@ -187,7 +261,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank      desc.base.mode = PCILIB_REGISTER_R;      desc.base.type = PCILIB_REGISTER_STANDARD; -    err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank]); +    err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank],&views_ok);      if (err) {  	pcilib_error("Error (%i) parsing an XML register", err);  	return err; @@ -202,6 +276,12 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank      ctx->register_ctx[reg].xml = node;          ctx->register_ctx[reg].min = desc.min;      ctx->register_ctx[reg].max = desc.max; +     +    /* if the register had a node of type views, then we compute its associated registers. I do that here as i need the index for register context*/ +    if(views_ok){ +      err=pcilib_get_associated_views(ctx,desc.base.name,xpath,reg); +      if(err) pcilib_warning("can't get correctly the associated views of the register %s",desc.base.name); +    }      xpath->node = node;      nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath); @@ -228,7 +308,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank  	    fdesc.base.rwmask = desc.base.rwmask;  	    fdesc.base.type = PCILIB_REGISTER_BITS; -    	    err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank]); +    	    err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank],&views_ok);      	    if (err) {      		pcilib_error("Error parsing field in the XML register %s", desc.base.name);      		continue; @@ -243,6 +323,10 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank      	    ctx->register_ctx[reg].xml = nodeset->nodeTab[i];  	    ctx->register_ctx[reg].min = fdesc.min;  	    ctx->register_ctx[reg].max = fdesc.max; +	    if(views_ok){ +	      err=pcilib_get_associated_views(ctx, desc.base.name,xpath,reg); +	      if(err) pcilib_warning("can't get correctly the associated views of the register %s",fdesc.base.name); +	    }  	}      }      xmlXPathFreeObject(nodes); @@ -397,6 +481,131 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo  } +/** + * function that create a view from a view node, and populate ctx views list + */ +static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { +    int err; +     +    pcilib_view_enum2_t complete_enum_desc={0}; +    pcilib_view_enum_t enum_desc = {0}; +    pcilib_view_formula_t formula_desc= {0}; +    xmlNodePtr cur; +    char *value, *name; +    char *endptr; +    xmlAttr *attr; +    int i=0; + +    /*must i initialize? i think it's only needed if we want to include a description property*/  +    enum_desc.name="default"; +    enum_desc.value=0; +    enum_desc.min=0; +    enum_desc.max=0; + +    complete_enum_desc.name="default enum"; +    complete_enum_desc.enums_list=malloc(sizeof(pcilib_view_enum_t)); +    if(!(complete_enum_desc.enums_list)){ +      pcilib_error("can't allocate memory for the complete enum type"); +      return PCILIB_ERROR_MEMORY; +    } +    complete_enum_desc.enums_list[0]=enum_desc; + +    formula_desc.name="formula_default"; +    formula_desc.read_formula="@reg"; +    formula_desc.write_formula="@reg"; + +    /* we get the attribute type of the view node*/ +    attr=node->properties; +    value=(char*)attr->children->content; +    /* regarding the architecture, i decided to follow what has been done for registers and banks. but without the context*/ +    /*if the view is of type enum, we get recursively its properties and then populate ctx enum views*/ +    if(!(strcasecmp(value,"enum"))){ +      for (cur = node->children; cur != NULL; cur = cur->next) { +	if (!cur->children) continue; +	if (!xmlNodeIsText(cur->children)) continue; +	 +	name = (char*)cur->name; +	value = (char*)cur->children->content; +        if (!value) continue; +         +	if (!(strcasecmp((char*)name,"name"))) { +	  complete_enum_desc.name = value; +        }else if (!(strcasecmp((char*)name,"enum"))) { + +	  complete_enum_desc.enums_list=realloc(complete_enum_desc.enums_list,(i+1)*sizeof(pcilib_view_enum_t)); +	  complete_enum_desc.enums_list[i].name=value;  +	   +	  /* we need to iterate through the different attributes of an enum node to get all properties*/ +	  for(attr=cur->properties; attr!=NULL;attr=attr->next){ +	    if(!attr->children) continue; +	    if(!xmlNodeIsText(attr->children)) continue; +	     +	    name=(char*)attr->name; +	    value=(char*)attr->children->content; + +	    if(!(strcasecmp(name,"value"))){ +	       pcilib_register_value_t dat_value = strtol(value, &endptr, 0); +	       if ((strlen(endptr) > 0)) { +		 pcilib_error("Invalid value (%s) is specified in the XML enum node", value); +		 return PCILIB_ERROR_INVALID_DATA; +	       } +	       complete_enum_desc.enums_list[i].value=dat_value; +	    }else if(!(strcasecmp(name,"min"))){ +	       pcilib_register_value_t dat_min = strtol(value, &endptr, 0); +	       if ((strlen(endptr) > 0)) { +		 pcilib_error("Invalid min (%s) is specified in the XML enum node", value); +		 return PCILIB_ERROR_INVALID_DATA; +	       } +	      complete_enum_desc.enums_list[i].min=dat_min; +	    }else if(!(strcasecmp(name,"max"))){ +	       pcilib_register_value_t dat_max = strtol(value, &endptr, 0); +	       if ((strlen(endptr) > 0)) { +		 pcilib_error("Invalid max (%s) is specified in the XML enum node", value); +		 return PCILIB_ERROR_INVALID_DATA; +	       } + +	      complete_enum_desc.enums_list[i].max=dat_max; +	    } +	  } +	  i++; +	} +      } +      err=pcilib_add_views_enum(ctx,1,&complete_enum_desc); +      if (err) { +	pcilib_error("Error (%i) adding a new enum view (%s) to the pcilib_t", err, complete_enum_desc.name); +	return err; +      } +    +      /* we do the same here but for a iew of type formula if the attribute gives formula*/ +    }else if(!(strcasecmp(value,"formula"))){ +      for (cur = node->children; cur != NULL; cur = cur->next) { +	if (!cur->children) continue; +	if (!xmlNodeIsText(cur->children)) continue; +	 +	name = (char*)cur->name; +	value = (char*)cur->children->content; +        if (!value) continue; +         +	if (!(strcasecmp((char*)name,"name"))) { +	  formula_desc.name = value; +        }else if (!(strcasecmp((char*)name,"read_from_register"))) { +	  formula_desc.read_formula=value; +        }else if (!(strcasecmp((char*)name,"write_to_register"))) { +	  formula_desc.write_formula=value; +	} +      } +      err=pcilib_add_views_formula(ctx,1,&formula_desc); +      if (err) { +	pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, formula_desc.name); +	return err; +      } + +    } +  +    return 0; +} + +  /** pcilib_xml_initialize_banks   *   * function to create the structures to store the banks from the AST @@ -405,12 +614,14 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo   * @param[in] pci the pcilib_t running, which will be filled   */  static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) { -    xmlXPathObjectPtr bank_nodes; +  xmlXPathObjectPtr bank_nodes,views_nodes;      xmlNodeSetPtr nodeset; +    int i; +    xmlErrorPtr xmlerr;      bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath);       if (!bank_nodes) { -	xmlErrorPtr xmlerr = xmlGetLastError(); +	xmlerr = xmlGetLastError();  	if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message);  	else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH);  	return PCILIB_ERROR_FAILED; @@ -419,13 +630,29 @@ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathCon      nodeset = bank_nodes->nodesetval;      if (!xmlXPathNodeSetIsEmpty(nodeset)) { -	int i;  	for (i = 0; i < nodeset->nodeNr; i++) {      	    pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]);  	}      }      xmlXPathFreeObject(bank_nodes); + +    views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); +    if(!views_nodes){ +	xmlerr = xmlGetLastError(); +	if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); +	else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); +	return PCILIB_ERROR_FAILED; +    } +     +    nodeset=views_nodes->nodesetval; +    if(!xmlXPathNodeSetIsEmpty(nodeset)){ +      for(i=0;i < nodeset->nodeNr; i++){ +	pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); +      } +    } +    xmlXPathFreeObject(views_nodes);     +      return 0;  }  | 
