summaryrefslogtreecommitdiffstats
path: root/pcilib
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-10-19 06:59:53 +0200
committerSuren A. Chilingaryan <csa@suren.me>2015-10-19 06:59:53 +0200
commit8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf (patch)
treeef9eb3a20cc6da36ff6c875dc6221ec0b6af780c /pcilib
parentfa54d4c2ca8ffcece7a9c6e9c784e2150cbed78b (diff)
downloadpcitool-8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf.tar.gz
pcitool-8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf.tar.bz2
pcitool-8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf.tar.xz
pcitool-8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf.zip
Provide register listings in public API
Diffstat (limited to 'pcilib')
-rw-r--r--pcilib/pcilib.h68
-rw-r--r--pcilib/register.c88
-rw-r--r--pcilib/register.h11
-rw-r--r--pcilib/xml.c18
4 files changed, 149 insertions, 36 deletions
diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h
index b2837a9..dbf837d 100644
--- a/pcilib/pcilib.h
+++ b/pcilib/pcilib.h
@@ -35,9 +35,9 @@ typedef enum {
} pcilib_log_priority_t;
typedef enum {
- PCILIB_HOST_ENDIAN = 0,
- PCILIB_LITTLE_ENDIAN,
- PCILIB_BIG_ENDIAN
+ PCILIB_HOST_ENDIAN = 0, /**< The same byte ordering as on the host system running the driver */
+ PCILIB_LITTLE_ENDIAN, /**< x86 is Little-endian, least significant bytes are at the lower addresses */
+ PCILIB_BIG_ENDIAN /**< Old mainframes and network byte order, most significant bytes are at the lower addresses */
} pcilib_endianess_t;
typedef enum {
@@ -47,6 +47,16 @@ typedef enum {
} pcilib_access_mode_t;
typedef enum {
+ PCILIB_REGISTER_R = 1, /**< reading from register is allowed */
+ PCILIB_REGISTER_W = 2, /**< normal writting to register is allowed */
+ PCILIB_REGISTER_RW = 3,
+ PCILIB_REGISTER_W1C = 4, /**< writting 1 resets the bit, writting 0 keeps the value */
+ PCILIB_REGISTER_RW1C = 5,
+ PCILIB_REGISTER_W1I = 8, /**< writting 1 inversts the bit, writting 0 keeps the value */
+ PCILIB_REGISTER_RW1I = 9,
+} pcilib_register_mode_t;
+
+typedef enum {
PCILIB_TYPE_INVALID = 0, /**< uninitialized */
PCILIB_TYPE_DEFAULT = 0, /**< default type */
PCILIB_TYPE_STRING = 1, /**< char* */
@@ -102,14 +112,6 @@ typedef enum {
PCILIB_EVENT_INFO_FLAG_BROKEN = 1 /**< Indicates broken frames (if this flag is fales, the frame still can be broken) */
} pcilib_event_info_flags_t;
-typedef struct {
- pcilib_event_t type;
- uint64_t seqnum; /**< we will add seqnum_overflow if required */
- uint64_t offset; /**< nanoseconds */
- struct timeval timestamp; /**< most accurate timestamp */
- pcilib_event_info_flags_t flags; /**< flags */
-} pcilib_event_info_t;
-
typedef enum {
PCILIB_LIST_FLAGS_DEFAULT = 0,
PCILIB_LIST_FLAG_CHILDS = 1 /**< Request all sub-elements or indicated that sub-elements are available */
@@ -133,6 +135,27 @@ typedef struct {
} pcilib_value_t;
typedef struct {
+ pcilib_register_value_t min, max; /**< Minimum and maximum allowed values */
+} pcilib_register_value_range_t;
+
+typedef struct {
+ pcilib_register_value_t value; /**< This value will get assigned instead of the name */
+ pcilib_register_value_t min, max; /**< the values in the specified range are aliased by name */
+ const char *name; /**< corresponding string to value */
+} pcilib_register_value_name_t;
+
+typedef struct {
+ pcilib_register_t id; /**< Direct register ID which can be used in API calls */
+ const char *name; /**< The access name of the register */
+ const char *description; /**< Brief description of the register */
+ const char *bank; /**< The name of the bank register belongs to */
+ pcilib_register_mode_t mode; /**< Register access (ro/wo/rw) and how writting to register works (clearing/inverting set bits) */
+ pcilib_register_value_t defvalue; /**< Default register value */
+ const pcilib_register_value_range_t *range; /**< Specifies default, minimum, and maximum values */
+ const pcilib_register_value_name_t *values; /**< The list of enum names for the register value */
+} pcilib_register_info_t;
+
+typedef struct {
const char *name; /**< Name of the property view */
const char *path; /**< Full path to the property */
const char *description; /**< Short description */
@@ -142,6 +165,14 @@ typedef struct {
const char *unit; /**< Returned unit (if any) */
} pcilib_property_info_t;
+typedef struct {
+ pcilib_event_t type;
+ uint64_t seqnum; /**< we will add seqnum_overflow if required */
+ uint64_t offset; /**< nanoseconds */
+ struct timeval timestamp; /**< most accurate timestamp */
+ pcilib_event_info_flags_t flags; /**< flags */
+} pcilib_event_info_t;
+
#define PCILIB_BAR_DETECT ((pcilib_bar_t)-1)
#define PCILIB_BAR_INVALID ((pcilib_bar_t)-1)
@@ -194,11 +225,19 @@ extern "C" {
#endif
+
int pcilib_set_logger(pcilib_log_priority_t min_prio, pcilib_logger_t logger, void *arg);
pcilib_t *pcilib_open(const char *device, const char *model);
void pcilib_close(pcilib_t *ctx);
+pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *branch, pcilib_list_flags_t flags);
+void pcilib_free_property_info(pcilib_t *ctx, pcilib_property_info_t *info);
+pcilib_register_info_t *pcilib_get_register_list(pcilib_t *ctx, const char *bank, pcilib_list_flags_t flags);
+pcilib_register_info_t *pcilib_get_register_info(pcilib_t *ctx, const char *req_bank_name, const char *req_reg_name, pcilib_list_flags_t flags);
+void pcilib_free_register_info(pcilib_t *ctx, pcilib_register_info_t *info);
+
+
int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
@@ -243,6 +282,8 @@ int pcilib_read_register_view(pcilib_t *ctx, const char *bank, const char *regna
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);
+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);
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);
@@ -256,11 +297,6 @@ pcilib_register_value_t pcilib_get_value_as_register_value(pcilib_t *ctx, const
int pcilib_convert_value_unit(pcilib_t *ctx, pcilib_value_t *val, const char *unit_name);
int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_type_t type);
-pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *branch, pcilib_list_flags_t flags);
-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);
diff --git a/pcilib/register.c b/pcilib/register.c
index 2752d47..08af871 100644
--- a/pcilib/register.c
+++ b/pcilib/register.c
@@ -19,6 +19,7 @@
#include "tools.h"
#include "error.h"
#include "property.h"
+#include "views/enum.h"
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) {
// DS: Overrride existing registers
@@ -414,3 +415,90 @@ int pcilib_get_register_attr(pcilib_t *ctx, const char *bank, const char *regnam
return pcilib_get_register_attr_by_id(ctx, reg, attr, val);
}
+
+pcilib_register_info_t *pcilib_get_register_info(pcilib_t *ctx, const char *req_bank_name, const char *req_reg_name, pcilib_list_flags_t flags) {
+ pcilib_register_t i, from, to, pos = 0;
+ pcilib_register_info_t *info;
+ pcilib_register_bank_t bank;
+ pcilib_register_bank_addr_t bank_addr;
+ const char *bank_name;
+
+ info = (pcilib_register_info_t*)malloc((ctx->num_reg + 1) * sizeof(pcilib_register_info_t));
+ if (!info) return NULL;
+
+ if (req_bank_name) {
+ bank = pcilib_find_register_bank_by_name(ctx, req_bank_name);
+ if (bank == PCILIB_REGISTER_BANK_INVALID) {
+ pcilib_error("The specified bank (%s) is not found", req_bank_name);
+ return NULL;
+ }
+ bank_addr = ctx->banks[bank].addr;
+ bank_name = req_bank_name;
+ } else {
+ bank_addr = PCILIB_REGISTER_BANK_INVALID;
+ bank_name = NULL;
+ }
+
+ if (req_reg_name) {
+ pcilib_register_t reg = pcilib_find_register(ctx, req_bank_name, req_reg_name);
+ if (reg == PCILIB_REGISTER_INVALID) {
+ pcilib_error("The specified register (%s) is not found", req_reg_name);
+ return NULL;
+ }
+ from = reg;
+ to = reg + 1;
+ } else {
+ from = 0;
+ to = ctx->num_reg;
+ }
+
+ for (i = from; i < to; i++) {
+ const pcilib_register_value_range_t *range = &ctx->register_ctx[i].range;
+ const pcilib_register_value_name_t *names = NULL;
+
+ if (req_bank_name) {
+ if (ctx->registers[i].bank != bank_addr) continue;
+ } else {
+ if (ctx->registers[i].bank != bank_addr) {
+ bank_addr = ctx->registers[i].bank;
+ bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);
+ if (bank == PCILIB_REGISTER_BANK_INVALID) bank_name = NULL;
+ else bank_name = ctx->banks[bank].name;
+ }
+ }
+
+ if (ctx->registers[i].views) {
+ int j;
+ for (j = 0; ctx->registers[i].views[j].view; j++) {
+ pcilib_view_t view = pcilib_find_view_by_name(ctx, ctx->registers[i].views[j].view);
+ if ((view != PCILIB_VIEW_INVALID)&&((ctx->views[view]->api == &pcilib_enum_view_xml_api)||(ctx->views[view]->api == &pcilib_enum_view_static_api)))
+ names = ((pcilib_enum_view_description_t*)(ctx->views[view]))->names;
+ }
+ }
+
+ if (range->min == range->max)
+ range = NULL;
+
+ info[pos++] = (pcilib_register_info_t){
+ .id = i,
+ .name = ctx->registers[i].name,
+ .description = ctx->registers[i].description,
+ .bank = bank_name,
+ .mode = ctx->registers[i].mode,
+ .defvalue = ctx->registers[i].defvalue,
+ .range = range,
+ .values = names
+ };
+ }
+ memset(&info[pos], 0, sizeof(pcilib_register_info_t));
+ return info;
+}
+
+pcilib_register_info_t *pcilib_get_register_list(pcilib_t *ctx, const char *req_bank_name, pcilib_list_flags_t flags) {
+ return pcilib_get_register_info(ctx, req_bank_name, NULL, flags);
+}
+
+void pcilib_free_register_info(pcilib_t *ctx, pcilib_register_info_t *info) {
+ if (info)
+ free(info);
+}
diff --git a/pcilib/register.h b/pcilib/register.h
index e2e8508..f3df309 100644
--- a/pcilib/register.h
+++ b/pcilib/register.h
@@ -9,15 +9,6 @@
#define PCILIB_REGISTER_NO_BITS 0
#define PCILIB_REGISTER_ALL_BITS ((pcilib_register_value_t)-1)
-typedef enum {
- PCILIB_REGISTER_R = 1, /**< reading from register is allowed */
- PCILIB_REGISTER_W = 2, /**< normal writting to register is allowed */
- PCILIB_REGISTER_RW = 3,
- PCILIB_REGISTER_W1C = 4, /**< writting 1 resets the bit, writting 0 keeps the value */
- PCILIB_REGISTER_RW1C = 5,
- PCILIB_REGISTER_W1I = 8, /**< writting 1 inversts the bit, writting 0 keeps the value */
- PCILIB_REGISTER_RW1I = 9,
-} pcilib_register_mode_t;
typedef enum {
PCILIB_REGISTER_STANDARD = 0,
@@ -55,7 +46,7 @@ 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_register_value_range_t range; /**< 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;
diff --git a/pcilib/xml.c b/pcilib/xml.c
index 09e7cba..b9deed2 100644
--- a/pcilib/xml.c
+++ b/pcilib/xml.c
@@ -61,7 +61,7 @@ static const char *pcilib_xml_enum_view_unit = "name";
typedef struct {
pcilib_register_description_t base;
- pcilib_register_value_t min, max;
+ pcilib_register_value_range_t range;
} pcilib_xml_register_description_t;
/*
@@ -156,14 +156,14 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
return PCILIB_ERROR_INVALID_DATA;
}
- xml_desc->min = min;
+ xml_desc->range.min = min;
} else if (!strcasecmp(name, "max")) {
pcilib_register_value_t max = strtol(value, &endptr, 0);
if ((strlen(endptr) > 0)) {
pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value);
return PCILIB_ERROR_INVALID_DATA;
}
- xml_desc->max = max;
+ xml_desc->range.max = max;
} else if (!strcasecmp((char*)name,"rwmask")) {
if (!strcasecmp(value, "all")) {
desc->rwmask = PCILIB_REGISTER_ALL_BITS;
@@ -275,8 +275,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank
}
ctx->register_ctx[reg].xml = node;
- ctx->register_ctx[reg].min = desc.min;
- ctx->register_ctx[reg].max = desc.max;
+ memcpy(&ctx->register_ctx[reg].range, &desc.range, sizeof(pcilib_register_value_range_t));
ctx->register_ctx[reg].views = desc.base.views;
@@ -319,8 +318,7 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank
}
ctx->register_ctx[reg].xml = nodeset->nodeTab[i];
- ctx->register_ctx[reg].min = fdesc.min;
- ctx->register_ctx[reg].max = fdesc.max;
+ memcpy(&ctx->register_ctx[reg].range, &fdesc.range, sizeof(pcilib_register_value_range_t));
ctx->register_ctx[reg].views = fdesc.base.views;
}
}
@@ -563,7 +561,7 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp
}
-static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_value_name_t *desc) {
+static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_register_value_name_t *desc) {
xmlAttr *cur;
char *value, *name;
char *endptr;
@@ -660,7 +658,7 @@ static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath,
return PCILIB_ERROR_INVALID_DATA;
}
- desc.names = (pcilib_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_value_name_t));
+ desc.names = (pcilib_register_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_register_value_name_t));
if (!desc.names) {
xmlXPathFreeObject(nodes);
pcilib_error("No names is defined for enum view (%s)", desc.base.name);
@@ -676,7 +674,7 @@ static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath,
return err;
}
}
- memset(&desc.names[nodeset->nodeNr], 0, sizeof(pcilib_value_name_t));
+ memset(&desc.names[nodeset->nodeNr], 0, sizeof(pcilib_register_value_name_t));
xmlXPathFreeObject(nodes);