diff options
-rw-r--r-- | dma/ipe.c | 16 | ||||
-rw-r--r-- | dma/ipe.h | 6 | ||||
-rw-r--r-- | dma/ipe_private.h | 6 | ||||
-rw-r--r-- | docs/IPEHARDWARE | 8 | ||||
-rw-r--r-- | pcilib/bank.c | 2 | ||||
-rw-r--r-- | pcilib/bank.h | 12 | ||||
-rw-r--r-- | pcilib/bar.c | 3 | ||||
-rw-r--r-- | pcilib/export.c | 4 | ||||
-rw-r--r-- | pcilib/kmem.h | 3 | ||||
-rw-r--r-- | pcilib/model.h | 2 | ||||
-rw-r--r-- | pcilib/pcilib.h | 2 | ||||
-rw-r--r-- | protocols/CMakeLists.txt | 4 | ||||
-rw-r--r-- | protocols/software.c | 122 | ||||
-rw-r--r-- | protocols/software.h (renamed from protocols/software_registers.h) | 25 | ||||
-rw-r--r-- | protocols/software_registers.c | 114 |
15 files changed, 181 insertions, 148 deletions
@@ -111,10 +111,12 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm else if ((reuse_desc & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing..."); else { #ifndef IPEDMA_BUG_DMARD +# ifndef IPEDMA_STREAMING_MODE RD(IPEDMA_REG_PAGE_COUNT, value); if (value != IPEDMA_DMA_PAGES) pcilib_warning("Inconsistent DMA buffers are found (Number of allocated buffers (%lu) does not match current request (%lu)), reinitializing...", value + 1, IPEDMA_DMA_PAGES); else +# endif /* IPEDMA_STREAMING_MODE */ #endif /* IPEDMA_BUG_DMARD */ preserve = 1; } @@ -501,9 +503,21 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin ret = cb(cbattr, packet_flags, ctx->page_size, buf); if (ret < 0) return -ret; - // We don't need this because hardwaredoes not intend to read anything from the memory + // We don't need this because hardware does not intend to read anything from the memory // pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read); + // Return buffer into the DMA pool when processed +#ifdef IPEDMA_STREAMING_MODE + uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, cur_read); + WR(IPEDMA_REG_PAGE_ADDR, buf_ba); +# ifdef IPEDMA_STREAMING_CHECKS + pcilib_register_value_t streaming_status; + RD(IPEDMA_REG_STREAMING_STATUS, streaming_status); + if (streaming_status) + pcilib_error("Invalid status (0x%lx) adding a DMA buffer into the queue", streaming_status); +# endif /* IPEDMA_STREAMING_MODE */ +#endif /* IPEDMA_STREAMING_MODE */ + // Numbered from 1 #ifdef IPEDMA_BUG_LAST_READ WR(IPEDMA_REG_LAST_READ, cur_read?cur_read:IPEDMA_DMA_PAGES); @@ -39,7 +39,7 @@ static const pcilib_dma_engine_description_t ipe_dma_engines[] = { static const pcilib_register_bank_description_t ipe_dma_banks[] = { { PCILIB_REGISTER_BANK_DMA, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, 0, 0, 32, 0x0200, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, - { PCILIB_REGISTER_BANK_DMA + 1, PCILIB_REGISTER_PROTOCOL_SOFTWARE_REGISTERS, PCILIB_BARUNDEF, 0, 0, 32, 0x0003, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "test", "test Registers"}, + { PCILIB_REGISTER_BANK_DMACONF, PCILIB_REGISTER_PROTOCOL_SOFTWARE, PCILIB_BAR_NOBAR, 0, 0, 32, 0x1000, PCILIB_HOST_ENDIAN, PCILIB_HOST_ENDIAN, "0x%lx", "dmaconf", "DMA Software Registers"}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; @@ -78,9 +78,7 @@ static const pcilib_register_description_t ipe_dma_registers[] = { {0x0058, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "last_descriptor_read", "Last descriptor read by the host"}, {0x005C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "desc_mem_addr", "Number of descriptors configured"}, {0x0060, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "update_thresh", "Update threshold of progress register"}, - {0x0001, 0, 32, 0x1, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA +1, "test1", "ister"}, - {0x0002, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA +1, "test2", "ter"}, - {0x0003, 0, 32, 0x020, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA +1, "test3", "er"}, + {0x0000, 0, 32, PCILIB_VERSION, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMACONF, "dma_version", "Version of DMA engine"}, {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} }; #endif /* _PCILIB_EXPORT_C */ diff --git a/dma/ipe_private.h b/dma/ipe_private.h index 5cfb10b..249286d 100644 --- a/dma/ipe_private.h +++ b/dma/ipe_private.h @@ -8,6 +8,8 @@ #define IPEDMA_MAX_TLP_SIZE 256 /**< Defines maximum TLP in bytes supported by device */ //#define IPEDMA_TLP_SIZE 128 /**< If set, enforces the specified TLP size */ +#define IPEDMA_STREAMING_MODE /**< Enables streaming DMA operation mode instead of ring-buffer, the page is written once and forgotten and need to be pushed in queue again */ +#define IPEDMA_STREAMING_CHECKS /**< Enables status checks in streaming mode (it will cause performance penalty) */ #define IPEDMA_PAGE_SIZE 4096 #define IPEDMA_DMA_PAGES 1024 /**< number of DMA pages in the ring buffer to allocate */ #define IPEDMA_DMA_PROGRESS_THRESHOLD 1 /**< how many pages the DMA engine should fill before reporting progress */ @@ -31,9 +33,11 @@ #define IPEDMA_REG_TLP_COUNT 0x10 #define IPEDMA_REG_PAGE_ADDR 0x50 #define IPEDMA_REG_UPDATE_ADDR 0x54 -#define IPEDMA_REG_LAST_READ 0x58 +#define IPEDMA_REG_LAST_READ 0x58 /**< In streaming mode, we can use it freely to track current status */ #define IPEDMA_REG_PAGE_COUNT 0x5C #define IPEDMA_REG_UPDATE_THRESHOLD 0x60 +#define IPEDMA_REG_STREAMING_STATUS 0x68 + #define WR(addr, value) { *(uint32_t*)(ctx->base_addr + addr) = value; } #define RD(addr, value) { value = *(uint32_t*)(ctx->base_addr + addr); } diff --git a/docs/IPEHARDWARE b/docs/IPEHARDWARE new file mode 100644 index 0000000..a7bbf3a --- /dev/null +++ b/docs/IPEHARDWARE @@ -0,0 +1,8 @@ +IPEDMA +====== + - Normally, we are using register 0x5C to get number of buffers configured in the hardware + and check if it is consistent with number of allocated buffers. However, in streaming mode + this does not work at the moment. After writting the buffers, the hardware forgets them + and only stores the current queue of free buffers. Currently, the check is disabled in the + streaming mode. Can we handle it somehow? +
\ No newline at end of file diff --git a/pcilib/bank.c b/pcilib/bank.c index dbbb427..3d53db2 100644 --- a/pcilib/bank.c +++ b/pcilib/bank.c @@ -65,7 +65,7 @@ void pcilib_free_register_banks(pcilib_t *ctx) { if (ctx->bank_ctx[i]) { if (bapi->free) - bapi->free(ctx->bank_ctx[i]); + bapi->free(ctx, ctx->bank_ctx[i]); else free(ctx->bank_ctx[i]); diff --git a/pcilib/bank.h b/pcilib/bank.h index dfd2adb..8b461af 100644 --- a/pcilib/bank.h +++ b/pcilib/bank.h @@ -2,8 +2,6 @@ #define _PCILIB_BANK_H #include <pcilib.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> #define PCILIB_REGISTER_BANK_INVALID ((pcilib_register_bank_t)-1) #define PCILIB_REGISTER_BANK0 0 /**< First BANK to be used in the event engine */ @@ -11,13 +9,14 @@ #define PCILIB_REGISTER_BANK2 2 #define PCILIB_REGISTER_BANK3 3 #define PCILIB_REGISTER_BANK_DMA 64 /**< First BANK address to be used by DMA engines */ +#define PCILIB_REGISTER_BANK_DMACONF 65 /**< DMA configuration in the software registers */ #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 */ #define PCILIB_REGISTER_PROTOCOL_DEFAULT 64 /**< Default memmap based protocol */ +#define PCILIB_REGISTER_PROTOCOL_SOFTWARE 65 /**< Software registers */ #define PCILIB_REGISTER_PROTOCOL_DMA 96 /**< First PROTOCOL address to be used by DMA engines */ #define PCILIB_REGISTER_PROTOCOL_DYNAMIC 128 /**< First PROTOCOL address to be used by plugins */ -#define PCILIB_REGISTER_PROTOCOL_SOFTWARE_REGISTERS 32 typedef uint8_t pcilib_register_bank_t; /**< Type holding the bank position within the field listing register banks in the model */ typedef uint8_t pcilib_register_bank_addr_t; /**< Type holding the bank address number */ @@ -31,7 +30,7 @@ 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_register_bank_context_t *bank_ctx); /**< Optional API call to cleanup bank context */ + void (*free)(pcilib_t *pcilib, pcilib_register_bank_context_t *ctx); /**< Optional API call to cleanup bank context */ 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; @@ -63,7 +62,6 @@ typedef struct { const char *format; /**< printf format for the registers, either %lu for decimal output or 0x%lx for hexdecimal */ const char *name; /**< short bank name */ const char *description; /**< longer bank description */ - xmlNodePtr xmlNode; /**<pointer to xmlNode of the bank in the file*/ } pcilib_register_bank_description_t; /** @@ -86,12 +84,8 @@ typedef struct { struct pcilib_register_bank_context_s { const pcilib_register_bank_description_t *bank; /**< Corresponding bank description */ const pcilib_register_protocol_api_description_t *api; /**< API functions */ - xmlNodeSetPtr banks_nodes; - void *kmem_base_address; - pcilib_t *ctx; }; - // we don't copy strings, they should be statically allocated int pcilib_init_register_banks(pcilib_t *ctx); void pcilib_free_register_banks(pcilib_t *ctx); diff --git a/pcilib/bar.c b/pcilib/bar.c index a2670c0..ce04f6d 100644 --- a/pcilib/bar.c +++ b/pcilib/bar.c @@ -131,6 +131,9 @@ int pcilib_map_register_space(pcilib_t *ctx) { // uint32_t buf[2]; void *reg_space; pcilib_bar_t bar = banks[i].bar; + + if (bar == PCILIB_BAR_NOBAR) + continue; if (bar == PCILIB_BAR_DETECT) { uintptr_t addr = banks[0].read_addr; diff --git a/pcilib/export.c b/pcilib/export.c index ed3b5bf..7b78e32 100644 --- a/pcilib/export.c +++ b/pcilib/export.c @@ -5,11 +5,11 @@ #include "export.h" #include "protocols/default.h" -#include "protocols/software_registers.h" +#include "protocols/software.h" const pcilib_register_protocol_description_t pcilib_protocols[] = { { PCILIB_REGISTER_PROTOCOL_DEFAULT, &pcilib_default_protocol_api, NULL, NULL, "default", "" }, - { PCILIB_REGISTER_PROTOCOL_SOFTWARE_REGISTERS, &pcilib_register_software_register_protocol_api, NULL, NULL, "software_registers", "" }, + { PCILIB_REGISTER_PROTOCOL_SOFTWARE, &pcilib_register_software_protocol_api, NULL, NULL, "software_registers", "" }, { 0 } }; diff --git a/pcilib/kmem.h b/pcilib/kmem.h index 8302b6a..ae690fe 100644 --- a/pcilib/kmem.h +++ b/pcilib/kmem.h @@ -4,6 +4,8 @@ typedef struct pcilib_s pcilib_t; typedef struct pcilib_kmem_list_s pcilib_kmem_list_t; +#define PCILIB_KMEM_PAGE_SIZE 0x1000 + typedef enum { PCILIB_TRISTATE_NO = 0, PCILIB_TRISTATE_PARTIAL = 1, @@ -27,6 +29,7 @@ typedef enum { PCILIB_KMEM_USE_STANDARD = 0, PCILIB_KMEM_USE_DMA_RING = 1, PCILIB_KMEM_USE_DMA_PAGES = 2, + PCILIB_KMEM_USE_SOFTWARE_REGISTERS = 3, PCILIB_KMEM_USE_USER = 0x10 } pcilib_kmem_use_t; diff --git a/pcilib/model.h b/pcilib/model.h index b60ff3b..ab55adc 100644 --- a/pcilib/model.h +++ b/pcilib/model.h @@ -7,6 +7,7 @@ #include <pcilib/event.h> #include <pcilib/export.h> + typedef struct { const pcilib_version_t interface_version; @@ -23,7 +24,6 @@ typedef struct { const char *name; const char *description; - } pcilib_model_description_t; diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h index 6c1d592..9710642 100644 --- a/pcilib/pcilib.h +++ b/pcilib/pcilib.h @@ -85,9 +85,9 @@ typedef struct { #define PCILIB_BAR_DETECT ((pcilib_bar_t)-1) #define PCILIB_BAR_INVALID ((pcilib_bar_t)-1) +#define PCILIB_BAR_NOBAR ((pcilib_bar_t)-2) #define PCILIB_BAR0 0 #define PCILIB_BAR1 1 -#define PCILIB_BARUNDEF -1 #define PCILIB_DMA_ENGINE_INVALID ((pcilib_dma_engine_t)-1) #define PCILIB_DMA_ENGINE_ALL ((pcilib_dma_engine_t)-1) #define PCILIB_DMA_FLAGS_DEFAULT ((pcilib_dma_flags_t)0) diff --git a/protocols/CMakeLists.txt b/protocols/CMakeLists.txt index 2299061..2c482f6 100644 --- a/protocols/CMakeLists.txt +++ b/protocols/CMakeLists.txt @@ -3,6 +3,6 @@ include_directories( ${CMAKE_SOURCE_DIR}/pcilib ) -set(HEADERS ${HEADERS} default.h software_registers.h) +set(HEADERS ${HEADERS} default.h software.h) -add_library(protocols STATIC default.c software_registers.c) +add_library(protocols STATIC default.c software.c) diff --git a/protocols/software.c b/protocols/software.c new file mode 100644 index 0000000..5534dc7 --- /dev/null +++ b/protocols/software.c @@ -0,0 +1,122 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/file.h> + +#include "model.h" +#include "error.h" +#include "kmem.h" +#include "pcilib.h" +#include "pci.h" + +typedef struct pcilib_software_register_bank_context_s pcilib_software_register_bank_context_t; + +struct pcilib_software_register_bank_context_s { + pcilib_register_bank_context_t bank_ctx; + + pcilib_kmem_handle_t *kmem; + void *addr; +}; + +/** + * pcilib_software_registers_close + * this function clear the kernel memory space that could have been allocated for software registers + * @param[in] bank_ctx the bank context running that we get from the initialisation function + */ +void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx) { + if (((pcilib_software_register_bank_context_t*)bank_ctx)->kmem) + pcilib_free_kernel_memory(ctx, ((pcilib_software_register_bank_context_t*)bank_ctx)->kmem, PCILIB_KMEM_FLAG_REUSE); + free(bank_ctx); +} + +/** + * pcilib_software_registers_open + * this function initializes the kernel space memory and stores in it the default values of the registers of the given bank index, if it was not initialized by a concurrent process, and return a bank context containing the adress of this kernel space. It the kernel space memory was already initialized by a concurrent process, then this function just return the bank context with the adress of this kernel space already used + * @param[in] ctx the pcilib_t structure running + * @param[in] bank the bank index that will permits to get the bank we want registers from + * @param[in] model not used + * @param[in] args not used + * @return a bank context with the adress of the kernel space memory related to it + */ +pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) { + pcilib_software_register_bank_context_t *bank_ctx; + pcilib_kmem_handle_t *handle; + pcilib_kmem_reuse_state_t reused; + + const pcilib_register_bank_description_t *bank_desc = ctx->banks + bank; + + if (bank_desc->size > PCILIB_KMEM_PAGE_SIZE) { + pcilib_error("Currently software register banks are limited to %lu bytes, but %lu requested", PCILIB_KMEM_PAGE_SIZE, bank_desc->size); + return NULL; + } + + bank_ctx = calloc(1, sizeof(pcilib_software_register_bank_context_t)); + + handle = pcilib_alloc_kernel_memory(ctx, PCILIB_KMEM_TYPE_PAGE, 1, PCILIB_KMEM_PAGE_SIZE, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_SOFTWARE_REGISTERS, bank), PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); + if (!handle) { + pcilib_error("Allocation of kernel memory for software registers has failed"); + pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); + return NULL; + } + + bank_ctx->kmem = handle; + bank_ctx->addr = pcilib_kmem_get_block_ua(ctx, handle, 0); + reused = pcilib_kmem_is_reused(ctx, handle); + + if ((reused & PCILIB_KMEM_REUSE_REUSED) == 0) { + pcilib_register_t i; + + if (reused & PCILIB_KMEM_REUSE_PARTIAL) { + pcilib_error("Inconsistent software registers are found (only part of required buffers is available)"); + pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); + return NULL; + } + + for (i = 0; ctx->model_info.registers[i].name != NULL; i++) { + if ((ctx->model_info.registers[i].bank == ctx->banks[bank].addr)&&(ctx->model_info.registers[i].type == PCILIB_REGISTER_STANDARD)) { + *(pcilib_register_value_t*)(bank_ctx->addr + ctx->model_info.registers[i].addr) = ctx->model_info.registers[i].defvalue; + } + } + } + + return (pcilib_register_bank_context_t*)bank_ctx; +} + +/** + * pcilib_software_registers_read + * 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 + * @param[in] addr the adress of the register we want to read + * @param[out] value the value of the register + * @return 0 in case of success + */ +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){ + if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { + pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); + return PCILIB_ERROR_INVALID_ADDRESS; + } + + *value = *(pcilib_register_value_t*)(((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr); + return 0; +} + +/** + * pcilib_software_registers_write + * this function write the said value to 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 + * @param[in] addr the adress of the register we want to write in + * @param[out] value the value we want to write in the register + * @return 0 in case of success + */ +int pcilib_software_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value){ + if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { + pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); + return PCILIB_ERROR_INVALID_ADDRESS; + } + + *(pcilib_register_value_t*)(((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr) = value; + return 0; +} diff --git a/protocols/software_registers.h b/protocols/software.h index f31e292..d066cd6 100644 --- a/protocols/software_registers.h +++ b/protocols/software.h @@ -1,11 +1,11 @@ /** - * @file software_registers.h + * @file software.h * @skip author nicolas zilio, nicolas.zilio@hotmail.fr - * @brief header file for implementation of the protocol with registers registered in the kernel space. + * @brief header file for implementation of the protocol with software registers allocated in the main memory. */ -#ifndef _PCILIB_SOFTREG_PROT -#define _PCILIB_SOFTREG_PROT +#ifndef _PCILIB_SOFTWARE_H +#define _PCILIB_SOFTWARE_H #include "pcilib.h" #include "version.h" @@ -13,36 +13,37 @@ /** * this function initialize the kernel space memory for the use of software register. it initializes the kernel space memory and stores in it the default values of the registers of the given bank index, if it was not initialized by a concurrent process, and return a bank context containing the adress of this kernel space. If the kernel space memory was already initialized by a concurrent process, then this function just return the bank context with the adress of this kernel space already used - *@param[in] ctx the pcilib_t structure running + * @param[in] ctx the pcilib_t structure running * @param[in] bank the bank index that will permits to get the bank we want registers from * @param[in] model not used * @param[in] args not used - *@return a bank context with the adress of the kernel space memory related to it + * @return a bank context with the adress of the kernel space memory related to it */ pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args); /** * this function clear the kernel memory space that could have been allocated for software registers. + * @param[in] ctx the pcilib_t structure runnning * @param[in] bank_ctx the bank context running that we get from the initialisation function */ -void pcilib_software_registers_close(pcilib_register_bank_context_t *bank_ctx); +void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx); /** * 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 * @param[in] addr the adress of the register we want to read - *@param[out] value the value of the register + * @param[out] value the value of the register * @return 0 in case of success */ -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); +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); /** * this function write the said value to 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 * @param[in] addr the adress of the register we want to write in - *@param[out] value the value we want to write in the register + * @param[out] value the value we want to write in the register * @return 0 in case of success */ int pcilib_software_registers_write(pcilib_t *ctx,pcilib_register_bank_context_t* bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value); @@ -51,8 +52,8 @@ int pcilib_software_registers_write(pcilib_t *ctx,pcilib_register_bank_context_t /** * new protocol addition to the protocol api. */ -const pcilib_register_protocol_api_description_t pcilib_register_software_register_protocol_api = +const pcilib_register_protocol_api_description_t pcilib_register_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*/ #endif /* _PCILIB_EXPORT_C */ -#endif /* _PCILIB_SOFTREG_PROT*/ +#endif /* _PCILIB_SOFTWARE_H */ diff --git a/protocols/software_registers.c b/protocols/software_registers.c deleted file mode 100644 index ab5d31d..0000000 --- a/protocols/software_registers.c +++ /dev/null @@ -1,114 +0,0 @@ -#include <string.h> -#include <sys/file.h> -#include <unistd.h> - -#include "model.h" -#include "error.h" -#include "kmem.h" -#include "pcilib.h" -#include "pci.h" - -#include <stdio.h> - -/** - * pcilib_software_registers_open - * this function initializes the kernel space memory and stores in it the default values of the registers of the given bank index, if it was not initialized by a concurrent process, and return a bank context containing the adress of this kernel space. It the kernel space memory was already initialized by a concurrent process, then this function just return the bank context with the adress of this kernel space already used - *@param[in] ctx the pcilib_t structure running - * @param[in] bank the bank index that will permits to get the bank we want registers from - * @param[in] model not used - * @param[in] args not used - *@return a bank context with the adress of the kernel space memory related to it - */ -pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank,const char* model, const void *args){ - pcilib_register_bank_context_t* bank_ctx; - pcilib_kmem_handle_t *handle; - int j; - /* the protocol thing is here to make sure to avoid segfault in write_registers_internal, but is not useful as it is now*/ - pcilib_register_protocol_t protocol; - protocol = pcilib_find_register_protocol_by_addr(ctx, ctx->banks[bank].protocol); - - bank_ctx=calloc(1,sizeof(pcilib_register_bank_context_t)); - bank_ctx->bank=ctx->banks + bank; - bank_ctx->ctx=ctx; - bank_ctx->api=ctx->protocols[protocol].api; - ctx->bank_ctx[bank]=bank_ctx; - - handle=pcilib_alloc_kernel_memory(ctx, PCILIB_KMEM_TYPE_PAGE, 1, 0, 1,PCILIB_KMEM_USE_STANDARD,PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); - - if (!handle)pcilib_error("allocation of kernel memory for registers has failed"); - - bank_ctx->kmem_base_address=handle; - - if(pcilib_kmem_is_reused(ctx,handle)!= PCILIB_KMEM_REUSE_ALLOCATED){ - j=0; - while(ctx->model_info.registers[j].name!=NULL){ - if(ctx->model_info.registers[j].bank==(ctx->banks+bank)->addr){ - /* !!!!!warning!!!!! - hey suren, - you may check here too :the programm seems to always go this path, so pcilib_write_register_by_id always write the original value, kmem_is_reused working? - */ - pcilib_write_register_by_id(ctx,j,ctx->model_info.registers[j].defvalue); - - } - j++; - } - } - - return bank_ctx; -} - - -/** - * pcilib_software_registers_close - * this function clear the kernel memory space that could have been allocated for software registers - * @param[in] bank_ctx the bank context running that we get from the initialisation function - */ -void pcilib_software_registers_close(pcilib_register_bank_context_t *bank_ctx){ - /*!!!!! to check!!!! - - ps: i am using uint32_t to calculate registers adress, may it change in the future? should we define some #define? - */ - pcilib_free_kernel_memory(bank_ctx->ctx,bank_ctx->kmem_base_address, 0); -} - -/** - * pcilib_software_registers_read - * 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 - * @param[in] addr the adress of the register we want to read - *@param[out] value the value of the register - * @return 0 in case of success - */ -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){ - int i; - void* base_addr; - - base_addr=pcilib_kmem_get_block_ua(ctx,bank_ctx->kmem_base_address,0); - for(i=0;ctx->registers[i].name!=NULL;i++){ - if(ctx->registers[i].addr==addr) break; - } - *value=*(pcilib_register_value_t*)(base_addr+i*sizeof(uint32_t)); - return 0; -} - -/** - * pcilib_software_registers_write - * this function write the said value to 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 - * @param[in] addr the adress of the register we want to write in - *@param[out] value the value we want to write in the register - * @return 0 in case of success - */ -int pcilib_software_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value){ - int i; - void* base_addr; - - base_addr=pcilib_kmem_get_block_ua(ctx,bank_ctx->kmem_base_address,0); - for(i=0;ctx->registers[i].name!=NULL;i++){ - if(ctx->registers[i].addr==addr) break; - } - *(pcilib_register_value_t*)(base_addr+i*sizeof(uint32_t))=value; - return 0; -} |