/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
1
#include <stdio.h>
2
#include <string.h>
3
#include <strings.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <stdarg.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include <sys/ioctl.h>
10
#include <sys/mman.h>
11
#include <arpa/inet.h>
12
#include <errno.h>
13
#include <assert.h>
315 by Suren A. Chilingaryan
Support properties of arbitrary type
14
#include <alloca.h>
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
15
16
#include "pci.h"
236 by Suren A. Chilingaryan
Big redign of model structures
17
#include "bank.h"
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
18
330 by Suren A. Chilingaryan
Support for 64-bit registes
19
#include "datacpy.h"
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
20
#include "tools.h"
21
#include "error.h"
315 by Suren A. Chilingaryan
Support properties of arbitrary type
22
#include "property.h"
319 by Suren A. Chilingaryan
Provide register listings in public API
23
#include "views/enum.h"
236 by Suren A. Chilingaryan
Big redign of model structures
24
303 by Suren A. Chilingaryan
Initial integration of XML support
25
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) {
242 by Suren A. Chilingaryan
Initial support for event engines
26
	// DS: Overrride existing registers 
249 by Suren A. Chilingaryan
Create dummy register context
27
	// Registers identified by addr + offset + size + type or name
315 by Suren A. Chilingaryan
Support properties of arbitrary type
28
    int err;
29
    size_t size;
310 by Suren A. Chilingaryan
Introduce hashes
30
    pcilib_register_t i;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
31
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
32
    pcilib_register_description_t *regs;
249 by Suren A. Chilingaryan
Create dummy register context
33
    pcilib_register_context_t *reg_ctx;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
34
35
    pcilib_register_bank_t bank = PCILIB_REGISTER_BANK_INVALID;
36
    pcilib_register_bank_addr_t bank_addr = (pcilib_register_bank_addr_t)-1;
37
    pcilib_register_bank_t *banks;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
38
39
    if (!n) {
40
	for (n = 0; registers[n].bits; n++);
41
    }
42
236 by Suren A. Chilingaryan
Big redign of model structures
43
    if ((ctx->num_reg + n + 1) > ctx->alloc_reg) {
44
	for (size = ctx->alloc_reg; size < 2 * (n + ctx->num_reg + 1); size<<=1);
45
46
	regs = (pcilib_register_description_t*)realloc(ctx->registers, size * sizeof(pcilib_register_description_t));
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
47
	if (!regs) return PCILIB_ERROR_MEMORY;
236 by Suren A. Chilingaryan
Big redign of model structures
48
49
	ctx->registers = regs;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
50
	ctx->model_info.registers = regs;
249 by Suren A. Chilingaryan
Create dummy register context
51
52
	reg_ctx = (pcilib_register_context_t*)realloc(ctx->registers, size * sizeof(pcilib_register_context_t));
53
	if (!reg_ctx) return PCILIB_ERROR_MEMORY;
54
	
55
	memset(reg_ctx + ctx->alloc_reg, 0, (size - ctx->alloc_reg) * sizeof(pcilib_register_context_t));
56
310 by Suren A. Chilingaryan
Introduce hashes
57
	if (ctx->register_ctx != reg_ctx) {
58
	        // We need to recreate cache if context is moved...
59
	    HASH_CLEAR(hh, ctx->reg_hash);
60
	    for (i = 0; i < ctx->num_reg; i++) {
61
                pcilib_register_context_t *cur = &ctx->register_ctx[ctx->num_reg + i];
62
                HASH_ADD_KEYPTR(hh, ctx->reg_hash, cur->name, strlen(cur->name), cur);
63
	    }
64
	}
65
249 by Suren A. Chilingaryan
Create dummy register context
66
	ctx->register_ctx = reg_ctx;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
67
	ctx->alloc_reg = size;
68
    }
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
69
315 by Suren A. Chilingaryan
Support properties of arbitrary type
70
    banks = (pcilib_register_bank_t*)alloca(n * sizeof(pcilib_register_bank_t));
71
    if (!banks) return PCILIB_ERROR_MEMORY;
72
73
    for (i = 0; i < n; i++) {
74
        if (registers[i].bank != bank_addr) {
75
            bank_addr = registers[i].bank;
76
            bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);
77
            if (bank == PCILIB_REGISTER_BANK_INVALID) {
321 by Suren A. Chilingaryan
Support computed (property-based) registers
78
                    // We need to add a bank first in this case
79
                if (registers[i].type == PCILIB_REGISTER_PROPERTY) {
80
                    err = pcilib_add_register_banks(ctx, 0, 1, &pcilib_property_register_bank, &bank);
81
                } else {
82
                    err = PCILIB_ERROR_INVALID_BANK;
83
                }
84
85
                if (err) {
86
                    pcilib_error("Invalid bank address (0x%lx) is specified for register %s", bank_addr, registers[i].name);
87
                    return err;
88
                }
315 by Suren A. Chilingaryan
Support properties of arbitrary type
89
            }
90
        }
91
92
/*
93
            // No hash so far, will iterate.
94
        pcilib_register_t reg = pcilib_find_register(ctx, ctx->banks[bank].name, registers[i].name);
95
        if (reg != PCILIB_REGISTER_INVALID) {
96
            pcilib_error("Register %s is already defined in the model", registers[i].name);
97
            return PCILIB_ERROR_EXIST;
98
        }
99
*/
100
101
        banks[i] = bank;
102
    }
