summaryrefslogtreecommitdiffstats
path: root/pci.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2012-11-14 01:08:27 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2012-11-14 01:08:27 +0100
commit82f2ca1e370e5e1461379e42a355ef535228bc78 (patch)
tree479a99afb26a497cf0403ef10f0e6bdf87d21084 /pci.c
parentdb56e69bb654a8447b9c6844bb53791cef7d07ba (diff)
downloadipecamera-82f2ca1e370e5e1461379e42a355ef535228bc78.tar.gz
ipecamera-82f2ca1e370e5e1461379e42a355ef535228bc78.tar.bz2
ipecamera-82f2ca1e370e5e1461379e42a355ef535228bc78.tar.xz
ipecamera-82f2ca1e370e5e1461379e42a355ef535228bc78.zip
Automatically select PCI Bar if only one present
Diffstat (limited to 'pci.c')
-rw-r--r--pci.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/pci.c b/pci.c
index b1286d5..5164111 100644
--- a/pci.c
+++ b/pci.c
@@ -96,15 +96,23 @@ pcilib_model_t pcilib_get_model(pcilib_t *ctx) {
}
static pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) {
+ int n = 0;
pcilib_bar_t i;
const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx);
if (!board_info) return PCILIB_BAR_INVALID;
for (i = 0; i < PCILIB_MAX_BANKS; i++) {
- if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return 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;
+
+ if (n) n = -1;
+ else n = i + 1;
+ }
}
-
+
+ if (n > 0) return n - 1;
+
return PCILIB_BAR_INVALID;
}
@@ -114,24 +122,26 @@ static int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *ad
if (*bar == PCILIB_BAR_DETECT) {
*bar = pcilib_detect_bar(ctx, *addr, size);
- if (*bar < 0) {
- pcilib_error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
+ if (*bar == PCILIB_BAR_INVALID) {
+ pcilib_error("The requested data block at address 0x%x with size %zu does not belongs to any available memory bank", *addr, size);
return PCILIB_ERROR_NOTFOUND;
}
+ if (*addr < board_info->bar_start[*bar])
+ *addr += board_info->bar_start[*bar];
} else {
if ((*addr < board_info->bar_start[*bar])||((board_info->bar_start[*bar] + board_info->bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
if ((board_info->bar_length[*bar]) >= (((uintptr_t)*addr) + size)) {
*addr += board_info->bar_start[*bar];
} else {
- pcilib_error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]);
+ pcilib_error("The requested data block at address 0x%x with size %zu does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]);
return PCILIB_ERROR_NOTFOUND;
}
}
}
-
+
*addr -= board_info->bar_start[*bar];
*addr += board_info->bar_start[*bar] & ctx->page_mask;
-
+
return 0;
}