/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: 2011-07-09 03:33:18 UTC
  • Revision ID: csa@dside.dyndns.org-20110709033318-2k7vk5s5p5u7btem
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include "tools.h"
18
18
#include "error.h"
19
19
 
 
20
int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers) {
 
21
    pcilib_register_description_t *regs;
 
22
    size_t size, n_present, n_new;
 
23
 
 
24
    if (!n) {
 
25
        for (n = 0; registers[n].bits; n++);
 
26
    }
 
27
 
 
28
 
 
29
    if (ctx->model_info.registers == pcilib_model[ctx->model].registers) {
 
30
        for (n_present = 0; ctx->model_info.registers[n_present].bits; n_present++);
 
31
        for (size = 1024; size < 2 * (n + n_present + 1); size<<=1);
 
32
        regs = (pcilib_register_description_t*)malloc(size * sizeof(pcilib_register_description_t));
 
33
        if (!regs) return PCILIB_ERROR_MEMORY;
 
34
        
 
35
        ctx->model_info.registers = regs;
 
36
        ctx->num_reg = n + n_present;
 
37
        ctx->alloc_reg = size;
 
38
        
 
39
        memcpy(ctx->model_info.registers, pcilib_model[ctx->model].registers, (n_present + 1) * sizeof(pcilib_register_description_t));
 
40
    } else {
 
41
        n_present = ctx->num_reg;
 
42
        if ((n_present + n + 1) > ctx->alloc_reg) {
 
43
            for (size = ctx->alloc_reg; size < 2 * (n + n_present + 1); size<<=1);
 
44
 
 
45
            regs = (pcilib_register_description_t*)realloc(ctx->model_info.registers, size * sizeof(pcilib_register_description_t));
 
46
            if (!regs) return PCILIB_ERROR_MEMORY;
 
47
            
 
48
            ctx->model_info.registers = regs;
 
49
            ctx->alloc_reg = size;
 
50
        }
 
51
        ctx->num_reg += n;
 
52
    }
 
53
    
 
54
    memcpy(ctx->model_info.registers + ctx->num_reg, ctx->model_info.registers + n_present, sizeof(pcilib_register_description_t));
 
55
    memcpy(ctx->model_info.registers + n_present, registers, n * sizeof(pcilib_register_description_t));
 
56
    
 
57
    return 0;    
 
58
}
 
59
 
20
60
pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
21
61
    pcilib_register_bank_t i;
22
 
    pcilib_model_t model = pcilib_get_model(ctx);
23
 
    pcilib_register_bank_description_t *banks = pcilib_model[model].banks;
 
62
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
63
    pcilib_register_bank_description_t *banks = model_info->banks;
24
64
 
25
65
    for (i = 0; banks[i].access; i++)
26
66
        if (banks[i].addr == bank) return i;
30
70
 
31
71
pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) {
32
72
    pcilib_register_bank_t i;
33
 
    pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
 
73
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
74
    pcilib_register_bank_description_t *banks = model_info->banks;
34
75
 
35
76
    for (i = 0; banks[i].access; i++)
36
77
        if (!strcasecmp(banks[i].name, bankname)) return i;
43
84
    unsigned long addr;
44
85
    
45
86
    if (!bank) {
46
 
        pcilib_model_t model = pcilib_get_model(ctx);
47
 
        pcilib_register_bank_description_t *banks = pcilib_model[model].banks;
 
87
        pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
88
        pcilib_register_bank_description_t *banks = model_info->banks;
48
89
        if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0;
49
90
        return -1;
50
91
    }
62
103
    pcilib_register_t i;
63
104
    pcilib_register_bank_t bank_id;
64
105
    pcilib_register_bank_addr_t bank_addr;
65
 
    
66
 
    pcilib_model_t model = pcilib_get_model(ctx);
67
 
    
68
 
    pcilib_register_description_t *registers =  pcilib_model[model].registers;
 
106
 
 
107
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
108
    pcilib_register_description_t *registers =  model_info->registers;
69
109
    
70
110
    if (bank) {
71
111
        bank_id = pcilib_find_bank(ctx, bank);
74
114
            return -1;
75
115
        }
76
116
        
77
 
        bank_addr = pcilib_model[model].banks[bank_id].addr;
 
117
        bank_addr = model_info->banks[bank_id].addr;
78
118
    }
79
119
    
80
120
    for (i = 0; registers[i].bits; i++) {
81
121
        if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
82
122
    }
83
123
    
 
124
    if ((ctx->model_info.dma_api)&&(!ctx->dma_ctx)&&(pcilib_get_dma_info(ctx))) {
 
125
        registers =  model_info->registers;
 
126
 
 
127
        for (; registers[i].bits; i++) {
 
128
            if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
 
129
        }
 
130
    }
 
131
    
84
132
    return (pcilib_register_t)-1;
85
133
};
86
134
 
87
 
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) {
 
135
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) {
88
136
    int err;
89
137
    int rest;
90
138
    size_t i;
91
139
    
92
 
    pcilib_model_t model = pcilib_get_model(ctx);
93
 
    pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank;
 
140
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
141
    pcilib_register_bank_description_t *b = model_info->banks + bank;
94
142
 
95
143
    assert(bits < 8 * sizeof(pcilib_register_value_t));
96
144
    
97
145
    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
98
 
        pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
 
146
        pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
99
147
        return PCILIB_ERROR_OUTOFRANGE;
100
148
    }