103
321 by Suren A. Chilingaryan
Support computed (property-based) registers
104
    err = pcilib_add_properties_from_registers(ctx, n, banks, registers);
315 by Suren A. Chilingaryan
Support properties of arbitrary type
105
    if (err) return err;
106
310 by Suren A. Chilingaryan
Introduce hashes
107
    for (i = 0; i < n; i++) {
108
        pcilib_register_context_t *cur = &ctx->register_ctx[ctx->num_reg + i];
315 by Suren A. Chilingaryan
Support properties of arbitrary type
109
310 by Suren A. Chilingaryan
Introduce hashes
110
        cur->reg = ctx->num_reg + i;
111
        cur->name = registers[i].name;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
112
        cur->bank = banks[i];
310 by Suren A. Chilingaryan
Introduce hashes
113
        HASH_ADD_KEYPTR(hh, ctx->reg_hash, cur->name, strlen(cur->name), cur);
114
    }
315 by Suren A. Chilingaryan
Support properties of arbitrary type
115
236 by Suren A. Chilingaryan
Big redign of model structures
116
    memcpy(ctx->registers + ctx->num_reg, registers, n * sizeof(pcilib_register_description_t));
117
    memset(ctx->registers + ctx->num_reg + n, 0, sizeof(pcilib_register_description_t));
303 by Suren A. Chilingaryan
Initial integration of XML support
118
119
    if (ids) {
120
	size_t i;
121
	
122
	for (i = 0; i < n; i++)
123
	    ids[i] = ctx->num_reg + i;
124
    }
125
236 by Suren A. Chilingaryan
Big redign of model structures
126
    ctx->num_reg += n;
310 by Suren A. Chilingaryan
Introduce hashes
127
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
128
    return 0;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
