diff options
| -rw-r--r-- | pcilib/bank.c | 14 | ||||
| -rw-r--r-- | pcilib/pci.c | 25 | ||||
| -rw-r--r-- | pcilib/pci.h | 17 | ||||
| -rw-r--r-- | pcilib/register.c | 37 | ||||
| -rw-r--r-- | pcilib/register.h | 1 | ||||
| -rw-r--r-- | pcilib/unit.c | 96 | ||||
| -rw-r--r-- | pcilib/unit.h | 3 | ||||
| -rw-r--r-- | pcilib/view.c | 144 | ||||
| -rw-r--r-- | pcilib/view.h | 20 | ||||
| -rw-r--r-- | views/enum.c | 4 | ||||
| -rw-r--r-- | views/transform.c | 2 | 
11 files changed, 252 insertions, 111 deletions
| diff --git a/pcilib/bank.c b/pcilib/bank.c index 66ff739..24ddf1f 100644 --- a/pcilib/bank.c +++ b/pcilib/bank.c @@ -208,6 +208,7 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch      pcilib_register_t i;      pcilib_register_bank_t bank_id;      pcilib_register_bank_addr_t bank_addr = 0; +    pcilib_register_context_t *reg_ctx;      const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);      const pcilib_register_description_t *registers =  model_info->registers; @@ -220,11 +221,16 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch  	}  	bank_addr = model_info->banks[bank_id].addr; + +            // ToDo: we can use additionaly per-bank hashes +        for (i = 0; registers[i].bits; i++) { +	    if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; +        } +    } else { +        HASH_FIND_STR(ctx->reg_hash, reg, reg_ctx); +        if (reg_ctx) return reg_ctx->reg;      } -     -    for (i = 0; registers[i].bits; i++) { -	if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; -    } +      return PCILIB_REGISTER_INVALID;  }; diff --git a/pcilib/pci.c b/pcilib/pci.c index 0ba5f51..4a0e79c 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -365,7 +365,6 @@ char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) {  void pcilib_close(pcilib_t *ctx) { -    int i;      pcilib_bar_t bar;      if (ctx) { @@ -386,15 +385,6 @@ void pcilib_close(pcilib_t *ctx) {  	pcilib_free_register_banks(ctx); -	if (ctx->register_ctx) { -	    pcilib_register_t reg; -	    for (reg = 0; reg < ctx->num_reg; reg++) { -		if (ctx->register_ctx[reg].views) -		    free(ctx->register_ctx[reg].views); -	    } -	    free(ctx->register_ctx); -	} -  	if (ctx->event_plugin)  	    pcilib_plugin_close(ctx->event_plugin); @@ -422,15 +412,22 @@ void pcilib_close(pcilib_t *ctx) {  	if (ctx->pci_cfg_space_fd >= 0)  	    close(ctx->pci_cfg_space_fd); -	if (ctx->units); -	    free(ctx->units); + +        if (ctx->units) { +            pcilib_clean_units(ctx); +            free(ctx->units); +        }  	if (ctx->views) { -	    for (i = 0; ctx->views[i]; i++) -	        free(ctx->views[i]); +	    pcilib_clean_views(ctx);  	    free(ctx->views);  	} +        pcilib_clean_registers(ctx); + +	if (ctx->register_ctx) +            free(ctx->register_ctx); +  	if (ctx->registers)  	    free(ctx->registers); diff --git a/pcilib/pci.h b/pcilib/pci.h index 88327b3..ff18e52 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -40,22 +40,25 @@ typedef struct {  } pcilib_pcie_link_info_t;  struct pcilib_view_context_s { -    UT_hash_handle hh; +    const char *name;      pcilib_view_t view; -//    pcilib_view_description_t desc;							/**< We will allocate more memory and store actual description instance here, so it should be the last member */ -};  +    UT_hash_handle hh; +};  struct pcilib_unit_context_s { -    UT_hash_handle hh; +    const char *name;      pcilib_unit_t unit; -//    pcilib_unit_description_t desc; +    UT_hash_handle hh;  };  typedef struct { +    const char *name;                                                                   /**< Register name */ +    pcilib_register_t reg;                                                              /**< Register index */      pcilib_register_bank_t bank;							/**< Reference to bank containing the register */      pcilib_register_value_t min, max;							/**< Minimum & maximum allowed values */      pcilib_xml_node_t *xml;								/**< Additional XML properties */      pcilib_view_reference_t *views;							/**< For non-static list of views, this vairables holds a copy of a NULL-terminated list from model (if present, memory should be de-allocated) */ +    UT_hash_handle hh;  } pcilib_register_context_t;  struct pcilib_s { @@ -104,6 +107,10 @@ struct pcilib_s {      pcilib_view_description_t **views;							/**< list of currently defined views */      pcilib_unit_description_t *units;							/**< list of currently defined units */ +    pcilib_unit_context_t *unit_hash;                                                   /**< Hash of units */ +    pcilib_view_context_t *view_hash;                                                   /**< Hash of views */ +    pcilib_register_context_t *reg_hash;                                                /**< Hash of registers */ +      pcilib_lock_t *dma_rlock[PCILIB_MAX_DMA_ENGINES];					/**< Per-engine locks to serialize streaming and read operations */      pcilib_lock_t *dma_wlock[PCILIB_MAX_DMA_ENGINES];					/**< Per-engine locks to serialize write operations */ diff --git a/pcilib/register.c b/pcilib/register.c index 68e5d36..3a60800 100644 --- a/pcilib/register.c +++ b/pcilib/register.c @@ -23,6 +23,7 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,  	// DS: Overrride existing registers   	// Registers identified by addr + offset + size + type or name +    pcilib_register_t i;      pcilib_register_description_t *regs;      pcilib_register_context_t *reg_ctx;      size_t size; @@ -45,11 +46,26 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,  	memset(reg_ctx + ctx->alloc_reg, 0, (size - ctx->alloc_reg) * sizeof(pcilib_register_context_t)); -	ctx->register_ctx = reg_ctx; +	if (ctx->register_ctx != reg_ctx) { +	        // We need to recreate cache if context is moved... +	    HASH_CLEAR(hh, ctx->reg_hash); +	    for (i = 0; i < ctx->num_reg; i++) { +                pcilib_register_context_t *cur = &ctx->register_ctx[ctx->num_reg + i]; +                HASH_ADD_KEYPTR(hh, ctx->reg_hash, cur->name, strlen(cur->name), cur); +	    } +	} +	ctx->register_ctx = reg_ctx;  	ctx->alloc_reg = size;      } +    for (i = 0; i < n; i++) { +        pcilib_register_context_t *cur = &ctx->register_ctx[ctx->num_reg + i]; +        cur->reg = ctx->num_reg + i; +        cur->name = registers[i].name; +        HASH_ADD_KEYPTR(hh, ctx->reg_hash, cur->name, strlen(cur->name), cur); +    } +          memcpy(ctx->registers + ctx->num_reg, registers, n * sizeof(pcilib_register_description_t));      memset(ctx->registers + ctx->num_reg + n, 0, sizeof(pcilib_register_description_t)); @@ -61,11 +77,28 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,      }      ctx->num_reg += n; -     +      return 0;  } +void pcilib_clean_registers(pcilib_t *ctx) { +    pcilib_register_t reg; + +    HASH_CLEAR(hh, ctx->reg_hash); +    for (reg = 0; reg < ctx->num_reg; reg++) { +	if (ctx->register_ctx[reg].views) +	    free(ctx->register_ctx[reg].views); +    } + +    if (ctx->registers) +        memset(ctx->registers, 0, sizeof(pcilib_register_description_t)); + +    if (ctx->register_ctx) +        memset(ctx->register_ctx, 0, ctx->alloc_reg * sizeof(pcilib_register_context_t)); + +    ctx->num_reg = 0; +}  static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t *buf) {      int err; diff --git a/pcilib/register.h b/pcilib/register.h index 74eeb12..95f52cc 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -55,6 +55,7 @@ extern "C" {  #endif  int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_description_t *registers, pcilib_register_t *ids); +void pcilib_clean_registers(pcilib_t *ctx);  #ifdef __cplusplus  } diff --git a/pcilib/unit.c b/pcilib/unit.c index 6817afc..0295120 100644 --- a/pcilib/unit.c +++ b/pcilib/unit.c @@ -8,16 +8,79 @@  #include "unit.h"  #include "error.h" -  static pcilib_unit_transform_t pcilib_unit_transform_null = { NULL, NULL }; +int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_description_t *desc) { +    size_t i; +    int err = 0; + +    if (!n) { +        for (n = 0; desc[n].name; n++); +    } + +    if ((ctx->num_units + n + 1) > ctx->alloc_units) { +	size_t size; +	pcilib_unit_description_t *units; + +        for (size = ctx->alloc_units; size < 2 * (n + ctx->num_units + 1); size <<= 1); + +        units = (pcilib_unit_description_t*)realloc(ctx->units, size * sizeof(pcilib_unit_description_t)); +        if (!units) return PCILIB_ERROR_MEMORY; + +        ctx->units = units; +        ctx->alloc_units = size; + +        ctx->model_info.units = units; +    } + +        // ToDo: Check if exists... +    for (i = 0; i < n; i++) { +        pcilib_unit_context_t *unit_ctx = (pcilib_unit_context_t*)malloc(sizeof(pcilib_unit_context_t)); +        if (!unit_ctx) { +            err = PCILIB_ERROR_MEMORY; +            break; +        } +        memset(unit_ctx, 0, sizeof(pcilib_unit_context_t)); +        unit_ctx->unit = ctx->num_units + i; +        unit_ctx->name = desc[i].name; + +        HASH_ADD_KEYPTR(hh, ctx->unit_hash, unit_ctx->name, strlen(unit_ctx->name), unit_ctx); +        memcpy(ctx->units + ctx->num_units + i, &desc[i], sizeof(pcilib_unit_description_t)); +    } + +    memset(ctx->units + ctx->num_units + i, 0, sizeof(pcilib_unit_description_t)); +    ctx->num_units += i; + +    return err; +} + +void pcilib_clean_units(pcilib_t *ctx) { +    pcilib_unit_context_t *s, *tmp; + +    if (ctx->unit_hash) { +        HASH_ITER(hh, ctx->unit_hash, s, tmp) { +            HASH_DEL(ctx->unit_hash, s); +            free(s); +        } +    } + +    memset(ctx->units, 0, sizeof(pcilib_unit_description_t)); +    ctx->num_units = 0; +} +  pcilib_unit_t pcilib_find_unit_by_name(pcilib_t *ctx, const char *name) { -    pcilib_unit_t i; +    pcilib_unit_context_t *unit_ctx = NULL; +    HASH_FIND_STR(ctx->unit_hash, name, unit_ctx); +    if (unit_ctx) return unit_ctx->unit; + +/* +    pcilib_unit_t i;      for(i = 0; ctx->units[i].name; i++) {          if (!strcasecmp(ctx->units[i].name, name))  	    return i;      } +*/      return PCILIB_UNIT_INVALID;  } @@ -42,35 +105,6 @@ pcilib_unit_transform_t *pcilib_find_transform_by_unit_names(pcilib_t *ctx, cons      return NULL;  } -int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_description_t *desc) { -    if (!n) { -        for (n = 0; desc[n].name; n++); -    } - -    if ((ctx->num_units + n + 1) > ctx->alloc_units) { -	size_t size; -	pcilib_unit_description_t *units; - -        for (size = ctx->alloc_units; size < 2 * (n + ctx->num_units + 1); size <<= 1); - -        units = (pcilib_unit_description_t*)realloc(ctx->units, size * sizeof(pcilib_unit_description_t)); -        if (!units) return PCILIB_ERROR_MEMORY; - -        ctx->units = units; -        ctx->alloc_units = size; - -        ctx->model_info.units = units; -    } - -    memcpy(ctx->units + ctx->num_units, desc, n * sizeof(pcilib_unit_description_t)); -    memset(ctx->units + ctx->num_units + n, 0, sizeof(pcilib_unit_description_t)); - -    ctx->num_units += n; - -    return 0; -} - -  int pcilib_transform_unit(pcilib_t *ctx, pcilib_unit_transform_t *trans, pcilib_value_t *value) {      int err; diff --git a/pcilib/unit.h b/pcilib/unit.h index e0eeefc..dad7962 100644 --- a/pcilib/unit.h +++ b/pcilib/unit.h @@ -8,7 +8,7 @@  #define PCILIB_MAX_TRANSFORMS_PER_UNIT 16			/**< Limits number of supported transforms per unit */ -typedef struct pcilib_unit_context_s *pcilib_unit_context_t; +typedef struct pcilib_unit_context_s pcilib_unit_context_t;  /**   * unit transformation routines @@ -28,6 +28,7 @@ extern "C" {  #endif  int pcilib_add_units(pcilib_t *ctx, size_t n, const pcilib_unit_description_t *desc); +void pcilib_clean_units(pcilib_t *ctx);  pcilib_unit_t pcilib_find_unit_by_name(pcilib_t *ctx, const char *unit);  pcilib_unit_transform_t *pcilib_find_transform_by_unit_names(pcilib_t *ctx, const char *from, const char *to); diff --git a/pcilib/view.c b/pcilib/view.c index d121f34..bf312e4 100644 --- a/pcilib/view.c +++ b/pcilib/view.c @@ -11,6 +11,7 @@  #include "value.h"  int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc) { +    int err = 0;      size_t i;      void *ptr; @@ -43,88 +44,138 @@ int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *d      ptr = (void*)desc;      for (i = 0; i < n; i++) {          const pcilib_view_description_t *v = (const pcilib_view_description_t*)ptr; +        pcilib_view_context_t *view_ctx; +          ctx->views[ctx->num_views + i] = (pcilib_view_description_t*)malloc(v->api->description_size);          if (!ctx->views[ctx->num_views + i]) { -            size_t j; -            for (j = 0; j < i; j++) -                free(ctx->views[ctx->num_views + j]); -            ctx->views[ctx->num_views] = NULL; -            pcilib_error("Error allocating %zu bytes of memory for the view description", v->api->description_size); -            return PCILIB_ERROR_MEMORY; +            err = PCILIB_ERROR_MEMORY; +            break; +        } + +        if (v->api->init)  +            view_ctx = v->api->init(ctx); +        else { +            view_ctx = (pcilib_view_context_t*)malloc(sizeof(pcilib_view_context_t)); +            memset(view_ctx, 0, sizeof(pcilib_view_context_t));          } + +        view_ctx->view = ctx->num_views + i; +        view_ctx->name = v->name; + +        if (!view_ctx) { +            free(ctx->views[ctx->num_views + i]); +            err = PCILIB_ERROR_MEMORY; +            break; +        } + +        HASH_ADD_KEYPTR(hh, ctx->view_hash, view_ctx->name, strlen(view_ctx->name), view_ctx);          memcpy(ctx->views[ctx->num_views + i], v, v->api->description_size);          ptr += v->api->description_size;      }      ctx->views[ctx->num_views + i] = NULL; -    ctx->num_views += n; +    ctx->num_views += i; -    return 0; +    return err;  } - -pcilib_view_t pcilib_find_view_by_name(pcilib_t *ctx, const char *name) { +void pcilib_clean_views(pcilib_t *ctx) {      pcilib_view_t i; +    pcilib_view_context_t *view_ctx, *tmp; + +    if (ctx->unit_hash) { +        HASH_ITER(hh, ctx->view_hash, view_ctx, tmp) { +            const pcilib_view_description_t *v = ctx->views[view_ctx->view]; + +            HASH_DEL(ctx->view_hash, view_ctx); +            if (v->api->free) v->api->free(ctx, view_ctx); +            else free(view_ctx); +        } +    } -    for(i = 0; ctx->views[i]; i++) { -        if (!strcasecmp(ctx->views[i]->name, name)) -	    return i; +    for (i = 0; ctx->views[i]; i++) { +	if (ctx->views[i]->api->free_description) { +	    ctx->views[i]->api->free_description(ctx, ctx->views[i]); +	} else { +	    free(ctx->views[i]); +	}      } +    ctx->views[0] = NULL; +    ctx->num_views = 0; +} + +pcilib_view_context_t *pcilib_find_view_context_by_name(pcilib_t *ctx, const char *name) { +    pcilib_view_context_t *view_ctx = NULL; + +    HASH_FIND_STR(ctx->view_hash, name, view_ctx); +    return view_ctx; +} + +pcilib_view_t pcilib_find_view_by_name(pcilib_t *ctx, const char *name) { +    pcilib_view_context_t *view_ctx = pcilib_find_view_context_by_name(ctx, name); +    if (view_ctx) return view_ctx->view;      return PCILIB_VIEW_INVALID;  } -pcilib_view_t pcilib_find_register_view_by_name(pcilib_t *ctx, pcilib_register_t reg, const char *name) { + + +pcilib_view_context_t *pcilib_find_register_view_context_by_name(pcilib_t *ctx, pcilib_register_t reg, const char *name) {      pcilib_view_t i;      pcilib_register_context_t *regctx = &ctx->register_ctx[reg]; -    if (!regctx->views) return PCILIB_VIEW_INVALID; +    if (!regctx->views) return NULL;      for (i = 0; regctx->views[i].name; i++) {  	if (strcasecmp(name, regctx->views[i].name)) { -	    return pcilib_find_view_by_name(ctx, regctx->views[i].view); +	    return pcilib_find_view_context_by_name(ctx, regctx->views[i].view);  	}      } -     -    return PCILIB_VIEW_INVALID; + +    return NULL;  }      // We expect symmetric units. Therefore, we don't distringuish if we read or write -pcilib_view_t pcilib_find_register_view(pcilib_t *ctx, pcilib_register_t reg, const char *name) { +pcilib_view_context_t *pcilib_find_register_view_context(pcilib_t *ctx, pcilib_register_t reg, const char *name) {      pcilib_view_t i; +    pcilib_view_context_t *view_ctx; +    pcilib_view_description_t *view_desc;      pcilib_register_context_t *regctx = &ctx->register_ctx[reg]; -    if (!regctx->views) return PCILIB_VIEW_INVALID; +    if (!regctx->views) return NULL;  	// Check if view is just a name of listed view -    i = pcilib_find_register_view_by_name(ctx, reg, name); -    if (i != PCILIB_VIEW_INVALID) return i; +    view_ctx = pcilib_find_register_view_context_by_name(ctx, reg, name); +    if (view_ctx) return view_ctx;  	// Check if view is a unit      for (i = 0; regctx->views[i].name; i++) {  	pcilib_unit_transform_t *trans; -	pcilib_view_t view = pcilib_find_view_by_name(ctx, regctx->views[i].view); -	if (view == PCILIB_VIEW_INVALID) continue; -         -        if (ctx->views[view]->unit) { -	    trans = pcilib_find_transform_by_unit_names(ctx, ctx->views[view]->unit, name); -	    if (trans) return view; + +	view_ctx = pcilib_find_view_context_by_name(ctx, regctx->views[i].view); +	if (!view_ctx) continue; + +        view_desc = ctx->views[view_ctx->view]; +        if (view_desc->unit) { +	    trans = pcilib_find_transform_by_unit_names(ctx, view_desc->unit, name); +	    if (trans) return pcilib_find_view_context_by_name(ctx, view_desc->name);  	}      } -    return PCILIB_VIEW_INVALID; +    return NULL;  }  typedef struct {      pcilib_register_t reg; -    pcilib_view_t view; +    pcilib_view_context_t *view;      pcilib_unit_transform_t *trans;  } pcilib_view_configuration_t;  static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, const char *regname, const char *view_cname, int write_direction, pcilib_view_configuration_t *cfg) {      pcilib_view_t view; -    pcilib_register_t reg = PCILIB_REGISTER_INVALID; +    pcilib_view_context_t *view_ctx;      pcilib_unit_transform_t *trans = NULL; +    pcilib_register_t reg = PCILIB_REGISTER_INVALID;      char *view_name = alloca(strlen(view_cname) + 1);      char *unit_name; @@ -147,20 +198,21 @@ static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, con  	// get value -	if (unit_name) view = pcilib_find_register_view_by_name(ctx, reg, view_name); -	else view = pcilib_find_register_view(ctx, reg, view_name); +	if (unit_name) view_ctx = pcilib_find_register_view_context_by_name(ctx, reg, view_name); +	else view_ctx = pcilib_find_register_view_context(ctx, reg, view_name); -	if (view == PCILIB_VIEW_INVALID) { +	if (!view_ctx) {  	    pcilib_error("Can't find the specified view %s for register %s", view_name, regname);  	    return PCILIB_ERROR_NOTFOUND;  	}      } else { -        view = pcilib_find_view_by_name(ctx, view_name); -	if (view == PCILIB_VIEW_INVALID) { +        view_ctx = pcilib_find_view_context_by_name(ctx, view_name); +	if (!view_ctx) {  	    pcilib_error("Can't find the specified view %s", view_name);  	    return PCILIB_ERROR_NOTFOUND;  	}      } +    view = view_ctx->view;      if (unit_name) {          if (write_direction) trans = pcilib_find_transform_by_unit_names(ctx, unit_name, ctx->views[view]->unit); @@ -175,7 +227,7 @@ static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, con      }      cfg->reg = reg; -    cfg->view = view; +    cfg->view = view_ctx;      cfg->trans = trans;      return 0; @@ -185,13 +237,16 @@ static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, con  int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, pcilib_value_t *val) {      int err; +    pcilib_view_description_t *v;      pcilib_view_configuration_t cfg;      pcilib_register_value_t regvalue = 0;      err = pcilib_detect_view_configuration(ctx, bank, regname, view, 0, &cfg);      if (err) return err; -    if (!ctx->views[cfg.view]->api->read_from_reg) { +    v = ctx->views[cfg.view->view]; + +    if (!v->api->read_from_reg) {          pcilib_error("The view (%s) does not support reading from the register", view);          return PCILIB_ERROR_NOTSUPPORTED;      } @@ -206,7 +261,7 @@ int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regna      pcilib_clean_value(ctx, val); -    err = ctx->views[cfg.view]->api->read_from_reg(ctx, NULL /*???*/, ®value, val); +    err = v->api->read_from_reg(ctx, cfg.view, ®value, val);      if (err) {          if (regname)               pcilib_error("Error (%i) computing view (%s) of register %s", err, view, regname); @@ -228,13 +283,16 @@ int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regn      int err;      pcilib_value_t val; +    pcilib_view_description_t *v;      pcilib_view_configuration_t cfg;      pcilib_register_value_t regvalue = 0;      err = pcilib_detect_view_configuration(ctx, bank, regname, view, 1, &cfg);      if (err) return err; -    if (!ctx->views[cfg.view]->api->write_to_reg) { +    v = ctx->views[cfg.view->view]; + +    if (!v->api->write_to_reg) {          pcilib_error("The view (%s) does not support reading from the register", view);          return PCILIB_ERROR_NOTSUPPORTED;      } @@ -242,9 +300,9 @@ int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regn      err = pcilib_copy_value(ctx, &val, valarg);      if (err) return err; -    err = pcilib_convert_value_type(ctx, &val, ctx->views[cfg.view]->type); +    err = pcilib_convert_value_type(ctx, &val, v->type);      if (err) { -        pcilib_error("Error (%i) converting the value of type (%s) to type (%s) used by view (%s)", pcilib_get_type_name(val.type), pcilib_get_type_name(ctx->views[cfg.view]->type), view); +        pcilib_error("Error (%i) converting the value of type (%s) to type (%s) used by view (%s)", pcilib_get_type_name(val.type), pcilib_get_type_name(v->type), view);          return err;      } @@ -254,7 +312,7 @@ int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regn      } -    err = ctx->views[cfg.view]->api->write_to_reg(ctx, NULL /*???*/, ®value, &val); +    err = v->api->write_to_reg(ctx, cfg.view, ®value, &val);      if (err) {          if (regname)               pcilib_error("Error (%i) computing view (%s) of register %s", err, view, regname); diff --git a/pcilib/view.h b/pcilib/view.h index bf0ea28..4af4c00 100644 --- a/pcilib/view.h +++ b/pcilib/view.h @@ -6,8 +6,8 @@  #define PCILIB_VIEW_INVALID ((pcilib_view_t)-1) -//typedef void *pcilib_view_context_t; -typedef struct pcilib_view_context_s *pcilib_view_context_t; +typedef struct pcilib_view_context_s pcilib_view_context_t; +typedef struct pcilib_view_description_s pcilib_view_description_t;  typedef enum {      PCILIB_VIEW_FLAG_PROPERTY = 1                                               /**< Indicates that view does not depend on a value and is independent property */ @@ -16,30 +16,34 @@ typedef enum {  typedef struct {      pcilib_version_t version;      size_t description_size; -    pcilib_view_context_t (*init)(pcilib_t *ctx); +    pcilib_view_context_t *(*init)(pcilib_t *ctx);      void (*free)(pcilib_t *ctx, pcilib_view_context_t *view); +    void (*free_description)(pcilib_t *ctx, pcilib_view_description_t *view);      int (*read_from_reg)(pcilib_t *ctx, pcilib_view_context_t *view, const pcilib_register_value_t *regval, pcilib_value_t *val);      int (*write_to_reg)(pcilib_t *ctx, pcilib_view_context_t *view, pcilib_register_value_t *regval, const pcilib_value_t *val);  } pcilib_view_api_description_t; -typedef struct { +struct pcilib_view_description_s {      const pcilib_view_api_description_t *api;      pcilib_value_type_t type;			                                /**< The default data type returned by operation, PCILIB_VIEW_TYPE_STRING is supported by all operations */      pcilib_view_flags_t flags;                                                  /**< Flags specifying type of the view */      const char *unit;				                                /**< Returned unit (if any) */      const char *name;				                                /**< Name of the view */      const char *description;			                                /**< Short description */ -} pcilib_view_description_t; +};  #ifdef __cplusplus  extern "C" {  #endif  int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc); +void pcilib_clean_views(pcilib_t *ctx); + +pcilib_view_context_t *pcilib_find_view_context_by_name(pcilib_t *ctx, const char *view); +pcilib_view_context_t *pcilib_find_register_view_context_by_name(pcilib_t *ctx, pcilib_register_t reg, const char *name); +pcilib_view_context_t *pcilib_find_register_view_context(pcilib_t *ctx, pcilib_register_t reg, const char *name); -pcilib_view_t pcilib_find_view_by_name(pcilib_t *ctx, const char *view); -pcilib_view_t pcilib_find_register_view_by_name(pcilib_t *ctx, pcilib_register_t reg, const char *name); -pcilib_view_t pcilib_find_register_view(pcilib_t *ctx, pcilib_register_t reg, const char *name); +pcilib_view_t pcilib_find_view_by_name(pcilib_t *ctx, const char *name);  #ifdef __cplusplus  } diff --git a/views/enum.c b/views/enum.c index aecda7a..5d3a726 100644 --- a/views/enum.c +++ b/views/enum.c @@ -42,6 +42,6 @@ static int pcilib_enum_view_write(pcilib_t *ctx, pcilib_view_context_t *view, pc  }  const pcilib_view_api_description_t pcilib_enum_view_static_api = -  { PCILIB_VERSION, sizeof(pcilib_enum_view_description_t), NULL, NULL,  pcilib_enum_view_read,  pcilib_enum_view_write }; +  { PCILIB_VERSION, sizeof(pcilib_enum_view_description_t), NULL, NULL, NULL, pcilib_enum_view_read,  pcilib_enum_view_write };  const pcilib_view_api_description_t pcilib_enum_view_xml_api = -  { PCILIB_VERSION, sizeof(pcilib_enum_view_description_t), NULL, pcilib_enum_view_free,  pcilib_enum_view_read,  pcilib_enum_view_write }; +  { PCILIB_VERSION, sizeof(pcilib_enum_view_description_t), NULL, NULL, pcilib_enum_view_free,  pcilib_enum_view_read,  pcilib_enum_view_write }; diff --git a/views/transform.c b/views/transform.c index 93fc783..8885e17 100644 --- a/views/transform.c +++ b/views/transform.c @@ -68,4 +68,4 @@ static int pcilib_transform_view_write(pcilib_t *ctx, pcilib_view_context_t *vie  const pcilib_view_api_description_t pcilib_transform_view_api = -  { PCILIB_VERSION, sizeof(pcilib_transform_view_description_t), NULL, NULL,  pcilib_transform_view_read,  pcilib_transform_view_write }; +  { PCILIB_VERSION, sizeof(pcilib_transform_view_description_t), NULL, NULL, NULL, pcilib_transform_view_read,  pcilib_transform_view_write }; | 
