summaryrefslogtreecommitdiffstats
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/CMakeLists.txt4
-rw-r--r--protocols/software.c122
-rw-r--r--protocols/software.h (renamed from protocols/software_registers.h)25
-rw-r--r--protocols/software_registers.c114
4 files changed, 137 insertions, 128 deletions
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;
-}