101
149
 
109
157
    //bits %= b->access; 
110
158
    
111
159
    for (i = 0; i < n; i++) {
112
 
        err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, b->access, buf + i);
 
160
        err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, buf + i);
113
161
        if (err) break;
114
162
    }
115
163
    
116
 
    if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, bits, buf + n);
 
164
    if ((bits > 0)&&(!err)) {
 
165
        pcilib_register_value_t val = 0;
 
166
        err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, &val);
 
167
 
 
168
        val = (val >> offset)&BIT_MASK(bits);
 
169
        memcpy(buf + n, &val, sizeof(pcilib_register_value_t));
 
170
    }
117
171
    
118
172
    return err;
119
173
}
126
180
        return PCILIB_ERROR_INVALID_BANK;
127
181
    }
128
182
    
129
 
    return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, buf);
 
183
    return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, 0, buf);
130
184
}
131
185
 
132
186
int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value) {
133
187
    int err;
134
 
    size_t i, n, bits;
 
188
    size_t i, n;
 
189
    pcilib_register_size_t bits;
135
190
    pcilib_register_value_t res;
 
191
    pcilib_register_bank_t bank;
136
192
    pcilib_register_description_t *r;
137
193
    pcilib_register_bank_description_t *b;
138
 
    pcilib_model_t model = pcilib_get_model(ctx);
 
194
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
139
195
 
140
 
    r = pcilib_model[model].registers + reg;
141
 
    b = pcilib_model[model].banks + r->bank;
 
196
    r = model_info->registers + reg;
 
197
    
 
198
    bank = pcilib_find_bank_by_addr(ctx, r->bank);
 
199
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
 
200
    
 
201
    b = model_info->banks + bank;
142
202
    
143
203
    n = r->bits / b->access;
144
204
    bits = r->bits % b->access; 
145
205
 
146
206
    pcilib_register_value_t buf[n + 1];
147
 
    err = pcilib_read_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
 
207
    err = pcilib_read_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, buf);
148
208
 
149
209
    if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) {
150
210
        pcilib_error("Big-endian byte order support is not implemented");
174
234
    }
175
235
    
176
236
    return pcilib_read_register_by_id(ctx, reg, value);
177
 
 
178
 
//    registers[reg].bank
179
 
//    printf("%li %li", sizeof(pcilib_model[model].banks), sizeof(pcilib_register_bank_description_t));
180
237
}
181
238
 
182
239
 
183
 
static int pcilib_write_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) {
 
240
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) {
184
241
    int err;
185
242
    int rest;
186
243
    size_t i;
187
244
    
188
 
    pcilib_model_t model = pcilib_get_model(ctx);
189
 
    pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank;
 
245
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
246
    pcilib_register_bank_description_t *b = model_info->banks + bank;
190
247
 
191
248
    assert(bits < 8 * sizeof(pcilib_register_value_t));
192
249
 
193
250
    if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
194
 
        pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
 
251
        pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
195
252
        return PCILIB_ERROR_OUTOFRANGE;
196
253
    }
197
254
 
205
262
    //bits %= b->access; 
206
263
    
207
264
    for (i = 0; i < n; i++) {
208
 
        err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, b->access, buf[i]);
 
265
        err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, buf[i]);
209
266
        if (err) break;
210
267
    }
211
268
    
212
 
    if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, bits, buf[n]);
 
269
    if ((bits > 0)&&(!err)) {
 
270
        pcilib_register_value_t val = (buf[n]&BIT_MASK(bits))<<offset;
 
271
        pcilib_register_value_t mask = BIT_MASK(bits)<<offset;
 
272
 
 
273
        if (~mask&rwmask) {
 
274
            pcilib_register_value_t rval;
 
275
            
 
276
            err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, &rval); 
 
277
            if (err) return err;
 
278
            
 
279
            val |= (rval & rwmask & ~mask);
 
280
        }
 
281
        
 
282
        err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, val);
 
283
    }
213
284
    
214
285
    return err;
215
286
}
222
293
        return PCILIB_ERROR_INVALID_BANK;
223
294
    }
224
295
    
225
 
    return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, buf);
 
296
    return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, 0, 0, buf);
226
297
}
227
298
 
228
299
 
229
300
int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value) {
230
301
    int err;
231
 
    size_t i, n, bits;
 
302
    size_t i, n;
 
303
    pcilib_register_size_t bits;
 
304
    pcilib_register_bank_t bank;
232
305
    pcilib_register_value_t res;
233
306
    pcilib_register_description_t *r;
234
307
    pcilib_register_bank_description_t *b;
235
 
    pcilib_model_t model = pcilib_get_model(ctx);
236
 
 
237
 
    r = pcilib_model[model].registers + reg;
238
 
    b = pcilib_model[model].banks + r->bank;
 
308
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
 
309
 
 
310
    r = model_info->registers + reg;
 
311
 
 
312
    bank = pcilib_find_bank_by_addr(ctx, r->bank);
 
313
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
 
314
 
 
315
    b = model_info->banks + bank;
239
316
    
240
317
    n = r->bits / b->access;
241
318
    bits = r->bits % b->access; 
262
339
        }
263
340
    }
264
341
 
265
 
    err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
 
342
    err = pcilib_write_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, r->rwmask, buf);
266
343
    return err;
267
344
}
268
345