diff options
| author | Suren A. Chilingaryan <csa@suren.me> | 2015-11-18 03:24:04 +0100 | 
|---|---|---|
| committer | Suren A. Chilingaryan <csa@suren.me> | 2015-11-18 03:24:04 +0100 | 
| commit | ec667d49f84c45c261f050313d64f89ce88e4302 (patch) | |
| tree | c016cba088cc680f5d7d43e06031bfd9b635ae2e | |
| parent | 52e32b2c9f0e5ac7cfb31fd2306e6536340955e1 (diff) | |
Provide pcilib_get_bar_info & pcilib_get_bar_list API calls, remove obsolete pcilib_resolve_register_address
| -rw-r--r-- | pcilib/bar.c | 80 | ||||
| -rw-r--r-- | pcilib/bar.h | 21 | ||||
| -rw-r--r-- | pcilib/pci.h | 2 | 
3 files changed, 63 insertions, 40 deletions
| diff --git a/pcilib/bar.c b/pcilib/bar.c index 095fa4a..6d6cd6d 100644 --- a/pcilib/bar.c +++ b/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; diff --git a/pcilib/bar.h b/pcilib/bar.h index deb6f81..3c0eef6 100644 --- a/pcilib/bar.h +++ b/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  } diff --git a/pcilib/pci.h b/pcilib/pci.h index 1b61f70..50c6c0e 100644 --- a/pcilib/pci.h +++ b/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 */ | 
