summaryrefslogtreecommitdiffstats
path: root/pci.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-09 01:45:29 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-09 01:45:29 +0100
commit1f39476f289cd6ac1f45da7f0d9b528b4bc9a978 (patch)
tree295c7283a6e665afb01d882dba950d99ee31209b /pci.c
parent7f97ea07417de4c2ea260e2860e589011c732e04 (diff)
downloadipecamera-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.gz
ipecamera-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.bz2
ipecamera-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.xz
ipecamera-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.zip
Better handling of register banks
Diffstat (limited to 'pci.c')
-rw-r--r--pci.c82
1 files changed, 62 insertions, 20 deletions
diff --git a/pci.c b/pci.c
index af3fc72..48cc318 100644
--- a/pci.c
+++ b/pci.c
@@ -202,30 +202,65 @@ int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, v
}
+static pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
+ pcilib_register_bank_t i;
+ pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
+
+ for (i = 0; banks[i].access; i++)
+ if (banks[i].addr == bank) return i;
+
+ return -1;
+}
+
+static pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) {
+ pcilib_register_bank_t i;
+ pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
+
+ for (i = 0; banks[i].access; i++)
+ if (!strcasecmp(banks[i].name, bankname)) return i;
+
+ return -1;
+}
+
+pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank) {
+ pcilib_register_bank_t res;
+ unsigned long addr;
+
+ if (sscanf(bank,"%lx", &addr) == 1) {
+ res = pcilib_find_bank_by_addr(ctx, addr);
+ if (res != PCILIB_REGISTER_BANK_INVALID) return res;
+ }
+
+ return pcilib_find_bank_by_name(ctx, bank);
+}
+
// FIXME create hash during map_register space
-pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg) {
+pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) {
pcilib_register_t i;
+ pcilib_register_bank_t bank_id;
+ pcilib_register_bank_addr_t bank_addr;
pcilib_model_t model = pcilib_get_model(ctx);
pcilib_register_description_t *registers = pcilib_model[model].registers;
+ if (bank) {
+ bank_id = pcilib_find_bank(ctx, bank);
+ if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
+ pcilib_error("Invalid bank (%s) is specified", bank);
+ return -1;
+ }
+
+ bank_addr = pcilib_model[ctx->model].banks[bank_id].addr;
+ }
+
for (i = 0; registers[i].bits; i++) {
- if (!strcasecmp(registers[i].name, reg)) return i;
+ if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
}
return -1;
};
-static pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
- pcilib_register_bank_t i;
- pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
-
- for (i = 0; banks[i].access; i++)
- if (banks[i].addr == bank) return i;
-
- return -1;
-}
static int pcilib_map_register_space(pcilib_t *ctx) {
@@ -283,9 +318,6 @@ void pcilib_close(pcilib_t *ctx) {
}
}
-
-
-
static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, uint8_t bits, pcilib_register_value_t *buf) {
int err;
int rest;
@@ -294,6 +326,11 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba
pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
assert(bits < 8 * sizeof(pcilib_register_value_t));
+
+ if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ return PCILIB_ERROR_OUTOFRANGE;
+ }
err = pcilib_map_register_space(ctx);
if (err) {
@@ -314,8 +351,8 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba
return err;
}
-int pcilib_read_register_space(pcilib_t *ctx, pcilib_register_bank_addr_t bank_addr, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
- pcilib_register_bank_t bank = pcilib_find_bank(ctx, bank_addr);
+int pcilib_read_register_space(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
+// pcilib_register_bank_t bank = pcilib_find_bank(ctx, bank_addr);
return pcilib_read_register_space_internal(ctx, bank, addr, n, 0, buf);
}
@@ -352,11 +389,11 @@ int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_regi
}
-int pcilib_read_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t *value) {
+int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value) {
int err;
int reg;
- reg = pcilib_find_register(ctx, regname);
+ reg = pcilib_find_register(ctx, bank, regname);
if (reg < 0) {
pcilib_error("Register (%s) is not found", regname);
return PCILIB_ERROR_NOTFOUND;
@@ -378,6 +415,11 @@ static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_b
assert(bits < 8 * sizeof(pcilib_register_value_t));
+ if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ return PCILIB_ERROR_OUTOFRANGE;
+ }
+
err = pcilib_map_register_space(ctx);
if (err) {
pcilib_error("Failed to map the register space");
@@ -432,11 +474,11 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg
return err;
}
-int pcilib_write_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t value) {
+int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value) {
int err;
int reg;
- reg = pcilib_find_register(ctx, regname);
+ reg = pcilib_find_register(ctx, bank, regname);
if (reg < 0) pcilib_error("Register (%s) is not found", regname);
return pcilib_write_register_by_id(ctx, reg, value);