diff options
| -rw-r--r-- | pcilib/bank.c | 39 | ||||
| -rw-r--r-- | pcilib/bank.h | 21 | ||||
| -rw-r--r-- | pcilib/pcilib.h | 1 | ||||
| -rw-r--r-- | protocols/default.c | 35 | ||||
| -rw-r--r-- | protocols/default.h | 3 | ||||
| -rw-r--r-- | protocols/property.h | 2 | ||||
| -rw-r--r-- | protocols/software.c | 15 | ||||
| -rw-r--r-- | protocols/software.h | 12 | 
8 files changed, 123 insertions, 5 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 diff --git a/protocols/default.c b/protocols/default.c index 6f3dccf..f78c656 100644 --- a/protocols/default.c +++ b/protocols/default.c @@ -7,9 +7,40 @@  #include "error.h"  #include "bar.h"  #include "datacpy.h" +#include "pci.h"  #define default_datacpy(dst, src, access, bank)   pcilib_datacpy(dst, src, access, 1, bank->raw_endianess) +uintptr_t pcilib_default_resolve(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t reg_addr) { +    uintptr_t addr; +    const pcilib_register_bank_description_t *b = bank_ctx->bank; + +    if (reg_addr == PCILIB_REGISTER_ADDRESS_INVALID) reg_addr = 0; + +    switch (flags&PCILIB_ADDRESS_RESOLUTION_MASK_ACCESS_MODE) { +     case 0: +	if (b->read_addr != b->write_addr) +	    return PCILIB_ADDRESS_INVALID; +     case PCILIB_ADDRESS_RESOLUTION_FLAG_READ_ONLY: +	addr = b->read_addr + reg_addr; +	break; +     case PCILIB_ADDRESS_RESOLUTION_FLAG_WRITE_ONLY: +        addr = b->write_addr + reg_addr; +     default: +        return PCILIB_ADDRESS_INVALID; +    } + +    switch (flags&PCILIB_ADDRESS_RESOLUTION_MASK_ADDRESS_TYPE) { +     case 0: +        return (uintptr_t)pcilib_resolve_bar_address(ctx, b->bar, addr); +     case PCILIB_ADDRESS_RESOLUTION_FLAG_BUS_ADDRESS: +     case PCILIB_ADDRESS_RESOLUTION_FLAG_PHYS_ADDRESS: +        return ctx->board_info.bar_start[b->bar] + addr; +    } + +    return PCILIB_ADDRESS_INVALID; +} +  int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) {      char *ptr;      pcilib_register_value_t val = 0; @@ -18,7 +49,7 @@ int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx,      int access = b->access / 8; -    ptr =  pcilib_resolve_register_address(ctx, b->bar, b->read_addr + addr); +    ptr =  pcilib_resolve_bar_address(ctx, b->bar, b->read_addr + addr);      default_datacpy(&val, ptr, access, b);  //    *value = val&BIT_MASK(bits); @@ -35,7 +66,7 @@ int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx      int access = b->access / 8; -    ptr =  pcilib_resolve_register_address(ctx, b->bar, b->write_addr + addr); +    ptr =  pcilib_resolve_bar_address(ctx, b->bar, b->write_addr + addr);      default_datacpy(ptr, &value, access, b);      return 0; diff --git a/protocols/default.h b/protocols/default.h index 829b65d..74dd91c 100644 --- a/protocols/default.h +++ b/protocols/default.h @@ -5,12 +5,13 @@  #include "version.h"  #include "model.h" +uintptr_t pcilib_default_resolve(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t addr);  int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value);  int pcilib_default_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_default_protocol_api = -    { PCILIB_VERSION, NULL, NULL, pcilib_default_read, pcilib_default_write }; +    { PCILIB_VERSION, NULL, NULL, pcilib_default_resolve, pcilib_default_read, pcilib_default_write };  #endif /* _PCILIB_EXPORT_C */  #endif /* _PCILIB_PROTOCOL_DEFAULT_H */ diff --git a/protocols/property.h b/protocols/property.h index 3d3eb63..7f9b0db 100644 --- a/protocols/property.h +++ b/protocols/property.h @@ -10,7 +10,7 @@ int pcilib_property_registers_write(pcilib_t *ctx, pcilib_register_bank_context_  #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 }; +    { PCILIB_VERSION, NULL, NULL, NULL, pcilib_property_registers_read, pcilib_property_registers_write };  #endif /* _PCILIB_EXPORT_C */  #endif /* _PCILIB_PROTOCOL_PROPERTY_H */ diff --git a/protocols/software.c b/protocols/software.c index 3da8fde..5b217d4 100644 --- a/protocols/software.c +++ b/protocols/software.c @@ -105,6 +105,21 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc  	return (pcilib_register_bank_context_t*)bank_ctx;  } +uintptr_t pcilib_software_registers_resolve(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t addr) { +    if (addr == PCILIB_REGISTER_ADDRESS_INVALID) addr = 0; + +    switch (flags&PCILIB_ADDRESS_RESOLUTION_MASK_ADDRESS_TYPE) { +     case 0: +        return (uintptr_t)((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr; + +     case PCILIB_ADDRESS_RESOLUTION_FLAG_PHYS_ADDRESS: +	return pcilib_kmem_get_block_pa(ctx, ((pcilib_software_register_bank_context_t*)bank_ctx)->kmem, 0) + addr; +    } + +    return PCILIB_ADDRESS_INVALID; +} + +  int pcilib_software_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value){      const pcilib_register_bank_description_t *b = bank_ctx->bank;      int access = b->access / 8; diff --git a/protocols/software.h b/protocols/software.h index 27ab86e..88f2986 100644 --- a/protocols/software.h +++ b/protocols/software.h @@ -28,6 +28,16 @@ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pc  void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx);  /** + * this function resolve the virtual address of the register for direct access + * @param[in] - ctx the pcilib_t structure runnning + * @param[in] - bank_ctx the bank context that was returned by the initialisation function + * @param[in] - flags  + * @param[in] - addr the adress of the register we want to read + * @return virtual address or PCILIB_ADDRESS_INVALID on error  + */ +uintptr_t pcilib_software_registers_resolve(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t addr); + +/**   * this function read the value of a said register in the kernel space.   * @param[in] - ctx the pcilib_t structure runnning   * @param[in] - bank_ctx the bank context that was returned by the initialisation function @@ -52,7 +62,7 @@ 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_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*/ +  { PCILIB_VERSION, pcilib_software_registers_open, pcilib_software_registers_close, pcilib_software_registers_resolve, pcilib_software_registers_read, pcilib_software_registers_write };   #endif /* _PCILIB_EXPORT_C */  #endif /* _PCILIB_PROTOCOL_SOFTWARE_H */  | 
