summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-10-19 15:58:46 +0200
committerSuren A. Chilingaryan <csa@suren.me>2015-10-19 15:58:46 +0200
commit55255f2ce3a2234850249efcabd9ba32d0a89a9c (patch)
tree586d075665bebbb698e3a84eee6595f47401997f
parent87ef1499bfcaa0ea2a58cb6d3c327162507f6ac8 (diff)
downloadpcitool-55255f2ce3a2234850249efcabd9ba32d0a89a9c.tar.gz
pcitool-55255f2ce3a2234850249efcabd9ba32d0a89a9c.tar.bz2
pcitool-55255f2ce3a2234850249efcabd9ba32d0a89a9c.tar.xz
pcitool-55255f2ce3a2234850249efcabd9ba32d0a89a9c.zip
Support computed (property-based) registers
-rw-r--r--pcilib/bank.h6
-rw-r--r--pcilib/export.c9
-rw-r--r--pcilib/export.h2
-rw-r--r--pcilib/property.c34
-rw-r--r--pcilib/property.h20
-rw-r--r--pcilib/register.c65
-rw-r--r--pcilib/register.h7
-rw-r--r--pcilib/view.c18
-rw-r--r--pcilib/view.h4
-rw-r--r--pcilib/xml.c38
-rw-r--r--pcitool/cli.c33
-rw-r--r--protocols/CMakeLists.txt4
-rw-r--r--protocols/default.h6
-rw-r--r--protocols/property.c42
-rw-r--r--protocols/property.h16
-rw-r--r--protocols/software.h8
-rw-r--r--xml/test/camera.xml2
-rw-r--r--xml/types.xsd13
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, &regval);
+ if (r->mode&PCILIB_ACCESS_R) {
+ err = pcilib_read_register_by_id(handle, reg, &regval);
+ } 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">