From 8ba85a9aff0009d03090a1ba3e9d7e146f02b7bf Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Mon, 19 Oct 2015 06:59:53 +0200 Subject: Provide register listings in public API --- pcilib/pcilib.h | 68 ++++++++++++++++++++++++++++++++---------- pcilib/register.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ pcilib/register.h | 11 +------ pcilib/xml.c | 18 +++++------- 4 files changed, 149 insertions(+), 36 deletions(-) (limited to 'pcilib') 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 { @@ -46,6 +46,16 @@ typedef enum { PCILIB_ACCESS_RW = 3 } 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 */ @@ -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 */ @@ -132,6 +134,27 @@ typedef struct { char str[16]; /**< Used for shorter strings converted from integer/float types */ } 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 */ @@ -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); -- cgit v1.2.3