diff options
Diffstat (limited to 'pcilib/register.c')
-rw-r--r-- | pcilib/register.c | 65 |
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; |