129
}
130
315 by Suren A. Chilingaryan
Support properties of arbitrary type
131
void pcilib_clean_registers(pcilib_t *ctx, pcilib_register_t start) {
310 by Suren A. Chilingaryan
Introduce hashes
132
    pcilib_register_t reg;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
133
    pcilib_register_context_t *reg_ctx, *tmp;
134
135
    if (start) {
136
        HASH_ITER(hh, ctx->reg_hash, reg_ctx, tmp) {
137
            if (reg_ctx->reg >= start) {
138
                HASH_DEL(ctx->reg_hash, reg_ctx);
139
            }
140
        }
141
    } else {
142
        HASH_CLEAR(hh, ctx->reg_hash);
143
    }
144
145
    for (reg = start; reg < ctx->num_reg; reg++) {
310 by Suren A. Chilingaryan
Introduce hashes
146
	if (ctx->register_ctx[reg].views)
147
	    free(ctx->register_ctx[reg].views);
148
    }
149
150
    if (ctx->registers)
315 by Suren A. Chilingaryan
Support properties of arbitrary type
151
        memset(&ctx->registers[start], 0, sizeof(pcilib_register_description_t));
310 by Suren A. Chilingaryan
Introduce hashes
152
153
    if (ctx->register_ctx)
315 by Suren A. Chilingaryan
Support properties of arbitrary type
154
        memset(&ctx->register_ctx[start], 0, (ctx->alloc_reg - start) * sizeof(pcilib_register_context_t));
310 by Suren A. Chilingaryan
Introduce hashes
155
315 by Suren A. Chilingaryan
Support properties of arbitrary type
156
    ctx->num_reg = start;
310 by Suren A. Chilingaryan
Introduce hashes
157
}
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
158
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
159
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) {
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
160
    int err;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
161
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
162
    size_t i;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
163
    size_t space_size;
236 by Suren A. Chilingaryan
Big redign of model structures
164
165
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
166
    const pcilib_register_protocol_api_description_t *bapi = bctx->api;
167
    const pcilib_register_bank_description_t *b = bctx->bank;
168
116 by Suren A. Chilingaryan
Fix multiword register reads in a proper way
169
    int access = b->access / 8;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
170
171
    assert(bits < 8 * sizeof(pcilib_register_value_t));
236 by Suren A. Chilingaryan
Big redign of model structures
172
173
    if (!bapi->read) {
174
	pcilib_error("Used register protocol does not define a way to read register value");
175
	return PCILIB_ERROR_NOTSUPPORTED;
176
    }
177
324 by Suren A. Chilingaryan
Documentation update
178
    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views * access;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
179
    else space_size = b->size;
180
324 by Suren A. Chilingaryan
Documentation update
181
    if (((addr + n * access) > space_size)||(((addr + n * access) == space_size)&&(bits))) {
102 by Suren A. Chilingaryan
Accept short addresses for IPECamera FPGA registers
182
	if ((b->format)&&(strchr(b->format, 'x')))
324 by Suren A. Chilingaryan
Documentation update
183
	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u %u-bit registers total)", bits?(n+1):n, addr, space_size / access, access * 8);
102 by Suren A. Chilingaryan
Accept short addresses for IPECamera FPGA registers
184
	else 
324 by Suren A. Chilingaryan
Documentation update
185
	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u %u-bit registers total)", bits?(n+1):n, addr, space_size / access, access * 8);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
186
	return PCILIB_ERROR_OUTOFRANGE;
187
    }
188
189
    for (i = 0; i < n; i++) {
236 by Suren A. Chilingaryan
Big redign of model structures
190
	err = bapi->read(ctx, bctx, addr + i * access, buf + i);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
191
	if (err) break;
192
    }
193
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
194
    if ((bits > 0)&&(!err)) {
195
	pcilib_register_value_t val = 0;
236 by Suren A. Chilingaryan
Big redign of model structures
196
	err = bapi->read(ctx, bctx, addr + n * access, &val);
303 by Suren A. Chilingaryan
Initial integration of XML support
197
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
198
	val = (val >> offset)&BIT_MASK(bits);
199
	memcpy(buf + n, &val, sizeof(pcilib_register_value_t));
200
    }
303 by Suren A. Chilingaryan
Initial integration of XML support
201
    
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
202
    return err;
203
}
204
205
int pcilib_read_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
236 by Suren A. Chilingaryan
Big redign of model structures
206
    pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
207
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
208
	if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
209
	else pcilib_error("Register bank should be specified");
210
	return PCILIB_ERROR_INVALID_BANK;
211
    }
212
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
213
    return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, 0, buf);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
214
}
215
216
int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value) {
217
    int err;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
218
    size_t i, n;
219
    pcilib_register_size_t bits;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
220
    pcilib_register_value_t res;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
221
    pcilib_register_bank_t bank;
236 by Suren A. Chilingaryan
Big redign of model structures
222
    const pcilib_register_description_t *r;
223
    const pcilib_register_bank_description_t *b;
224
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
225
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
226
    r = model_info->registers + reg;
227
    
236 by Suren A. Chilingaryan
Big redign of model structures
228
    bank = pcilib_find_register_bank_by_addr(ctx, r->bank);
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
229
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
230
    
231
    b = model_info->banks + bank;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
232
    
233
    n = r->bits / b->access;
234
    bits = r->bits % b->access; 
235
236
    pcilib_register_value_t buf[n + 1];
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
237
    err = pcilib_read_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, buf);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
