/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to register.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-20 20:01:04 UTC
  • Revision ID: csa@suren.me-20150420200104-b5xny65io8lvoz3w
Big redign of model structures

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
#include <assert.h>
14
14
 
15
15
#include "pci.h"
 
16
#include "bank.h"
16
17
 
17
18
#include "tools.h"
18
19
#include "error.h"
19
20
 
20
 
int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers) {
 
21
 
 
22
int pcilib_add_registers(pcilib_t *ctx, size_t n, const pcilib_register_description_t *registers) {
 
23
        // DS: What we are doing if register exists?
 
24
        
21
25
    pcilib_register_description_t *regs;
22
 
    size_t size, n_present = 0;
 
26
    size_t size;
23
27
 
24
28
    if (!n) {
25
29
        for (n = 0; registers[n].bits; n++);
26
30
    }
27
31
 
28
 
    if (ctx->model_info.registers == pcilib_model[ctx->model].registers) {
29
 
        for (n_present = 0; ctx->model_info.registers[n_present].bits; n_present++);
30
 
        for (size = 1024; size < 2 * (n + n_present + 1); size<<=1);
31
 
        regs = (pcilib_register_description_t*)malloc(size * sizeof(pcilib_register_description_t));
 
32
    if ((ctx->num_reg + n + 1) > ctx->alloc_reg) {
 
33
        for (size = ctx->alloc_reg; size < 2 * (n + ctx->num_reg + 1); size<<=1);
 
34
 
 
35
        regs = (pcilib_register_description_t*)realloc(ctx->registers, size * sizeof(pcilib_register_description_t));
32
36
        if (!regs) return PCILIB_ERROR_MEMORY;
33
 
        
 
37
 
 
38
        ctx->registers = regs;
34
39
        ctx->model_info.registers = regs;
35
 
        ctx->num_reg = n + n_present;
36
40
        ctx->alloc_reg = size;
37
 
        
38
 
        memcpy(ctx->model_info.registers, pcilib_model[ctx->model].registers, (n_present + 1) * sizeof(pcilib_register_description_t));
39
 
    } else {
40
 
        n_present = ctx->num_reg;
41
 
        if ((n_present + n + 1) > ctx->alloc_reg) {
42
 
            for (size = ctx->alloc_reg; size < 2 * (n + n_present + 1); size<<=1);
43
 
 
44
 
            regs = (pcilib_register_description_t*)realloc(ctx->model_info.registers, size * sizeof(pcilib_register_description_t));
45
 
            if (!regs) return PCILIB_ERROR_MEMORY;
46
 
 
47
 
            ctx->model_info.registers = regs;
48
 
            ctx->alloc_reg = size;
49
 
        }
50
 
        ctx->num_reg += n;
51
41
    }
52
42
 
53
 
    memcpy(ctx->model_info.registers + ctx->num_reg, ctx->model_info.registers + n_present, sizeof(pcilib_register_description_t));
54
 
    memcpy(ctx->model_info.registers + n_present, registers, n * sizeof(pcilib_register_description_t));
 
43
    memcpy(ctx->registers + ctx->num_reg, registers, n * sizeof(pcilib_register_description_t));
 
44
    memset(ctx->registers + ctx->num_reg + n, 0, sizeof(pcilib_register_description_t));
 
45
    ctx->num_reg += n;
55
46
 
56
47
    return 0;
57
48
}
58
49
 
59
 
pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
60
 
    pcilib_register_bank_t i;
61
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
62
 
    pcilib_register_bank_description_t *banks = model_info->banks;
63
 
 
64
 
    for (i = 0; banks[i].access; i++)
65
 
        if (banks[i].addr == bank) return i;
66
 
 
67
 
    return -1;
68
 
}
69
 
 
70
 
pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) {
71
 
    pcilib_register_bank_t i;
72
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
73
 
    pcilib_register_bank_description_t *banks = model_info->banks;
74
 
 
75
 
    for (i = 0; banks[i].access; i++)
76
 
        if (!strcasecmp(banks[i].name, bankname)) return i;
77
 
 
78
 
    return -1;
79
 
}
80
 
 
81
 
pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank) {
82
 
    pcilib_register_bank_t res;
83
 
    unsigned long addr;
84
 
    
85
 
    if (!bank) {
86
 
        pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
87
 
        pcilib_register_bank_description_t *banks = model_info->banks;
88
 
        if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0;
89
 
        return -1;
90
 
    }
91
 
    
92
 
    if (pcilib_isxnumber(bank)&&(sscanf(bank,"%lx", &addr) == 1)) {
93
 
        res = pcilib_find_bank_by_addr(ctx, addr);
94
 
        if (res != PCILIB_REGISTER_BANK_INVALID) return res;
95
 
    }
96
 
    
97
 
    return pcilib_find_bank_by_name(ctx, bank);
98
 
}
99
 
 
100
 
    // FIXME create hash during map_register space
101
 
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) {
102
 
    pcilib_register_t i;
103
 
    pcilib_register_bank_t bank_id;
104
 
    pcilib_register_bank_addr_t bank_addr = 0;
105
 
 
106
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
107
 
    pcilib_register_description_t *registers =  model_info->registers;
108
 
    
109
 
    if (bank) {
110
 
        bank_id = pcilib_find_bank(ctx, bank);
111
 
        if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
112
 
            pcilib_error("Invalid bank (%s) is specified", bank);
113
 
            return -1;
114
 
        }
115
 
        
116
 
        bank_addr = model_info->banks[bank_id].addr;
117
 
    }
118
 
    
119
 
    for (i = 0; registers[i].bits; i++) {
120
 
        if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
121
 
    }
122
 
    
123
 
    if ((ctx->model_info.dma_api)&&(!ctx->dma_ctx)&&(pcilib_get_dma_info(ctx))) {
124
 
        registers =  model_info->registers;
125
 
 
126
 
        for (; registers[i].bits; i++) {
127
 
            if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
128
 
        }
129
 
    }
130
 
    
131
 
    return (pcilib_register_t)-1;
132
 
};
133
50
 
134
51
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) {
135
52
    int err;
136
53
    size_t i;
137
 
    
138
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
139
 
    pcilib_register_bank_description_t *b = model_info->banks + bank;
140
 
    
 
54
 
 
55
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
 
56
    const pcilib_register_protocol_api_description_t *bapi = bctx->api;
 
57
    const pcilib_register_bank_description_t *b = bctx->bank;
 
58
 
141
59
    int access = b->access / 8;
142
60
 
143
61
    assert(bits < 8 * sizeof(pcilib_register_value_t));
144
 
    
 
62
 
 
63
    if (!bapi->read) {
 
64
        pcilib_error("Used register protocol does not define a way to read register value");
 
65
        return PCILIB_ERROR_NOTSUPPORTED;
 
66
    }
 
67
 
145
68
    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
146
69
        if ((b->format)&&(strchr(b->format, 'x')))
147
70
            pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
150
73
        return PCILIB_ERROR_OUTOFRANGE;
151
74
    }
152
75
 
153
 
    err = pcilib_map_register_space(ctx);
154
 
    if (err) {
155
 
        pcilib_error("Failed to map the register space");
156
 
        return err;
157
 
    }
 
76
    //err = pcilib_init_register_banks(ctx);
 
77
    //if (err) return err;
158
78
    
159
79
    //n += bits / b->access;
160
80
    //bits %= b->access; 
161
81
    
162
82
    for (i = 0; i < n; i++) {
163
 
        err = pcilib_protocol[b->protocol].read(ctx, b, addr + i * access, buf + i);
 
83
        err = bapi->read(ctx, bctx, addr + i * access, buf + i);
164
84
        if (err) break;
165
85
    }
166
86
    
167
87
    if ((bits > 0)&&(!err)) {
168
88
        pcilib_register_value_t val = 0;
169
 
        err = pcilib_protocol[b->protocol].read(ctx, b, addr + n * access, &val);
 
89
        err = bapi->read(ctx, bctx, addr + n * access, &val);
170
90
 
171
91
        val = (val >> offset)&BIT_MASK(bits);
172
92
        memcpy(buf + n, &val, sizeof(pcilib_register_value_t));
176
96
}
177
97
 
178
98
int pcilib_read_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
179
 
    pcilib_register_bank_t bank_id = pcilib_find_bank(ctx, bank);
 
99
    pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
180
100
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
181
101
        if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
182
102
        else pcilib_error("Register bank should be specified");
192
112
    pcilib_register_size_t bits;
193
113
    pcilib_register_value_t res;
194
114
    pcilib_register_bank_t bank;
195
 
    pcilib_register_description_t *r;
196
 
    pcilib_register_bank_description_t *b;
197
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
115
    const pcilib_register_description_t *r;
 
116
    const pcilib_register_bank_description_t *b;
 
117
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
198
118
 
