diff options
| -rw-r--r-- | pcilib/bank.h | 6 | ||||
| -rw-r--r-- | pcilib/export.c | 9 | ||||
| -rw-r--r-- | pcilib/export.h | 2 | ||||
| -rw-r--r-- | pcilib/property.c | 34 | ||||
| -rw-r--r-- | pcilib/property.h | 20 | ||||
| -rw-r--r-- | pcilib/register.c | 65 | ||||
| -rw-r--r-- | pcilib/register.h | 7 | ||||
| -rw-r--r-- | pcilib/view.c | 18 | ||||
| -rw-r--r-- | pcilib/view.h | 4 | ||||
| -rw-r--r-- | pcilib/xml.c | 38 | ||||
| -rw-r--r-- | pcitool/cli.c | 33 | ||||
| -rw-r--r-- | protocols/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | protocols/default.h | 6 | ||||
| -rw-r--r-- | protocols/property.c | 42 | ||||
| -rw-r--r-- | protocols/property.h | 16 | ||||
| -rw-r--r-- | protocols/software.h | 8 | ||||
| -rw-r--r-- | xml/test/camera.xml | 2 | ||||
| -rw-r--r-- | xml/types.xsd | 13 | 
18 files changed, 281 insertions, 46 deletions
| diff --git a/pcilib/bank.h b/pcilib/bank.h index ba149b9..2f90321 100644 --- a/pcilib/bank.h +++ b/pcilib/bank.h @@ -8,13 +8,15 @@  #define PCILIB_REGISTER_BANK1 			1  #define PCILIB_REGISTER_BANK2 			2  #define PCILIB_REGISTER_BANK3 			3 -#define PCILIB_REGISTER_BANK_DMA		64					/**< First BANK address to be used by DMA engines */ -#define PCILIB_REGISTER_BANK_DMACONF		65					/**< DMA configuration in the software registers */ +#define PCILIB_REGISTER_BANK_PROPERTY           64                                      /**< Registers abstracting properties and other computed registers */ +#define PCILIB_REGISTER_BANK_DMA		96					/**< First BANK address to be used by DMA engines */ +#define PCILIB_REGISTER_BANK_DMACONF		96					/**< DMA configuration in the software registers */  #define PCILIB_REGISTER_BANK_DYNAMIC		128					/**< First BANK address to map dynamic XML configuration */  #define PCILIB_REGISTER_PROTOCOL_INVALID	((pcilib_register_protocol_t)-1)  #define PCILIB_REGISTER_PROTOCOL0		0					/**< First PROTOCOL address to be used in the event engine */  #define PCILIB_REGISTER_PROTOCOL_DEFAULT	64					/**< Default memmap based protocol */  #define PCILIB_REGISTER_PROTOCOL_SOFTWARE	65					/**< Software registers */ +#define PCILIB_REGISTER_PROTOCOL_PROPERTY       66                                      /**< Protocol to access registers interfacing properties */  #define PCILIB_REGISTER_PROTOCOL_DMA		96					/**< First PROTOCOL address to be used by DMA engines */  #define PCILIB_REGISTER_PROTOCOL_DYNAMIC	128					/**< First PROTOCOL address to be used by plugins */ diff --git a/pcilib/export.c b/pcilib/export.c index ffb1c4b..8e1a7d2 100644 --- a/pcilib/export.c +++ b/pcilib/export.c @@ -10,13 +10,20 @@ const char *pcilib_data_types[] = { "default", "string", "double", "long" };  #include "protocols/default.h"  #include "protocols/software.h" +#include "protocols/property.h"  const pcilib_register_protocol_description_t pcilib_protocols[] = {      { PCILIB_REGISTER_PROTOCOL_DEFAULT, &pcilib_default_protocol_api, NULL, NULL, "default", "" }, -    { PCILIB_REGISTER_PROTOCOL_SOFTWARE, &pcilib_register_software_protocol_api, NULL, NULL, "software_registers", "" }, +    { PCILIB_REGISTER_PROTOCOL_SOFTWARE, &pcilib_software_protocol_api, NULL, NULL, "software_registers", "" }, +    { PCILIB_REGISTER_PROTOCOL_PROPERTY, &pcilib_property_protocol_api, NULL, NULL, "property_registers", "" },      { 0 }  }; +const pcilib_register_bank_description_t pcilib_property_register_bank =  +    { PCILIB_REGISTER_BANK_PROPERTY, PCILIB_REGISTER_PROTOCOL_PROPERTY, PCILIB_BAR_NOBAR, 0, 0, 32, 0, PCILIB_HOST_ENDIAN, PCILIB_HOST_ENDIAN, "%lu", "property", "Computed registers interfacing properties"}; + + +  #include "dma/nwl.h"  #include "dma/ipe.h" diff --git a/pcilib/export.h b/pcilib/export.h index 6fb08c3..7d3ff35 100644 --- a/pcilib/export.h +++ b/pcilib/export.h @@ -13,6 +13,8 @@ extern const pcilib_dma_description_t pcilib_dma[];  extern const pcilib_register_protocol_api_description_t pcilib_default_protocol_api; +extern const pcilib_register_bank_description_t pcilib_property_register_bank; +  extern const pcilib_dma_description_t pcilib_ipedma;  extern const pcilib_dma_description_t pcilib_nwldma; diff --git a/pcilib/property.c b/pcilib/property.c index 276360a..1a20de1 100644 --- a/pcilib/property.c +++ b/pcilib/property.c @@ -15,7 +15,34 @@  #include "tools.h"  #include "error.h" -int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers) { + +int pcilib_add_registers_from_properties(pcilib_t *ctx, size_t n, pcilib_view_context_t* const *view_ctx, pcilib_view_description_t* const *v) { +    pcilib_view_t i; +    pcilib_register_t pos = 0; +    pcilib_register_description_t regs[n]; + +    for (i = 0; i < n; i++) { +        if ((v[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) continue; + +        regs[pos++] = (pcilib_register_description_t){ +            .addr = view_ctx[i]->view, +            .bits = 8 * sizeof(pcilib_register_value_t), +            .mode = v[i]->mode, +            .type = PCILIB_REGISTER_PROPERTY, +            .bank = PCILIB_REGISTER_BANK_PROPERTY, +            .name = (v[i]->regname?v[i]->regname:v[i]->name), +            .description = v[i]->description +        }; +    } + +    if (pos) +        return pcilib_add_registers(ctx, 0, pos, regs, NULL); + +    return 0; +} + + +int pcilib_add_properties_from_registers(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers) {      int err;      pcilib_register_t i; @@ -26,12 +53,15 @@ int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_registe      for (i = 0; i < n; i++) { +        char *view_name;          pcilib_access_mode_t mode = 0;          pcilib_register_view_description_t v;          pcilib_register_bank_description_t *b = &ctx->banks[banks[i]]; -        char *view_name = malloc(strlen(registers[i].name) + strlen(b->name) + 13); +        if (registers[i].type == PCILIB_REGISTER_PROPERTY) continue; + +        view_name = malloc(strlen(registers[i].name) + strlen(b->name) + 13);          if (!view_name) {              pcilib_clean_views(ctx, cur_view);              return PCILIB_ERROR_MEMORY; diff --git a/pcilib/property.h b/pcilib/property.h index bec11c8..75ec053 100644 --- a/pcilib/property.h +++ b/pcilib/property.h @@ -5,7 +5,7 @@  extern "C" {  #endif  /** - * This is internal function used to add property view for all model registers. It is automatically + * This is an internal function used to add property view for all model registers. It is automatically   * called from pcilib_add_registers and should not be called by the users. On error no new views are    * initalized.   * @param[in,out] ctx - pcilib context @@ -14,7 +14,23 @@ extern "C" {   * @param[in] desc - register descriptions   * @return - error or 0 on success   */ -int pcilib_add_register_properties(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *desc); +int pcilib_add_properties_from_registers(pcilib_t *ctx, size_t n, const pcilib_register_bank_t *banks, const pcilib_register_description_t *registers); + + +/** + * To reduce number of required interfaces, some of the property views may be also mapped into the  + * model as registers. The client application, then, is able to use either register or property APIs + * to access them. This is an internal function which processes the supplied views, finds which views + * have to be mapped in the register space, and finally pushes corresponding registers into the model. + * The function is automatically called from pcilib_add_views and should never be called by the user.  + * On error no new registers are added. + * @param[in,out] ctx - pcilib context + * @param[in] n - number of views to analyze.  + * @param[in] view_ctx - views to analyze + * @param[in] view - array of pointers to corresponding view descriptions + * @return - error or 0 on success + */ +int pcilib_add_registers_from_properties(pcilib_t *ctx, size_t n, pcilib_view_context_t* const *view_ctx, pcilib_view_description_t* const *view);  #ifdef __cplusplus  } diff --git a/pcilib/register.c b/pcilib/register.c index 08af871..a166bbd 100644 --- a/pcilib/register.c +++ b/pcilib/register.c @@ -74,8 +74,17 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,              bank_addr = registers[i].bank;              bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);              if (bank == PCILIB_REGISTER_BANK_INVALID) { -                pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name); -                return PCILIB_ERROR_INVALID_BANK; +                    // We need to add a bank first in this case +                if (registers[i].type == PCILIB_REGISTER_PROPERTY) { +                    err = pcilib_add_register_banks(ctx, 0, 1, &pcilib_property_register_bank, &bank); +                } else { +                    err = PCILIB_ERROR_INVALID_BANK; +                } + +                if (err) { +                    pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name); +                    return err; +                }              }          } @@ -91,7 +100,7 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,          banks[i] = bank;      } -    err = pcilib_add_register_properties(ctx, n, banks, registers); +    err = pcilib_add_properties_from_registers(ctx, n, banks, registers);      if (err) return err;      for (i = 0; i < n; i++) { @@ -148,7 +157,9 @@ void pcilib_clean_registers(pcilib_t *ctx, pcilib_register_t start) {  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; +      size_t i; +    size_t space_size;      pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];      const pcilib_register_protocol_api_description_t *bapi = bctx->api; @@ -163,14 +174,31 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba  	return PCILIB_ERROR_NOTSUPPORTED;      } -    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { +    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views; +    else space_size = b->size; + +    if (((addr + n) > space_size)||(((addr + n) == space_size)&&(bits))) {  	if ((b->format)&&(strchr(b->format, 'x'))) -	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); +	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);  	else  -	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); +	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);  	return PCILIB_ERROR_OUTOFRANGE;      } +    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) { +        for (i = 0; i < (bits?(n+1):n); i++) { +            if ((ctx->views[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) { +                pcilib_error("Accessing invalid register %u (associated view does not provide register functionality)", addr + i); +                return PCILIB_ERROR_INVALID_REQUEST; +            } + +            if ((ctx->views[i]->mode&PCILIB_ACCESS_R) == 0) { +                pcilib_error("Read access is not allowed to register %u", addr + i); +                return PCILIB_ERROR_NOTPERMITED; +            } +        } +    }  +      //err = pcilib_init_register_banks(ctx);      //if (err) return err; @@ -259,7 +287,9 @@ int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, p  static int pcilib_write_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 rwmask, pcilib_register_value_t *buf) {      int err; +      size_t i; +    size_t space_size;      pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];      const pcilib_register_protocol_api_description_t *bapi = bctx->api; @@ -274,14 +304,31 @@ static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_b  	return PCILIB_ERROR_NOTSUPPORTED;      } -    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { +    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views; +    else space_size = b->size; + +    if (((addr + n) > space_size)||(((addr + n) == space_size)&&(bits))) {  	if ((b->format)&&(strchr(b->format, 'x'))) -	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); +	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);  	else  -	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); +	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);  	return PCILIB_ERROR_OUTOFRANGE;      } +    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) { +        for (i = 0; i < (bits?(n+1):n); i++) { +            if ((ctx->views[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) { +                pcilib_error("Accessing invalid register %u (associated view does not provide register functionality)", addr + i); +                return PCILIB_ERROR_INVALID_REQUEST; +            } + +            if ((ctx->views[i]->mode&PCILIB_ACCESS_W) == 0) { +                pcilib_error("Write access is not allowed to register %u", addr + i); +                return PCILIB_ERROR_NOTPERMITED; +            } +        } +    }  +      //err = pcilib_init_register_banks(ctx);      //if (err) return err; diff --git a/pcilib/register.h b/pcilib/register.h index f3df309..0963b22 100644 --- a/pcilib/register.h +++ b/pcilib/register.h @@ -11,9 +11,10 @@  typedef enum { -    PCILIB_REGISTER_STANDARD = 0, -    PCILIB_REGISTER_FIFO, -    PCILIB_REGISTER_BITS +    PCILIB_REGISTER_STANDARD = 0,               /**< Standard register */ +    PCILIB_REGISTER_FIFO,                       /**< FIFO register */ +    PCILIB_REGISTER_BITS,                       /**< Besides a big standard register, the register bit-fields may be described by bit registers */ +    PCILIB_REGISTER_PROPERTY                    /**< A special register bound to a property and gettings/setting it value through it */  } pcilib_register_type_t;  typedef struct { diff --git a/pcilib/view.c b/pcilib/view.c index d14e8aa..e31fdba 100644 --- a/pcilib/view.c +++ b/pcilib/view.c @@ -9,8 +9,11 @@  #include "view.h"  #include "error.h"  #include "value.h" +#include "property.h"  int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc, pcilib_view_context_t **refs) { +    int err; +      size_t i;      void *ptr; @@ -25,6 +28,11 @@ int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_descripti          }      } +    if (!refs) { +        refs = (pcilib_view_context_t**)alloca(n * sizeof(pcilib_view_context_t*)); +        if (!refs) return PCILIB_ERROR_MEMORY; +    } +      if ((ctx->num_views + n + 1) > ctx->alloc_views) {          size_t size;  	pcilib_view_description_t **views; @@ -48,6 +56,7 @@ int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_descripti          pcilib_view_t view = pcilib_find_view_by_name(ctx, v->name);          if (view != PCILIB_VIEW_INVALID) { +            ctx->views[ctx->num_views + i] = NULL;              pcilib_clean_views(ctx, ctx->num_views);              pcilib_error("View %s is already defined in the model", v->name);              return PCILIB_ERROR_EXIST; @@ -55,6 +64,7 @@ int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_descripti          cur = (pcilib_view_description_t*)malloc(v->api->description_size);          if (!cur) { +            ctx->views[ctx->num_views + i] = NULL;              pcilib_clean_views(ctx, ctx->num_views);              return PCILIB_ERROR_MEMORY;          } @@ -68,6 +78,7 @@ int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_descripti          if (!view_ctx) {              free(cur); +            ctx->views[ctx->num_views + i] = NULL;              pcilib_clean_views(ctx, ctx->num_views);              return PCILIB_ERROR_FAILED;          } @@ -85,6 +96,13 @@ int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_descripti      }      ctx->views[ctx->num_views + n] = NULL; + +    err = pcilib_add_registers_from_properties(ctx, n, refs, ctx->views + ctx->num_views); +    if (err) { +        pcilib_clean_views(ctx, ctx->num_views); +        return err; +    } +      ctx->num_views += n;      return 0; diff --git a/pcilib/view.h b/pcilib/view.h index ec775b7..33d4d96 100644 --- a/pcilib/view.h +++ b/pcilib/view.h @@ -12,7 +12,8 @@ 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 */ +    PCILIB_VIEW_FLAG_PROPERTY = 1,                                              /**< Indicates that view does not depend on a value and is independent property */ +    PCILIB_VIEW_FLAG_REGISTER = 2                                               /**< Indicates that view does not depend on a value and should be mapped to the register space */  } pcilib_view_flags_t;  typedef struct { @@ -32,6 +33,7 @@ struct pcilib_view_description_s {      pcilib_access_mode_t mode;                                                  /**< Specifies if the view is read/write-only */      const char *unit;				                                /**< Returned unit (if any) */      const char *name;				                                /**< Name of the view */ +    const char *regname;                                                        /**< Specifies the register name if the view should be mapped to register space */      const char *description;			                                /**< Short description */  }; diff --git a/pcilib/xml.c b/pcilib/xml.c index b022fd8..1238ba8 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -184,12 +184,16 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript                  desc->mode = PCILIB_REGISTER_W;              } else if (!strcasecmp(value, "RW")) {                  desc->mode = PCILIB_REGISTER_RW; -            } else if (!strcasecmp(value, "W")) { -                desc->mode = PCILIB_REGISTER_W;              } else if (!strcasecmp(value, "RW1C")) {                  desc->mode = PCILIB_REGISTER_RW1C;              } else if (!strcasecmp(value, "W1C")) {                  desc->mode = PCILIB_REGISTER_W1C; +            } else if (!strcasecmp(value, "RW1I")) { +                desc->mode = PCILIB_REGISTER_RW1I; +            } else if (!strcasecmp(value, "W1I")) { +                desc->mode = PCILIB_REGISTER_W1I; +            } else if (!strcasecmp(value, "-")) { +                desc->mode = 0;              } else {                  pcilib_error("Invalid access mode (%s) is specified in the XML register description", value);                  return PCILIB_ERROR_INVALID_DATA; @@ -487,11 +491,16 @@ static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDoc          if (!strcasecmp(name, "name")) {                  // Overriden by path -            if (!desc->name) -                desc->name = value; +            if (desc->name) continue; +            if (*value == '/') +	        desc->flags |= PCILIB_VIEW_FLAG_PROPERTY; +            desc->name = value;  	} else if (!strcasecmp(name, "path")) {  	    desc->name = value;  	    desc->flags |= PCILIB_VIEW_FLAG_PROPERTY; +	} else if (!strcasecmp(name, "register")) { +	    desc->regname = value; +	    desc->flags |= PCILIB_VIEW_FLAG_REGISTER;          } else if (!strcasecmp((char*)name, "description")) {      	    desc->description = value;          } else if (!strcasecmp((char*)name, "unit")) { @@ -504,6 +513,19 @@ static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDoc                  pcilib_error("Invalid type (%s) of register view is specified in the XML bank description", value);                  return PCILIB_ERROR_INVALID_DATA;              } +        } else if (!strcasecmp(name, "mode")) { +            if (!strcasecmp(value, "R")) { +                desc->mode = PCILIB_REGISTER_R; +            } else if (!strcasecmp(value, "W")) { +                desc->mode = PCILIB_REGISTER_W; +            } else if (!strcasecmp(value, "RW")) { +                desc->mode = PCILIB_REGISTER_RW; +            } else if (!strcasecmp(value, "-")) { +                desc->mode = 0; +            } else { +                pcilib_error("Invalid access mode (%s) is specified in the XML register description", value); +                return PCILIB_ERROR_INVALID_DATA; +            }          }      } @@ -516,10 +538,12 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp      const char *value, *name;      pcilib_view_context_t *view_ctx; +    pcilib_access_mode_t mode = 0;      pcilib_transform_view_description_t desc = {0};      desc.base.api = &pcilib_transform_view_api;      desc.base.type = PCILIB_TYPE_DOUBLE; +    desc.base.mode = PCILIB_ACCESS_RW;      err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc);      if (err) return err; @@ -540,7 +564,7 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp                  }              }              desc.read_from_reg = value; -            if ((value)&&(*value)) desc.base.mode |= PCILIB_ACCESS_R; +            if ((value)&&(*value)) mode |= PCILIB_ACCESS_R;          } else if (!strcasecmp(name, "write_to_register")) {              if (desc.base.flags&PCILIB_VIEW_FLAG_PROPERTY) {                  if (strstr(value, "$value")) { @@ -549,10 +573,12 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp                  }              }              desc.write_to_reg = value; -            if ((value)&&(*value)) desc.base.mode |= PCILIB_ACCESS_W; +            if ((value)&&(*value)) mode |= PCILIB_ACCESS_W;          }       } +    desc.base.mode &= mode; +      err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);      if (err) return err; diff --git a/pcitool/cli.c b/pcitool/cli.c index 4debb75..1cf59fb 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -706,16 +706,23 @@ void ViewInfo(pcilib_t *handle, pcilib_register_t reg, size_t id) {      if (r) printf(")");      printf("\n"); -    if (r) { -        err = pcilib_read_register_view_by_id(handle, reg, r->views[id].name, &val); +    if (v->mode&PCILIB_ACCESS_R) { +        if (r) { +            err = pcilib_read_register_view_by_id(handle, reg, r->views[id].name, &val); +        } else { +            err = pcilib_get_property(handle, v->name, &val); +        } +        if (!err) err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING);      } else { -        err = pcilib_get_property(handle, v->name, &val); +        err = PCILIB_ERROR_NOTPERMITED;      } -    if (!err) err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING); -    if (err) -        printf("    Current value  : error %i\n", err); -    else { +    if (err) { +        if (err == PCILIB_ERROR_NOTPERMITED) +            printf("    Current value  : no read access\n"); +        else +            printf("    Current value  : error %i\n", err); +    } else {          printf("    Current value  : %s", val.sval);          if (v->unit) printf(" (units: %s)", v->unit);          printf("\n"); @@ -775,15 +782,21 @@ void RegisterInfo(pcilib_t *handle, pcilib_register_t reg) {      pcilib_register_bank_t bank = pcilib_find_register_bank_by_addr(handle, r->bank);      const pcilib_register_bank_description_t *b = &model_info->banks[bank]; -    err = pcilib_read_register_by_id(handle, reg, ®val); +    if (r->mode&PCILIB_ACCESS_R) { +        err = pcilib_read_register_by_id(handle, reg, ®val); +    } else { +        err = PCILIB_ERROR_NOTPERMITED; +    }      info = pcilib_get_register_info(handle, b->name, r->name, 0);      if (!info) Error("Can't obtain register info for %s", r->name);      printf("%s/%s\n", b->name, r->name);      printf("  Current value: "); -    if (err) printf("error %i", err); -    else printf(b->format, regval); +    if (err) { +        if (err == PCILIB_ERROR_NOTPERMITED) printf("no read access"); +        else printf("error %i", err); +    } else printf(b->format, regval);      if (r->mode&PCILIB_REGISTER_W) {  	printf(" (default: "); diff --git a/protocols/CMakeLists.txt b/protocols/CMakeLists.txt index 6c72698..e66ce3a 100644 --- a/protocols/CMakeLists.txt +++ b/protocols/CMakeLists.txt @@ -8,6 +8,6 @@ include_directories(      ${UTHASH_INCLUDE_DIRS}  ) -set(HEADERS ${HEADERS} default.h software.h) +set(HEADERS ${HEADERS} default.h software.h property.h) -add_library(protocols STATIC default.c software.c) +add_library(protocols STATIC default.c software.c property.c) diff --git a/protocols/default.h b/protocols/default.h index c3e6d06..829b65d 100644 --- a/protocols/default.h +++ b/protocols/default.h @@ -1,5 +1,5 @@ -#ifndef _PCILIB_DEFAULT_H -#define _PCILIB_DEFAULT_H +#ifndef _PCILIB_PROTOCOL_DEFAULT_H +#define _PCILIB_PROTOCOL_DEFAULT_H  #include "pcilib.h"  #include "version.h" @@ -13,4 +13,4 @@ const pcilib_register_protocol_api_description_t pcilib_default_protocol_api =      { PCILIB_VERSION, NULL, NULL, pcilib_default_read, pcilib_default_write };  #endif /* _PCILIB_EXPORT_C */ -#endif /* _PCILIB_DEFAULT_H */ +#endif /* _PCILIB_PROTOCOL_DEFAULT_H */ diff --git a/protocols/property.c b/protocols/property.c new file mode 100644 index 0000000..0c7cf5d --- /dev/null +++ b/protocols/property.c @@ -0,0 +1,42 @@ +#include <sys/time.h> +#include <arpa/inet.h> +#include <assert.h> + +#include "pci.h" +#include "tools.h" +#include "model.h" +#include "error.h" + + +int pcilib_property_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *regval) { +    int err; + +    pcilib_view_t view = addr; +    pcilib_value_t val = {0}; + +    if ((view == PCILIB_VIEW_INVALID)||(view >= ctx->num_views)) +        return PCILIB_ERROR_INVALID_ARGUMENT; + +    err = pcilib_get_property(ctx, ctx->views[view]->name, &val); +    if (err) return err; + +    *regval = pcilib_get_value_as_register_value(ctx, &val, &err); + +    return err; +} + + +int pcilib_property_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t regval) { +    int err; + +    pcilib_view_t view = addr; +    pcilib_value_t val = {0}; + +    if ((view == PCILIB_VIEW_INVALID)||(view >= ctx->num_views)) +        return PCILIB_ERROR_INVALID_ARGUMENT; + +    err = pcilib_set_value_from_register_value(ctx, &val, regval); +    if (err) return err; + +    return pcilib_set_property(ctx, ctx->views[view]->name, &val); +} diff --git a/protocols/property.h b/protocols/property.h new file mode 100644 index 0000000..3d3eb63 --- /dev/null +++ b/protocols/property.h @@ -0,0 +1,16 @@ +#ifndef _PCILIB_PROTOCOL_PROPERTY_H +#define _PCILIB_PROTOCOL_PROPERTY_H + +#include "pcilib.h" +#include "version.h" +#include "model.h" + +int pcilib_property_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); +int pcilib_property_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); + +#ifdef _PCILIB_EXPORT_C +const pcilib_register_protocol_api_description_t pcilib_property_protocol_api = +    { PCILIB_VERSION, NULL, NULL, pcilib_property_registers_read, pcilib_property_registers_write }; +#endif /* _PCILIB_EXPORT_C */ + +#endif /* _PCILIB_PROTOCOL_PROPERTY_H */ diff --git a/protocols/software.h b/protocols/software.h index 484e344..27ab86e 100644 --- a/protocols/software.h +++ b/protocols/software.h @@ -3,8 +3,8 @@   * @brief header file for implementation of the protocol with software registers allocated in the kernel space, for parameters sharing between concurrent pcitool instances   */ -#ifndef _PCILIB_SOFTWARE_H -#define _PCILIB_SOFTWARE_H +#ifndef _PCILIB_PROTOCOL_SOFTWARE_H +#define _PCILIB_PROTOCOL_SOFTWARE_H  #include "pcilib.h"  #include "version.h" @@ -51,8 +51,8 @@ int pcilib_software_registers_write(pcilib_t *ctx,pcilib_register_bank_context_t  /**   * software protocol addition to the protocol api.   */ -const pcilib_register_protocol_api_description_t pcilib_register_software_protocol_api = +const pcilib_register_protocol_api_description_t pcilib_software_protocol_api =    { PCILIB_VERSION, pcilib_software_registers_open, pcilib_software_registers_close,pcilib_software_registers_read, pcilib_software_registers_write }; /**< we add there the protocol to the list of possible protocols*/  #endif /* _PCILIB_EXPORT_C */ -#endif /* _PCILIB_SOFTWARE_H */ +#endif /* _PCILIB_PROTOCOL_SOFTWARE_H */ diff --git a/xml/test/camera.xml b/xml/test/camera.xml index 81335b7..a84299a 100644 --- a/xml/test/camera.xml +++ b/xml/test/camera.xml @@ -106,7 +106,7 @@      <register address="0x1b0" offset="0" size="32" default="0" rwmask="0" mode="R" name="ddr_num_frames"/>    </bank>    <bank bar="0" size="0x0200" protocol="software_registers" read_address="0x0" write_address="0x0" word_size="32" endianess="little" format="0x%lx" name="dma" description="DMA Registers"/> -  <transform path="/test/prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/sensor_temperature:C} - 27315./100" write_to_register="(${/registers/fpga/sensor_temperature:C} + 27315./100)*(1024000./503975)" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/> +  <transform path="/test/prop1" register="test_prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/sensor_temperature:C} - 27315./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>    <transform name="formuu1" unit="C" read_from_register="(503975./1024000)*$value - 27315./100" write_to_register="($value + 27315./100)*(1024000./503975)" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>    <transform name="formuu2" unit="C1" read_from_register="((1./4)*($value - 1200)) if $freq==0 else ((3./10)*($value - 1000))" write_to_register="4*$value + 1200 if $freq==0 else (10./3)*$value + 1000" description="formula to get real sensor temperature from the sensor_temperature register in decimal"/>    <transform name="formuu3" unit="us" read_from_register="($value+(43./100))*129./(40*1000000)if $freq==0 else ($value+(43./100))*129./(48*1000000)" write_to_register="$value/129.*(40*1000000) - 43./100 if $freq==0 else $value/129.*(48*1000000) - 43./100" description="formula to get real exposure time from the cmosis_exp_time register in decimal"/> diff --git a/xml/types.xsd b/xml/types.xsd index edcfb08..78be773 100644 --- a/xml/types.xsd +++ b/xml/types.xsd @@ -58,6 +58,7 @@      <xsd:attribute name="name" type="xsd:ID" />      <xsd:attribute name="unit" type="xsd:string" />      <xsd:attribute name="type" type="pcilib_data_type_t" /> +    <xsd:attribute name="mode" type="pcilib_access_mode_t" />      <xsd:attribute name="visible" type="bool_t" default="0" />      <xsd:attribute name="description" type="xsd:string" />    </xsd:complexType> @@ -66,6 +67,7 @@      <xsd:complexContent>          <xsd:extension base="pcilib_view_t">            <xsd:attribute name="path" type="xsd:string" /> +          <xsd:attribute name="register" type="xsd:string" />            <xsd:attribute name="read_from_register" type="xsd:string" />            <xsd:attribute name="write_to_register" type="xsd:string" />            <!-- xsd 1.1 <xsd:assert test="(@path and not(@name)) or (not(@path) and @name)"/> --> @@ -180,13 +182,24 @@        <xsd:enumeration value="dma3"/>      </xsd:restriction>    </xsd:simpleType> +  <xsd:simpleType name="pcilib_access_mode_t"> +    <xsd:restriction base="xsd:string"> +      <xsd:enumeration value="-"/> +      <xsd:enumeration value="R"/> +      <xsd:enumeration value="W"/> +      <xsd:enumeration value="RW"/> +    </xsd:restriction> +  </xsd:simpleType>    <xsd:simpleType name="pcilib_register_mode_t">      <xsd:restriction base="xsd:string"> +      <xsd:enumeration value="-"/>        <xsd:enumeration value="R"/>        <xsd:enumeration value="W"/>        <xsd:enumeration value="RW"/>        <xsd:enumeration value="W1C"/>        <xsd:enumeration value="RW1C"/> +      <xsd:enumeration value="W1I"/> +      <xsd:enumeration value="RW1I"/>      </xsd:restriction>    </xsd:simpleType>    <xsd:simpleType name="pcilib_data_type_t"> | 
