summaryrefslogtreecommitdiffstats
path: root/pcilib
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-10-18 07:36:47 +0200
committerSuren A. Chilingaryan <csa@suren.me>2015-10-18 07:36:47 +0200
commitfa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b (patch)
tree80f82fdbeaf8d2f94c5a1a48ea28a5e452b561f5 /pcilib
parent6a4a556b15bda7e0c737f247c8282c1b3a9d1e0d (diff)
downloadpcitool-fa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b.tar.gz
pcitool-fa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b.tar.bz2
pcitool-fa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b.tar.xz
pcitool-fa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b.zip
Support reading/writting register views by id
Diffstat (limited to 'pcilib')
-rw-r--r--pcilib/bank.c19
-rw-r--r--pcilib/bank.h4
-rw-r--r--pcilib/pcilib.h6
-rw-r--r--pcilib/property.c14
-rw-r--r--pcilib/register.c29
-rw-r--r--pcilib/view.c73
-rw-r--r--pcilib/view.h14
-rw-r--r--pcilib/xml.c28
-rw-r--r--pcilib/xml.h3
9 files changed, 169 insertions, 21 deletions
diff --git a/pcilib/bank.c b/pcilib/bank.c
index ec38c82..efaa810 100644
--- a/pcilib/bank.c
+++ b/pcilib/bank.c
@@ -242,7 +242,6 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch
return PCILIB_REGISTER_INVALID;
};
-
pcilib_register_protocol_t pcilib_find_register_protocol_by_addr(pcilib_t *ctx, pcilib_register_protocol_addr_t protocol) {
pcilib_register_protocol_t i;
@@ -272,3 +271,21 @@ pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const ch
return pcilib_find_register_protocol_by_name(ctx, protocol);
}
+
+int pcilib_get_register_bank_attr_by_id(pcilib_t *ctx, pcilib_register_bank_t bank, const char *attr, pcilib_value_t *val) {
+ assert(bank < ctx->num_banks);
+
+ return pcilib_get_xml_attr(ctx, ctx->bank_ctx[bank]->xml, attr, val);
+}
+
+int pcilib_get_register_bank_attr(pcilib_t *ctx, const char *bankname, const char *attr, pcilib_value_t *val) {
+ pcilib_register_bank_t bank;
+
+ bank = pcilib_find_register_bank_by_name(ctx, bankname);
+ if (bank == PCILIB_REGISTER_BANK_INVALID) {
+ pcilib_error("Bank (%s) is not found", bankname);
+ return PCILIB_ERROR_NOTFOUND;
+ }
+
+ return pcilib_get_register_bank_attr_by_id(ctx, bank, attr, val);
+}
diff --git a/pcilib/bank.h b/pcilib/bank.h
index 39dd79c..ba149b9 100644
--- a/pcilib/bank.h
+++ b/pcilib/bank.h
@@ -153,7 +153,6 @@ int pcilib_add_register_protocols(pcilib_t *ctx, pcilib_model_modification_flags
*/
int pcilib_add_register_ranges(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_range_t *ranges);
-
pcilib_register_bank_t pcilib_find_register_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank);
pcilib_register_bank_t pcilib_find_register_bank_by_name(pcilib_t *ctx, const char *bankname);
pcilib_register_bank_t pcilib_find_register_bank(pcilib_t *ctx, const char *bank);
@@ -162,6 +161,9 @@ pcilib_register_protocol_t pcilib_find_register_protocol_by_addr(pcilib_t *ctx,
pcilib_register_protocol_t pcilib_find_register_protocol_by_name(pcilib_t *ctx, const char *name);
pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const char *name);
+
+int pcilib_get_register_bank_attr_by_id(pcilib_t *ctx, pcilib_register_bank_t bank, const char *attr, pcilib_value_t *val);
+
#ifdef __cplusplus
}
#endif
diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h
index e4fdf6d..b2837a9 100644
--- a/pcilib/pcilib.h
+++ b/pcilib/pcilib.h
@@ -241,6 +241,8 @@ int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, p
int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value);
int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, pcilib_value_t *value);
int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *unit, const pcilib_value_t *value);
+int pcilib_read_register_view_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *view, pcilib_value_t *val);
+int pcilib_write_register_view_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *view, const pcilib_value_t *valarg);
void pcilib_clean_value(pcilib_t *ctx, pcilib_value_t *val);
int pcilib_copy_value(pcilib_t *ctx, pcilib_value_t *dst, const pcilib_value_t *src);
@@ -259,6 +261,10 @@ void pcilib_free_property_info(pcilib_t *ctx, pcilib_property_info_t *info);
int pcilib_get_property(pcilib_t *ctx, const char *prop, pcilib_value_t *val);
int pcilib_set_property(pcilib_t *ctx, const char *prop, const pcilib_value_t *val);
+int pcilib_get_property_attr(pcilib_t *ctx, const char *prop, const char *attr, pcilib_value_t *val);
+int pcilib_get_register_attr_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *attr, pcilib_value_t *val);
+int pcilib_get_register_attr(pcilib_t *ctx, const char *bank, const char *regname, const char *attr, pcilib_value_t *val);
+int pcilib_get_register_bank_attr(pcilib_t *ctx, const char *bankname, const char *attr, pcilib_value_t *val);
int pcilib_reset(pcilib_t *ctx);
int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data);
diff --git a/pcilib/property.c b/pcilib/property.c
index 1db6dd3..276360a 100644
--- a/pcilib/property.c
+++ b/pcilib/property.c
@@ -206,3 +206,17 @@ int pcilib_get_property(pcilib_t *ctx, const char *prop, pcilib_value_t *val) {
int pcilib_set_property(pcilib_t *ctx, const char *prop, const pcilib_value_t *val) {
return pcilib_write_register_view(ctx, NULL, NULL, prop, val);
}
+
+int pcilib_get_property_attr(pcilib_t *ctx, const char *prop, const char *attr, pcilib_value_t *val) {
+ pcilib_view_context_t *view_ctx;
+
+ view_ctx = pcilib_find_view_context_by_name(ctx, prop);
+ if (!view_ctx) {
+ pcilib_error("The specified property (%s) is not found", prop);
+ return PCILIB_ERROR_NOTFOUND;
+ }
+
+ if (!view_ctx->xml) return NULL;
+
+ return pcilib_get_xml_attr(ctx, view_ctx->xml, attr, val);
+}
diff --git a/pcilib/register.c b/pcilib/register.c
index 30505ae..2752d47 100644
--- a/pcilib/register.c
+++ b/pcilib/register.c
@@ -385,3 +385,32 @@ int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname,
return pcilib_write_register_by_id(ctx, reg, value);
}
+
+
+int pcilib_get_register_attr_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *attr, pcilib_value_t *val) {
+ int err;
+
+ assert(reg < ctx->num_reg);
+
+ err = pcilib_get_xml_attr(ctx, ctx->register_ctx[reg].xml, attr, val);
+/*
+ // Shall we return from parrent register if not found?
+ if ((err == PCILIB_ERROR_NOTFOUND)&&(ctx->registers[reg].type == PCILIB_REGISTER_TYPE_BITS)) {
+ pcilib_register_t parent = pcilib_find_standard_register_by_addr(ctx, ctx->registers[reg].addr);
+ err = pcilib_get_xml_attr(ctx, ctx->register_ctx[parent].xml, attr, val);
+ }
+*/
+ return err;
+}
+
+int pcilib_get_register_attr(pcilib_t *ctx, const char *bank, const char *regname, const char *attr, pcilib_value_t *val) {
+ pcilib_register_t reg;
+
+ reg = pcilib_find_register(ctx, bank, regname);
+ if (reg == PCILIB_REGISTER_INVALID) {
+ pcilib_error("Register (%s) is not found", regname);
+ return PCILIB_ERROR_NOTFOUND;
+ }
+
+ return pcilib_get_register_attr_by_id(ctx, reg, attr, val);
+}
diff --git a/pcilib/view.c b/pcilib/view.c
index 8df5fc4..d14e8aa 100644
--- a/pcilib/view.c
+++ b/pcilib/view.c
@@ -10,7 +10,7 @@
#include "error.h"
#include "value.h"
-int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc) {
+int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc, pcilib_view_context_t **refs) {
size_t i;
void *ptr;
@@ -76,6 +76,8 @@ int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *d
view_ctx->view = ctx->num_views + i;
view_ctx->name = v->name;
+ if (refs) refs[i] = view_ctx;
+
HASH_ADD_KEYPTR(hh, ctx->view_hash, view_ctx->name, strlen(view_ctx->name), view_ctx);
ctx->views[ctx->num_views + i] = cur;
@@ -88,6 +90,11 @@ int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *d
return 0;
}
+int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc) {
+ return pcilib_add_views_custom(ctx, n, desc, NULL);
+}
+
+
void pcilib_clean_views(pcilib_t *ctx, pcilib_view_t start) {
pcilib_view_t i;
pcilib_view_context_t *view_ctx, *tmp;
@@ -201,17 +208,16 @@ typedef struct {
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, const char *unit_cname, int write_direction, pcilib_view_configuration_t *cfg) {
+static int pcilib_detect_view_configuration(pcilib_t *ctx, pcilib_register_t reg, const char *view_cname, const char *unit_cname, int write_direction, pcilib_view_configuration_t *cfg) {
int err = 0;
pcilib_view_t view;
+ const char *regname;
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);
const char *unit_name;
-
strcpy(view_name, view_cname);
if (unit_cname) unit_name = unit_cname;
@@ -223,14 +229,10 @@ static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, con
}
}
+ if (reg == PCILIB_REGISTER_INVALID) regname = NULL;
+ else regname = ctx->registers[reg].name;
if (regname) {
- reg = pcilib_find_register(ctx, bank, regname);
- if (reg == PCILIB_REGISTER_INVALID) {
- pcilib_error("Can't find the specified register %s", regname);
- return PCILIB_ERROR_NOTFOUND;
- }
-
if (unit_name) view_ctx = pcilib_find_register_view_context_by_name(ctx, reg, view_name);
else err = pcilib_detect_register_view_and_unit(ctx, reg, view_name, write_direction, &view_ctx, &trans);
@@ -267,15 +269,19 @@ static int pcilib_detect_view_configuration(pcilib_t *ctx, const char *bank, con
return 0;
}
-
-int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, pcilib_value_t *val) {
+int pcilib_read_register_view_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *view, pcilib_value_t *val) {
int err;
+ const char *regname;
+
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, NULL, 0, &cfg);
+ if (reg == PCILIB_REGISTER_INVALID) regname = NULL;
+ else regname = ctx->registers[reg].name;
+
+ err = pcilib_detect_view_configuration(ctx, reg, view, NULL, 0, &cfg);
if (err) return err;
v = ctx->views[cfg.view->view];
@@ -321,16 +327,37 @@ int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regna
return 0;
}
+int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, pcilib_value_t *val) {
+ pcilib_register_t reg;
+
+ if (regname) {
+ reg = pcilib_find_register(ctx, bank, regname);
+ if (reg == PCILIB_REGISTER_INVALID) {
+ pcilib_error("Register (%s) is not found", regname);
+ return PCILIB_ERROR_NOTFOUND;
+ }
+ } else {
+ reg = PCILIB_REGISTER_INVALID;
+ }
+
+ return pcilib_read_register_view_by_id(ctx, reg, view, val);
+}
+
-int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, const pcilib_value_t *valarg) {
+int pcilib_write_register_view_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *view, const pcilib_value_t *valarg) {
int err;
pcilib_value_t val = {0};
+ const char *regname;
+
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, valarg->unit, 1, &cfg);
+ if (reg == PCILIB_REGISTER_INVALID) regname = NULL;
+ else regname = ctx->registers[reg].name;
+
+ err = pcilib_detect_view_configuration(ctx, reg, view, valarg->unit, 1, &cfg);
if (err) return err;
v = ctx->views[cfg.view->view];
@@ -378,3 +405,19 @@ int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regn
return 0;
}
+
+int pcilib_write_register_view(pcilib_t *ctx, const char *bank, const char *regname, const char *view, const pcilib_value_t *val) {
+ pcilib_register_t reg;
+
+ if (regname) {
+ reg = pcilib_find_register(ctx, bank, regname);
+ if (reg == PCILIB_REGISTER_INVALID) {
+ pcilib_error("Register (%s) is not found", regname);
+ return PCILIB_ERROR_NOTFOUND;
+ }
+ } else {
+ reg = PCILIB_REGISTER_INVALID;
+ }
+
+ return pcilib_write_register_view_by_id(ctx, reg, view, val);
+}
diff --git a/pcilib/view.h b/pcilib/view.h
index 606a688..ec775b7 100644
--- a/pcilib/view.h
+++ b/pcilib/view.h
@@ -38,6 +38,7 @@ struct pcilib_view_description_s {
struct pcilib_view_context_s {
const char *name;
pcilib_view_t view;
+ pcilib_xml_node_t *xml;
UT_hash_handle hh;
};
@@ -58,6 +59,19 @@ extern "C" {
int pcilib_add_views(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc);
/**
+ * Use this function to add new view definitions into the model. It is error to re-register
+ * already registered view. The function will copy the context of unit description, but name,
+ * transform, and other strings in the structure are considered to have static duration
+ * and will not be copied. On error no new views are initalized.
+ * @param[in,out] ctx - pcilib context
+ * @param[in] n - number of views to initialize. It is OK to pass 0 if protocols variable is NULL terminated (last member of protocols array have all members set to 0)
+ * @param[in] desc - view descriptions
+ * @param[out] refs - fills allocated view contexts. On error context is undefined.
+ * @return - error or 0 on success
+ */
+int pcilib_add_views_custom(pcilib_t *ctx, size_t n, const pcilib_view_description_t *desc, pcilib_view_context_t **refs);
+
+/**
* Destroys data associated with views. This is an internal function and will
* be called during clean-up.
* @param[in,out] ctx - pcilib context
diff --git a/pcilib/xml.c b/pcilib/xml.c
index 4ecd16d..09e7cba 100644
--- a/pcilib/xml.c
+++ b/pcilib/xml.c
@@ -516,6 +516,7 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp
int err;
xmlAttrPtr cur;
const char *value, *name;
+ pcilib_view_context_t *view_ctx;
pcilib_transform_view_description_t desc = {0};
@@ -554,8 +555,11 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp
}
}
+ err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);
+ if (err) return err;
- return pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
+ view_ctx->xml = node;
+ return 0;
}
@@ -626,6 +630,7 @@ static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath,
xmlXPathObjectPtr nodes;
xmlNodeSetPtr nodeset;
+ pcilib_view_context_t *view_ctx;
pcilib_enum_view_description_t desc = {0};
desc.base.type = PCILIB_TYPE_STRING;
@@ -676,9 +681,13 @@ static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath,
xmlXPathFreeObject(nodes);
- err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc);
- if (err) free(desc.names);
- return err;
+ err = pcilib_add_views_custom(ctx, 1, (pcilib_view_description_t*)&desc, &view_ctx);
+ if (err) {
+ free(desc.names);
+ return err;
+ }
+ view_ctx->xml = node;
+ return 0;
}
static int pcilib_xml_parse_unit_transform(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_unit_transform_t *desc) {
@@ -1064,3 +1073,14 @@ void pcilib_free_xml(pcilib_t *ctx) {
xmlMemoryDump();
*/
}
+
+int pcilib_get_xml_attr(pcilib_t *ctx, pcilib_xml_node_t *node, const char *attr, pcilib_value_t *val) {
+ xmlAttr *prop;
+ xmlChar *str;
+
+ prop = xmlHasProp(node, BAD_CAST attr);
+ if ((!prop)||(!prop->children)) return PCILIB_ERROR_NOTFOUND;
+
+ str = prop->children->content;
+ return pcilib_set_value_from_static_string(ctx, val, (const char*)str);
+}
diff --git a/pcilib/xml.h b/pcilib/xml.h
index 6ad8676..10bc154 100644
--- a/pcilib/xml.h
+++ b/pcilib/xml.h
@@ -59,6 +59,9 @@ void pcilib_free_xml(pcilib_t *ctx);
*/
int pcilib_process_xml(pcilib_t *ctx, const char *location);
+int pcilib_get_xml_attr(pcilib_t *ctx, pcilib_xml_node_t *node, const char *attr, pcilib_value_t *val);
+
+
#ifdef __cplusplus
}
#endif