238
239
    if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) {
240
	pcilib_error("Big-endian byte order support is not implemented");
241
	return PCILIB_ERROR_NOTSUPPORTED;
242
    } else {
243
	res = 0;
244
	if (bits) ++n;
245
	for (i = 0; i < n; i++) {
246
	    res |= buf[i] << (i * b->access);
247
	}
248
    }
249
    
250
    *value = res;
303 by Suren A. Chilingaryan
Initial integration of XML support
251
    
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
252
    return err;
253
}
254
255
256
int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value) {
257
    int reg;
236 by Suren A. Chilingaryan
Big redign of model structures
258
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
259
    reg = pcilib_find_register(ctx, bank, regname);
259 by Suren A. Chilingaryan
Fix segmentation fault if requested register is not found
260
    if (reg == PCILIB_REGISTER_INVALID) {
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
261
	pcilib_error("Register (%s) is not found", regname);
262
	return PCILIB_ERROR_NOTFOUND;
263
    }
236 by Suren A. Chilingaryan
Big redign of model structures
264
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
265
    return pcilib_read_register_by_id(ctx, reg, value);
266
}
267
268
324 by Suren A. Chilingaryan
Documentation update
269
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, const pcilib_register_value_t *buf) {
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
270
    int err;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
271
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
272
    size_t i;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
273
    size_t space_size;
236 by Suren A. Chilingaryan
Big redign of model structures
274
275
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
276
    const pcilib_register_protocol_api_description_t *bapi = bctx->api;
277
    const pcilib_register_bank_description_t *b = bctx->bank;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
278
116 by Suren A. Chilingaryan
Fix multiword register reads in a proper way
279
    int access = b->access / 8;
280
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
281
    assert(bits < 8 * sizeof(pcilib_register_value_t));
282
236 by Suren A. Chilingaryan
Big redign of model structures
283
    if (!bapi->write) {
284
	pcilib_error("Used register protocol does not define a way to write value into the register");
285
	return PCILIB_ERROR_NOTSUPPORTED;
286
    }
287
324 by Suren A. Chilingaryan
Documentation update
288
    if (b->protocol == PCILIB_REGISTER_PROTOCOL_PROPERTY) space_size = ctx->num_views * access;
321 by Suren A. Chilingaryan
Support computed (property-based) registers
289
    else space_size = b->size;
290
324 by Suren A. Chilingaryan
Documentation update
291
    if (((addr + n * access) > space_size)||(((addr + n * access) == space_size)&&(bits))) {
102 by Suren A. Chilingaryan
Accept short addresses for IPECamera FPGA registers
292
	if ((b->format)&&(strchr(b->format, 'x')))
324 by Suren A. Chilingaryan
Documentation update
293
	    pcilib_error("Accessing register (%u regs at addr 0x%x) out of register space (%u %u-bit registers total)", bits?(n+1):n, addr, space_size / access, access * 8);
102 by Suren A. Chilingaryan
Accept short addresses for IPECamera FPGA registers
294
	else 
324 by Suren A. Chilingaryan
Documentation update
295
	    pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u %u-bit registers total)", bits?(n+1):n, addr, space_size / access, access * 8);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
296
	return PCILIB_ERROR_OUTOFRANGE;
297
    }
298
299
    for (i = 0; i < n; i++) {
236 by Suren A. Chilingaryan
Big redign of model structures
300
	err = bapi->write(ctx, bctx, addr + i * access, buf[i]);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
301
	if (err) break;
302
    }
303
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
304
    if ((bits > 0)&&(!err)) {
305
	pcilib_register_value_t val = (buf[n]&BIT_MASK(bits))<<offset;
306
	pcilib_register_value_t mask = BIT_MASK(bits)<<offset;
307
308
	if (~mask&rwmask) {
309
	    pcilib_register_value_t rval;
236 by Suren A. Chilingaryan
Big redign of model structures
310
311
	    if (!bapi->read) {
312
		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");
313
		return PCILIB_ERROR_NOTSUPPORTED;
314
	    }
315
316
	    err = bapi->read(ctx, bctx, addr + n * access, &rval); 
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
317
	    if (err) return err;
236 by Suren A. Chilingaryan
Big redign of model structures
318
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
319
	    val |= (rval & rwmask & ~mask);
320
	}
321
	
236 by Suren A. Chilingaryan
Big redign of model structures
322
	err = bapi->write(ctx, bctx, addr + n * access, val);
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
323
    }
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
324
    
