summaryrefslogtreecommitdiffstats
path: root/pcilib/register.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcilib/register.c')
-rw-r--r--pcilib/register.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/pcilib/register.c b/pcilib/register.c
index 08af871..a166bbd 100644
--- a/pcilib/register.c
+++ b/pcilib/register.c
@@ -74,8 +74,17 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,
bank_addr = registers[i].bank;
bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);
if (bank == PCILIB_REGISTER_BANK_INVALID) {
- pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name);
- return PCILIB_ERROR_INVALID_BANK;
+ // We need to add a bank first in this case
+ if (registers[i].type == PCILIB_REGISTER_PROPERTY) {
+ err = pcilib_add_register_banks(ctx, 0, 1, &pcilib_property_register_bank, &bank);
+ } else {
+ err = PCILIB_ERROR_INVALID_BANK;
+ }
+
+ if (err) {
+ pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name);
+ return err;
+ }
}
}
@@ -91,7 +100,7 @@ int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags,
banks[i] = bank;
}
- err = pcilib_add_register_properties(ctx, n, banks, registers);
+ err = pcilib_add_properties_from_registers(ctx, n, banks, registers);
if (err) return err;
for (i = 0; i < n; i++) {
@@ -148,7 +157,9 @@ void pcilib_clean_registers(pcilib_t *ctx, pcilib_register_t start) {
static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t *buf) {
int err;
+
size_t i;
+ size_t space_size;
pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
const pcilib_register_protocol_api_description_t *bapi = bctx->api;
@@ -163,14 +174,31 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba
return PCILIB_ERROR_NOTSUPPORTED;
}
- if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views;
+ else space_size = b->size;
+
+ if (((addr + n) > space_size)||(((addr + n) == space_size)&&(bits))) {
if ((b->format)&&(strchr(b->format, 'x')))
- pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);
else
- pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);
return PCILIB_ERROR_OUTOFRANGE;
}
+ if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) {
+ for (i = 0; i < (bits?(n+1):n); i++) {
+ if ((ctx->views[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) {
+ pcilib_error("Accessing invalid register %u (associated view does not provide register functionality)", addr + i);
+ return PCILIB_ERROR_INVALID_REQUEST;
+ }
+
+ if ((ctx->views[i]->mode&PCILIB_ACCESS_R) == 0) {
+ pcilib_error("Read access is not allowed to register %u", addr + i);
+ return PCILIB_ERROR_NOTPERMITED;
+ }
+ }
+ }
+
//err = pcilib_init_register_banks(ctx);
//if (err) return err;
@@ -259,7 +287,9 @@ int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, p
static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t rwmask, pcilib_register_value_t *buf) {
int err;
+
size_t i;
+ size_t space_size;
pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
const pcilib_register_protocol_api_description_t *bapi = bctx->api;
@@ -274,14 +304,31 @@ static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_b
return PCILIB_ERROR_NOTSUPPORTED;
}
- if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views;
+ else space_size = b->size;
+
+ if (((addr + n) > space_size)||(((addr + n) == space_size)&&(bits))) {
if ((b->format)&&(strchr(b->format, 'x')))
- pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);
else
- pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, space_size);
return PCILIB_ERROR_OUTOFRANGE;
}
+ if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) {
+ for (i = 0; i < (bits?(n+1):n); i++) {
+ if ((ctx->views[i]->flags&PCILIB_VIEW_FLAG_REGISTER) == 0) {
+ pcilib_error("Accessing invalid register %u (associated view does not provide register functionality)", addr + i);
+ return PCILIB_ERROR_INVALID_REQUEST;
+ }
+
+ if ((ctx->views[i]->mode&PCILIB_ACCESS_W) == 0) {
+ pcilib_error("Write access is not allowed to register %u", addr + i);
+ return PCILIB_ERROR_NOTPERMITED;
+ }
+ }
+ }
+
//err = pcilib_init_register_banks(ctx);
//if (err) return err;