Răsfoiți Sursa

Provide pcilib_get_bar_info & pcilib_get_bar_list API calls, remove obsolete pcilib_resolve_register_address

Suren A. Chilingaryan 8 ani în urmă
părinte
comite
ec667d49f8
3 a modificat fișierele cu 63 adăugiri și 40 ștergeri
  1. 50 30
      pcilib/bar.c
  2. 11 10
      pcilib/bar.h
  3. 2 0
      pcilib/pci.h

+ 50 - 30
pcilib/bar.c

@@ -24,11 +24,15 @@
 
 pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) {
     int n = 0;
-    pcilib_bar_t i;
+    pcilib_bar_t i = ctx->reg_bar;
 	
     const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
     if (!board_info) return PCILIB_BAR_INVALID;
-		
+
+	// First checking the default register bar
+    if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i;
+
+	// Otherwise iterate
     for (i = 0; i < PCILIB_MAX_BARS; i++) {
 	if (board_info->bar_length[i] > 0) {
 	    if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i;
@@ -131,26 +135,20 @@ void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) {
 }
 
 char *pcilib_resolve_bar_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr) {
-    if (bar == PCILIB_BAR_DETECT) {    
+    if (bar == PCILIB_BAR_DETECT) {
 	bar = pcilib_detect_bar(ctx, addr, 1);
-	if (bar != PCILIB_BAR_INVALID) {
-	    size_t offset = addr - ctx->board_info.bar_start[bar];
-	    if ((offset < ctx->board_info.bar_length[bar])&&(ctx->bar_space[bar])) {
-		if (!ctx->bar_space[bar]) {
-		    if (!pcilib_map_bar(ctx, bar)) {
-			pcilib_error("Failed to map the requested bar (%i)", bar);
-			return NULL;
-		    }
-		}
-		return ctx->bar_space[bar] + offset + (ctx->board_info.bar_start[bar] & ctx->page_mask);
-	    }
+	if (bar == PCILIB_BAR_INVALID) return NULL;
+	
+	if ((!ctx->bar_space[bar])&&(!pcilib_map_bar(ctx, bar))) {
+	    pcilib_error("Failed to map the requested bar (%i)", bar);
+	    return NULL;
 	}
+
+	return ctx->bar_space[bar] + (addr - ctx->board_info.bar_start[bar]) + (ctx->board_info.bar_start[bar] & ctx->page_mask);
     } else {
-	if (!ctx->bar_space[bar]) {
-	    if (!pcilib_map_bar(ctx, bar)) {
-		pcilib_error("Failed to map the requested bar (%i)", bar);
-		return NULL;
-	    }
+	if ((!ctx->bar_space[bar])&&(!pcilib_map_bar(ctx, bar))) {
+	    pcilib_error("Failed to map the requested bar (%i)", bar);
+	    return NULL;
 	}
 	
 	if (addr < ctx->board_info.bar_length[bar]) {
@@ -218,17 +216,6 @@ int pcilib_map_register_space(pcilib_t *ctx) {
     return 0;
 }
 
-char *pcilib_resolve_register_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr) {
-    if (bar == PCILIB_BAR_DETECT) {
-	    // First checking the default register bar
-	size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];
-	if ((addr > ctx->board_info.bar_start[ctx->reg_bar])&&(offset < ctx->board_info.bar_length[ctx->reg_bar])) {
-	    return pcilib_resolve_bar_address(ctx, ctx->reg_bar, addr - ctx->board_info.bar_start[ctx->reg_bar]);
-	}
-    }
-	// Otherwise trying to detect
-    return pcilib_resolve_bar_address(ctx, bar, addr);
-}
 
 int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) {
     int err;
@@ -302,6 +289,39 @@ char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) {
     return ctx->bar_space[ctx->data_bar] + (ctx->board_info.bar_start[ctx->data_bar] & ctx->page_mask);
 }
 
+const pcilib_bar_info_t *pcilib_get_bar_list(pcilib_t *ctx) {
+    int i, bars = 0;
+
+    const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
+    if (!board_info) return NULL;
+
+    for (i = 0; i < PCILIB_MAX_BARS; i++) {
+	if (board_info->bar_length[i] > 0) {
+	    ctx->bar_info[bars++] = (pcilib_bar_info_t) {
+		.bar = i,
+		.size = board_info->bar_length[i],
+		.phys_addr =  board_info->bar_start[i],
+		.virt_addr = ctx->bar_space[i]
+	    };
+	}
+    }
+
+    return ctx->bar_info;
+}
+
+const pcilib_bar_info_t *pcilib_get_bar_info(pcilib_t *ctx, pcilib_bar_t bar) {
+    int i;
+
+    const pcilib_bar_info_t *info = pcilib_get_bar_list(ctx);
+    if (!info) return NULL;
+
+    for (i = 0; info[i].size; i++) {
+	if (info[i].bar == bar)
+	    return &info[i];
+    }
+
+    return NULL;
+}
 
 int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
     void *data;

+ 11 - 10
pcilib/bar.h

@@ -1,6 +1,15 @@
 #ifndef _PCILIB_BAR_H
 #define _PCILIB_BAR_H
 
+
+typedef struct {
+    pcilib_bar_t bar;
+    size_t size;
+    uintptr_t phys_addr;
+    void *virt_addr;
+} pcilib_bar_info_t;
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -63,17 +72,9 @@ int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, siz
  */
 char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size);
 
+const pcilib_bar_info_t *pcilib_get_bar_info(pcilib_t *ctx, pcilib_bar_t bar);
+const pcilib_bar_info_t *pcilib_get_bar_list(pcilib_t *ctx);
 
-/**
- * The wrapper arround pcilib_resolve_bar_address() provided for backward compatibility. 
- * If bar is not specified, it first checks the first BAR with registers, before searching
- * in other available BARs.
- * @param[in,out] ctx	- pcilib context
- * @param[in] bar	- specifies the BAR address belong to, use PCILIB_BAR_DETECT for autodetection
- * @param[in] addr	- specifies the physical address on the PCI bus or offset in the BAR if \a bar is specified
- * @return		- the virtual address in the process address space or NULL in case of error
- */
-char *pcilib_resolve_register_address(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr);	
 
 #ifdef __cplusplus
 }

+ 2 - 0
pcilib/pci.h

@@ -22,6 +22,7 @@
 
 #include "timing.h"
 #include "cpu.h"
+#include "bar.h"
 #include "pcilib.h"
 #include "register.h"
 #include "kmem.h"
@@ -50,6 +51,7 @@ struct pcilib_s {
     pcilib_board_info_t board_info;							/**< The mandatory information about board as defined by PCI specification */
     pcilib_pcie_link_info_t link_info;							/**< Infomation about PCIe connection */
     char *bar_space[PCILIB_MAX_BARS];							/**< Pointers to the mapped BARs in virtual address space */
+    pcilib_bar_info_t bar_info[PCILIB_MAX_BARS + 1];					/**< NULL terminated list of PCI bar descriptions */
 
     int pci_cfg_space_fd;								/**< File descriptor linking to PCI configuration space in sysfs */
     uint32_t pci_cfg_space_cache[64];							/**< Cached PCI configuration space */