325
    return err;
326
}
327
324 by Suren A. Chilingaryan
Documentation update
328
int pcilib_write_register_space(pcilib_t *ctx, const char *bank, pcilib_register_addr_t addr, size_t n, const pcilib_register_value_t *buf) {
236 by Suren A. Chilingaryan
Big redign of model structures
329
    pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
330
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
331
	if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
332
	else pcilib_error("Register bank should be specified");
333
	return PCILIB_ERROR_INVALID_BANK;
334
    }
335
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
336
    return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, 0, 0, buf);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
337
}
338
339
340
int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value) {
341
    int err;
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
342
    size_t i, n;
343
    pcilib_register_size_t bits;
344
    pcilib_register_bank_t bank;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
345
    pcilib_register_value_t res;
236 by Suren A. Chilingaryan
Big redign of model structures
346
    const pcilib_register_description_t *r;
347
    const pcilib_register_bank_description_t *b;
348
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
349
350
    r = model_info->registers + reg;
351
236 by Suren A. Chilingaryan
Big redign of model structures
352
    bank = pcilib_find_register_bank_by_addr(ctx, r->bank);
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
353
    if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK;
354
355
    b = model_info->banks + bank;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
356
    
357
    n = r->bits / b->access;
358
    bits = r->bits % b->access; 
359
360
    pcilib_register_value_t buf[n + 1];
361
    memset(buf, 0, (n + 1) * sizeof(pcilib_register_value_t));
362
    
363
    if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) {
364
	pcilib_error("Big-endian byte order support is not implemented");
365
	return PCILIB_ERROR_NOTSUPPORTED;
366
    } else {
367
	if (b->access == sizeof(pcilib_register_value_t) * 8) {
368
	    buf[0] = value;
369
	} else {
370
	    for (i = 0, res = value; (res > 0)&&(i <= n); ++i) {
371
		buf[i] = res & BIT_MASK(b->access);
372
	        res >>= b->access;
373
	    }
374
	
375
	    if (res) {
376
		pcilib_error("Value %i is too big to fit in the register %s", value, r->name);
377
		return PCILIB_ERROR_OUTOFRANGE;
378
	    }
379
	}
380
    }
381
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
382
    err = pcilib_write_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, r->rwmask, buf);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
383
    return err;
