summaryrefslogtreecommitdiffstats
path: root/pcilib
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-11-18 03:25:02 +0100
committerSuren A. Chilingaryan <csa@suren.me>2015-11-18 03:25:02 +0100
commitca7353be486a0364a3460b511291a40182f130ba (patch)
tree1505293794cbe29fdeb6341bbe699c52dd39f8aa /pcilib
parentec667d49f84c45c261f050313d64f89ce88e4302 (diff)
downloadpcitool-ca7353be486a0364a3460b511291a40182f130ba.tar.gz
pcitool-ca7353be486a0364a3460b511291a40182f130ba.tar.bz2
pcitool-ca7353be486a0364a3460b511291a40182f130ba.tar.xz
pcitool-ca7353be486a0364a3460b511291a40182f130ba.zip
Provide API calls for register and bank address resolution
Diffstat (limited to 'pcilib')
-rw-r--r--pcilib/bank.c39
-rw-r--r--pcilib/bank.h21
-rw-r--r--pcilib/pcilib.h1
3 files changed, 61 insertions, 0 deletions
diff --git a/pcilib/bank.c b/pcilib/bank.c
index efaa810..15fc4a3 100644
--- a/pcilib/bank.c
+++ b/pcilib/bank.c
@@ -272,6 +272,45 @@ pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const ch
return pcilib_find_register_protocol_by_name(ctx, protocol);
}
+uintptr_t pcilib_resolve_bank_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_bank_t bank) {
+ pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
+
+ if (!bctx->api->resolve)
+ return PCILIB_ADDRESS_INVALID;
+
+ return bctx->api->resolve(ctx, bctx, flags, PCILIB_REGISTER_ADDRESS_INVALID);
+}
+
+uintptr_t pcilib_resolve_bank_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank) {
+ pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
+ if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
+ if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
+ else pcilib_error("Register bank should be specified");
+ return PCILIB_ADDRESS_INVALID;
+ }
+
+ return pcilib_resolve_bank_address_by_id(ctx, flags, bank_id);
+}
+
+uintptr_t pcilib_resolve_register_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_t reg) {
+ pcilib_register_bank_context_t *bctx = ctx->bank_ctx[ctx->register_ctx[reg].bank];
+
+ if (!bctx->api->resolve)
+ return PCILIB_ADDRESS_INVALID;
+
+ return bctx->api->resolve(ctx, bctx, 0, ctx->registers[reg].addr);
+}
+
+uintptr_t pcilib_resolve_register_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank, const char *regname) {
+ pcilib_register_t reg = pcilib_find_register(ctx, bank, regname);
+ if (reg == PCILIB_REGISTER_INVALID) {
+ pcilib_error("Register (%s) is not found", regname);
+ return PCILIB_ADDRESS_INVALID;
+ }
+
+ return pcilib_resolve_register_address_by_id(ctx, flags, reg);
+}
+
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);
diff --git a/pcilib/bank.h b/pcilib/bank.h
index f974b0a..e7be825 100644
--- a/pcilib/bank.h
+++ b/pcilib/bank.h
@@ -12,6 +12,10 @@
#define PCILIB_REGISTER_BANK_PROPERTY 65 /**< Registers abstracting properties and other computed registers */
#define PCILIB_REGISTER_BANK_DMACONF 96 /**< DMA configuration in the software registers */
#define PCILIB_REGISTER_BANK_DMA 97 /**< First BANK address to be used by DMA engines */
+#define PCILIB_REGISTER_BANK_DMA0 PCILIB_REGISTER_BANK_DMA /**< First BANK address to be used by DMA engines */
+#define PCILIB_REGISTER_BANK_DMA1 (PCILIB_REGISTER_BANK_DMA + 1) /**< Second BANK address to be used by DMA engines */
+#define PCILIB_REGISTER_BANK_DMA2 (PCILIB_REGISTER_BANK_DMA + 2) /**< Third BANK address to be used by DMA engines */
+#define PCILIB_REGISTER_BANK_DMA3 (PCILIB_REGISTER_BANK_DMA + 3) /**< Fourth BANK address to be used by DMA engines */
#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 */
@@ -34,11 +38,22 @@ typedef enum {
PCILIB_MODEL_MODIFICATION_FLAG_SKIP_EXISTING = 2 /**< If flag is set, pcilib will just skip existing registers/banks/etc instead of reporting a error */
} pcilib_model_modification_flags_t;
+typedef enum {
+ PCILIB_ADDRESS_RESOLUTION_FLAGS_DEFAULT = 0,
+ PCILIB_ADDRESS_RESOLUTION_FLAG_BUS_ADDRESS = 1, /**< Resolve bus address instead of VA */
+ PCILIB_ADDRESS_RESOLUTION_FLAG_PHYS_ADDRESS = 2, /**< Resolve hardware address instead of VA */
+ PCILIB_ADDRESS_RESOLUTION_MASK_ADDRESS_TYPE = 3,
+ PCILIB_ADDRESS_RESOLUTION_FLAG_READ_ONLY = 4, /**< Request read-only memory, in case if read-write resolution is impossible */
+ PCILIB_ADDRESS_RESOLUTION_FLAG_WRITE_ONLY = 8, /**< Request write-only resolution, in case if read-write resolution is impossible */
+ PCILIB_ADDRESS_RESOLUTION_MASK_ACCESS_MODE = 12
+} pcilib_address_resolution_flags_t;
+
typedef struct {
pcilib_version_t version;
pcilib_register_bank_context_t *(*init)(pcilib_t *ctx, pcilib_register_bank_t bank, const char *model, const void *args); /**< Optional API call to initialize bank context */
void (*free)(pcilib_t *pcilib, pcilib_register_bank_context_t *ctx); /**< Optional API call to cleanup bank context */
+ uintptr_t (*resolve)(pcilib_t *pcilib, pcilib_register_bank_context_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t addr); /**< Resolves register virtual address (if supported) */
int (*read)(pcilib_t *pcilib, pcilib_register_bank_context_t *ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value); /**< Read from register, mandatory for RO/RW registers */
int (*write)(pcilib_t *pcilib, pcilib_register_bank_context_t *ctx, pcilib_register_addr_t addr, pcilib_register_value_t value); /**< Write to register, mandatory for WO/RW registers */
} pcilib_register_protocol_api_description_t;
@@ -164,6 +179,12 @@ 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);
+uintptr_t pcilib_resolve_bank_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_bank_t bank);
+uintptr_t pcilib_resolve_bank_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank);
+
+uintptr_t pcilib_resolve_register_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_t reg);
+uintptr_t pcilib_resolve_register_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank, const char *regname);
+
int pcilib_get_register_bank_attr_by_id(pcilib_t *ctx, pcilib_register_bank_t bank, 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);
diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h
index 776a5c5..fbab883 100644
--- a/pcilib/pcilib.h
+++ b/pcilib/pcilib.h
@@ -185,6 +185,7 @@ typedef struct {
#define PCILIB_DMA_FLAGS_DEFAULT ((pcilib_dma_flags_t)0)
#define PCILIB_DMA_ENGINE_ADDR_INVALID ((pcilib_dma_engine_addr_t)-1)
#define PCILIB_REGISTER_INVALID ((pcilib_register_t)-1)
+#define PCILIB_REGISTER_ADDRESS_INVALID ((pcilib_register_addr_t)-1)
#define PCILIB_ADDRESS_INVALID ((uintptr_t)-1)
#define PCILIB_EVENT0 1
#define PCILIB_EVENT1 2