From ca7353be486a0364a3460b511291a40182f130ba Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@suren.me>
Date: Wed, 18 Nov 2015 03:25:02 +0100
Subject: Provide API calls for register and bank address resolution

---
 protocols/default.c  | 35 +++++++++++++++++++++++++++++++++--
 protocols/default.h  |  3 ++-
 protocols/property.h |  2 +-
 protocols/software.c | 15 +++++++++++++++
 protocols/software.h | 12 +++++++++++-
 5 files changed, 62 insertions(+), 5 deletions(-)

(limited to 'protocols')

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
@@ -27,6 +27,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
@@ -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 */
-- 
cgit v1.2.3