384
}
385
386
int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value) {
387
    int reg;
388
    
389
    reg = pcilib_find_register(ctx, bank, regname);
259 by Suren A. Chilingaryan
Fix segmentation fault if requested register is not found
390
    if (reg == PCILIB_REGISTER_INVALID) {
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
391
	pcilib_error("Register (%s) is not found", regname);
392
	return PCILIB_ERROR_NOTFOUND;
393
    }
394
395
    return pcilib_write_register_by_id(ctx, reg, value);
396
}
318 by Suren A. Chilingaryan
Support reading/writting register views by id
397
398
399
int pcilib_get_register_attr_by_id(pcilib_t *ctx, pcilib_register_t reg, const char *attr, pcilib_value_t *val) {
400
    int err;
401
402
    assert(reg < ctx->num_reg);
403
404
    err = pcilib_get_xml_attr(ctx, ctx->register_ctx[reg].xml, attr, val);
405
/*
406
        // Shall we return from parrent register if not found?
407
    if ((err == PCILIB_ERROR_NOTFOUND)&&(ctx->registers[reg].type == PCILIB_REGISTER_TYPE_BITS)) {
408
        pcilib_register_t parent = pcilib_find_standard_register_by_addr(ctx, ctx->registers[reg].addr);
409
        err = pcilib_get_xml_attr(ctx, ctx->register_ctx[parent].xml, attr, val);
410
    }
411
*/
412
    return err;
413
}
414
415
int pcilib_get_register_attr(pcilib_t *ctx, const char *bank, const char *regname, const char *attr, pcilib_value_t *val) {
416
    pcilib_register_t reg;
417
    
418
    reg = pcilib_find_register(ctx, bank, regname);
419
    if (reg == PCILIB_REGISTER_INVALID) {
420
        pcilib_error("Register (%s) is not found", regname);
421
        return PCILIB_ERROR_NOTFOUND;
422
    }
423
424
    return pcilib_get_register_attr_by_id(ctx, reg, attr, val);
425
}
319 by Suren A. Chilingaryan
Provide register listings in public API
426
427
pcilib_register_info_t *pcilib_get_register_info(pcilib_t *ctx, const char *req_bank_name, const char *req_reg_name, pcilib_list_flags_t flags) {
428
    pcilib_register_t i, from, to, pos = 0;
429
    pcilib_register_info_t *info;
430
    pcilib_register_bank_t bank;
431
    pcilib_register_bank_addr_t bank_addr;
432
    const char *bank_name;
433
434
    info = (pcilib_register_info_t*)malloc((ctx->num_reg + 1) * sizeof(pcilib_register_info_t));
435
    if (!info) return NULL;
436
437
    if (req_bank_name) {
438
        bank = pcilib_find_register_bank_by_name(ctx, req_bank_name);
439
        if (bank == PCILIB_REGISTER_BANK_INVALID) {
440
            pcilib_error("The specified bank (%s) is not found", req_bank_name);
441
            return NULL;
442
        }
443
        bank_addr = ctx->banks[bank].addr;
444
        bank_name = req_bank_name;
445
    } else {
446
        bank_addr = PCILIB_REGISTER_BANK_INVALID;
447
        bank_name = NULL;
448
    }
449
450
    if (req_reg_name) {
451
        pcilib_register_t reg = pcilib_find_register(ctx, req_bank_name, req_reg_name);
452
        if (reg == PCILIB_REGISTER_INVALID) {
453
            pcilib_error("The specified register (%s) is not found", req_reg_name);
454
            return NULL;
455
        }
456
        from = reg;
457
        to = reg + 1;
458
    } else {
459
        from = 0;
460
        to = ctx->num_reg;
461
    }
462
463
    for (i = from; i < to; i++) {
464
        const pcilib_register_value_range_t *range = &ctx->register_ctx[i].range;
465
        const pcilib_register_value_name_t *names = NULL;
466
467
        if (req_bank_name) {
468
            if (ctx->registers[i].bank != bank_addr) continue;
469
        } else {
470
            if (ctx->registers[i].bank != bank_addr) {
471
                bank_addr = ctx->registers[i].bank;
472
                bank = pcilib_find_register_bank_by_addr(ctx, bank_addr);
473
                if (bank == PCILIB_REGISTER_BANK_INVALID) bank_name = NULL;
474
                else bank_name = ctx->banks[bank].name;
475
            }
476
        }
477
478
        if (ctx->registers[i].views) {
479
            int j;
480
            for (j = 0; ctx->registers[i].views[j].view; j++) {
481
                pcilib_view_t view = pcilib_find_view_by_name(ctx, ctx->registers[i].views[j].view);
482
                if ((view != PCILIB_VIEW_INVALID)&&((ctx->views[view]->api == &pcilib_enum_view_xml_api)||(ctx->views[view]->api == &pcilib_enum_view_static_api)))
483
                    names = ((pcilib_enum_view_description_t*)(ctx->views[view]))->names;
484
            }
485
        }
486
487
        if (range->min == range->max) 
488
            range = NULL;
489
490
        info[pos++] = (pcilib_register_info_t){
491
            .id = i,
492
            .name = ctx->registers[i].name,
493
            .description = ctx->registers[i].description,
494
            .bank = bank_name,
495
            .mode = ctx->registers[i].mode,
496
            .defvalue = ctx->registers[i].defvalue,
497
            .range = range,
498
            .values = names
499
        };
500
    }
501
    memset(&info[pos], 0, sizeof(pcilib_register_info_t));
502
    return info;
503
}
504
505
pcilib_register_info_t *pcilib_get_register_list(pcilib_t *ctx, const char *req_bank_name, pcilib_list_flags_t flags) {
506
    return pcilib_get_register_info(ctx, req_bank_name, NULL, flags);
507
}
508
509
void pcilib_free_register_info(pcilib_t *ctx, pcilib_register_info_t *info) {
510
    if (info)
511
        free(info);
512
}