199
119
    r = model_info->registers + reg;
200
120
    
201
 
    bank = pcilib_find_bank_by_addr(ctx, r->bank);
 
121
    bank = pcilib_find_register_bank_by_addr(ctx, r->bank);
202
122
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
203
123
    
204
124
    b = model_info->banks + bank;
228
148
 
229
149
int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value) {
230
150
    int reg;
231
 
    
 
151
 
232
152
    reg = pcilib_find_register(ctx, bank, regname);
233
153
    if (reg < 0) {
234
154
        pcilib_error("Register (%s) is not found", regname);
235
155
        return PCILIB_ERROR_NOTFOUND;
236
156
    }
237
 
    
 
157
 
238
158
    return pcilib_read_register_by_id(ctx, reg, value);
239
159
}
240
160
 
242
162
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) {
243
163
    int err;
244
164
    size_t i;
245
 
    
246
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
247
 
    pcilib_register_bank_description_t *b = model_info->banks + bank;
 
165
 
 
166
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
 
167
    const pcilib_register_protocol_api_description_t *bapi = bctx->api;
 
168
    const pcilib_register_bank_description_t *b = bctx->bank;
248
169
 
249
170
    int access = b->access / 8;
250
171
 
251
172
    assert(bits < 8 * sizeof(pcilib_register_value_t));
252
173
 
 
174
    if (!bapi->write) {
 
175
        pcilib_error("Used register protocol does not define a way to write value into the register");
 
176
        return PCILIB_ERROR_NOTSUPPORTED;
 
177
    }
 
178
 
253
179
    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
254
180
        if ((b->format)&&(strchr(b->format, 'x')))
255
181
            pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
258
184
        return PCILIB_ERROR_OUTOFRANGE;
259
185
    }
260
186
 
261
 
    err = pcilib_map_register_space(ctx);
262
 
    if (err) {
263
 
        pcilib_error("Failed to map the register space");
264
 
        return err;
265
 
    }
 
187
    //err = pcilib_init_register_banks(ctx);
 
188
    //if (err) return err;
266
189
    
267
190
    //n += bits / b->access;
268
191
    //bits %= b->access; 
269
192
    
270
193
    for (i = 0; i < n; i++) {
271
 
        err = pcilib_protocol[b->protocol].write(ctx, b, addr + i * access, buf[i]);
 
194
        err = bapi->write(ctx, bctx, addr + i * access, buf[i]);
272
195
        if (err) break;
273
196
    }
274
197
    
278
201
 
279
202
        if (~mask&rwmask) {
280
203
            pcilib_register_value_t rval;
281
 
            
282
 
            err = pcilib_protocol[b->protocol].read(ctx, b, addr + n * access, &rval); 
 
204
 
 
205
            if (!bapi->read) {
 
206
                pcilib_error("Used register protocol does not define a way to read register. Therefore, it is only possible to write a full bank word, not partial as required by the accessed register");
 
207
                return PCILIB_ERROR_NOTSUPPORTED;
 
208
            }
 
209
 
 
210
            err = bapi->read(ctx, bctx, addr + n * access, &rval); 
283
211
            if (err) return err;
284
 
            
 
212
 
285
213
            val |= (rval & rwmask & ~mask);
286
214
        }
287
215
        
288
 
        err = pcilib_protocol[b->protocol].write(ctx, b, addr + n * access, val);
 
216
        err = bapi->write(ctx, bctx, addr + n * access, val);
289
217
    }
290
218
    
291
219
    return err;
292
220
}
293
221
 
294
222
int pcilib_write_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
295
 
    pcilib_register_bank_t bank_id = pcilib_find_bank(ctx, bank);
 
223
    pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
296
224
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
297
225
        if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
298
226
        else pcilib_error("Register bank should be specified");
309
237
    pcilib_register_size_t bits;
310
238
    pcilib_register_bank_t bank;
311
239
    pcilib_register_value_t res;
312
 
    pcilib_register_description_t *r;
313
 
    pcilib_register_bank_description_t *b;
314
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
240
    const pcilib_register_description_t *r;
 
241
    const pcilib_register_bank_description_t *b;
 
242
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
315
243
 
316
244
    r = model_info->registers + reg;
317
245
 
318
 
    bank = pcilib_find_bank_by_addr(ctx, r->bank);
 
246
    bank = pcilib_find_register_bank_by_addr(ctx, r->bank);
319
247
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
320
248
 
321
249
    b = model_info->banks + bank;