summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-11-18 03:24:04 +0100
committerSuren A. Chilingaryan <csa@suren.me>2015-11-18 03:24:04 +0100
commitec667d49f84c45c261f050313d64f89ce88e4302 (patch)
treec016cba088cc680f5d7d43e06031bfd9b635ae2e
parent52e32b2c9f0e5ac7cfb31fd2306e6536340955e1 (diff)
downloadpcitool-ec667d49f84c45c261f050313d64f89ce88e4302.tar.gz
pcitool-ec667d49f84c45c261f050313d64f89ce88e4302.tar.bz2
pcitool-ec667d49f84c45c261f050313d64f89ce88e4302.tar.xz
pcitool-ec667d49f84c45c261f050313d64f89ce88e4302.zip
Provide pcilib_get_bar_info & pcilib_get_bar_list API calls, remove obsolete pcilib_resolve_register_address
-rw-r--r--pcilib/bar.c80
-rw-r--r--pcilib/bar.h21
-rw-r--r--pcilib/pci.h2
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 */