11
11
#include <arpa/inet.h>
13
13
#include <assert.h>
22
23
int pcilib_add_registers(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_description_t *registers, pcilib_register_t *ids) {
23
24
// DS: Overrride existing registers
24
25
// Registers identified by addr + offset + size + type or name
26
28
pcilib_register_t i;
27
30
pcilib_register_description_t *regs;
28
31
pcilib_register_context_t *reg_ctx;
33
pcilib_register_bank_t bank = PCILIB_REGISTER_BANK_INVALID;
34
pcilib_register_bank_addr_t bank_addr = (pcilib_register_bank_addr_t)-1;
35
pcilib_register_bank_t *banks;
32
38
for (n = 0; registers[n].bits; n++);
59
65
ctx->alloc_reg = size;
68
banks = (pcilib_register_bank_t*)alloca(n * sizeof(pcilib_register_bank_t));
69
if (!banks) return PCILIB_ERROR_MEMORY;
71
for (i = 0; i < n; i++) {
72
if (registers[i].bank != bank_addr) {
73
bank_addr = registers[i].bank;
74
bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);
75
if (bank == PCILIB_REGISTER_BANK_INVALID) {
76
pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name);
77
return PCILIB_ERROR_INVALID_BANK;
82
// No hash so far, will iterate.
83
pcilib_register_t reg = pcilib_find_register(ctx, ctx->banks[bank].name, registers[i].name);
84
if (reg != PCILIB_REGISTER_INVALID) {
85
pcilib_error("Register %s is already defined in the model", registers[i].name);
86
return PCILIB_ERROR_EXIST;
93
err = pcilib_add_register_properties(ctx, n, banks, registers);
62
96
for (i = 0; i < n; i++) {
63
97
pcilib_register_context_t *cur = &ctx->register_ctx[ctx->num_reg + i];
64
99
cur->reg = ctx->num_reg + i;
65
100
cur->name = registers[i].name;
101
cur->bank = banks[i];
66
102
HASH_ADD_KEYPTR(hh, ctx->reg_hash, cur->name, strlen(cur->name), cur);
69
105
memcpy(ctx->registers + ctx->num_reg, registers, n * sizeof(pcilib_register_description_t));
70
106
memset(ctx->registers + ctx->num_reg + n, 0, sizeof(pcilib_register_description_t));
79
115
ctx->num_reg += n;
85
void pcilib_clean_registers(pcilib_t *ctx) {
120
void pcilib_clean_registers(pcilib_t *ctx, pcilib_register_t start) {
86
121
pcilib_register_t reg;
88
HASH_CLEAR(hh, ctx->reg_hash);
89
for (reg = 0; reg < ctx->num_reg; reg++) {
122
pcilib_register_context_t *reg_ctx, *tmp;
125
HASH_ITER(hh, ctx->reg_hash, reg_ctx, tmp) {
126
if (reg_ctx->reg >= start) {
127
HASH_DEL(ctx->reg_hash, reg_ctx);
131
HASH_CLEAR(hh, ctx->reg_hash);
134
for (reg = start; reg < ctx->num_reg; reg++) {
90
135
if (ctx->register_ctx[reg].views)
91
136
free(ctx->register_ctx[reg].views);
94
139
if (ctx->registers)
95
memset(ctx->registers, 0, sizeof(pcilib_register_description_t));
140
memset(&ctx->registers[start], 0, sizeof(pcilib_register_description_t));
97
142
if (ctx->register_ctx)
98
memset(ctx->register_ctx, 0, ctx->alloc_reg * sizeof(pcilib_register_context_t));
143
memset(&ctx->register_ctx[start], 0, (ctx->alloc_reg - start) * sizeof(pcilib_register_context_t));
145
ctx->num_reg = start;
103
148
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) {