/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
236 by Suren A. Chilingaryan
Big redign of model structures
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>
14
15
#include "pci.h"
16
17
#include "tools.h"
18
#include "error.h"
19
20
int pcilib_init_register_banks(pcilib_t *ctx) {
21
    int err; 
315 by Suren A. Chilingaryan
Support properties of arbitrary type
22
    size_t start = ctx->num_banks_init;
236 by Suren A. Chilingaryan
Big redign of model structures
23
24
    err = pcilib_map_register_space(ctx);
25
    if (err) return err;
26
27
    for (; ctx->num_banks_init < ctx->num_banks; ctx->num_banks_init++) {
28
	pcilib_register_bank_context_t *bank_ctx;
29
	pcilib_register_protocol_t protocol;
30
	const pcilib_register_protocol_api_description_t *bapi;
31
32
	protocol = pcilib_find_register_protocol_by_addr(ctx, ctx->banks[ctx->num_banks_init].protocol);
33
	if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) {
34
	    const char *name = ctx->banks[ctx->num_banks_init].name;
35
	    if (!name) name = "unnamed";
36
	    pcilib_error("Invalid register protocol address (%u) is specified for bank %i (%s)", ctx->banks[ctx->num_banks_init].protocol, ctx->banks[ctx->num_banks_init].addr, name);
315 by Suren A. Chilingaryan
Support properties of arbitrary type
37
	    pcilib_free_register_banks(ctx, start);
236 by Suren A. Chilingaryan
Big redign of model structures
38
	    return PCILIB_ERROR_INVALID_BANK;
39
	}
40
	
41
	bapi = ctx->protocols[protocol].api;
42
240 by Suren A. Chilingaryan
More structural changes to get ready for stand-alone event engines
43
	if (bapi->init) {
44
	    const char *model = ctx->protocols[protocol].model;
45
	    if (!model) model = ctx->model;
46
47
	    bank_ctx = bapi->init(ctx, ctx->num_banks_init, model, ctx->protocols[protocol].args);
48
	} else
236 by Suren A. Chilingaryan
Big redign of model structures
49
	    bank_ctx = (pcilib_register_bank_context_t*)malloc(sizeof(pcilib_register_bank_context_t));
50
	
315 by Suren A. Chilingaryan
Support properties of arbitrary type
51
	if (!bank_ctx) {
52
	    pcilib_free_register_banks(ctx, start);
236 by Suren A. Chilingaryan
Big redign of model structures
53
	    return PCILIB_ERROR_FAILED;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
54
	}
236 by Suren A. Chilingaryan
Big redign of model structures
55
	
56
	bank_ctx->bank = ctx->banks + ctx->num_banks_init;
57
	bank_ctx->api = bapi;
303 by Suren A. Chilingaryan
Initial integration of XML support
58
	bank_ctx->xml = ctx->xml.bank_nodes[ctx->num_banks_init];
236 by Suren A. Chilingaryan
Big redign of model structures
59
	ctx->bank_ctx[ctx->num_banks_init] = bank_ctx;
60
    }
61
62
    return 0;
63
}
64
315 by Suren A. Chilingaryan
Support properties of arbitrary type
65
void pcilib_free_register_banks(pcilib_t *ctx, pcilib_register_bank_t start) {
236 by Suren A. Chilingaryan
Big redign of model structures
66
    size_t i;
67
315 by Suren A. Chilingaryan
Support properties of arbitrary type
68
    for (i = start; i < ctx->num_banks_init; i++) {
236 by Suren A. Chilingaryan
Big redign of model structures
69
	const pcilib_register_protocol_api_description_t *bapi = ctx->bank_ctx[i]->api;
70
	
71
	if (ctx->bank_ctx[i]) {
72
	    if (bapi->free)
275 by Suren A. Chilingaryan
Integration of software registers
73
		bapi->free(ctx, ctx->bank_ctx[i]);
236 by Suren A. Chilingaryan
Big redign of model structures
74
	    else
75
		free(ctx->bank_ctx[i]);
76
		
77
	    ctx->bank_ctx[i] = NULL;
78
	}
79
    }
80
315 by Suren A. Chilingaryan
Support properties of arbitrary type
81
    ctx->num_banks_init = start;
236 by Suren A. Chilingaryan
Big redign of model structures
82
}
83
303 by Suren A. Chilingaryan
Initial integration of XML support
84
int pcilib_add_register_banks(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_bank_description_t *banks, pcilib_register_bank_t *ids) {
315 by Suren A. Chilingaryan
Support properties of arbitrary type
85
    int err;
303 by Suren A. Chilingaryan
Initial integration of XML support
86
    size_t i;
87
    pcilib_register_bank_t bank;
88
    size_t dyn_banks = ctx->dyn_banks;
89
    size_t num_banks = ctx->num_banks;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
90
    size_t cur_banks = num_banks;
236 by Suren A. Chilingaryan
Big redign of model structures
91
	
92
    if (!n) {
93
	for (n = 0; banks[n].access; n++);
94
    }
95
96
    if ((ctx->num_banks + n + 1) > PCILIB_MAX_REGISTER_BANKS)
97
	return PCILIB_ERROR_TOOBIG;
303 by Suren A. Chilingaryan
Initial integration of XML support
98
99
    for (i = 0; i < n; i++) {
100
	    // Try to find if the bank is already existing...
101
	bank = pcilib_find_register_bank_by_name(ctx, banks[i].name);
102
	if ((bank == PCILIB_REGISTER_BANK_INVALID)&&(banks[i].addr != PCILIB_REGISTER_BANK_DYNAMIC))
103
	    bank = pcilib_find_register_bank_by_addr(ctx, banks[i].addr);
104
105
	if (bank == PCILIB_REGISTER_BANK_INVALID) {
106
	    bank = num_banks++;
107
	} else if (flags&PCILIB_MODEL_MODIFICATION_FLAG_SKIP_EXISTING) {
108
	    if (ids) ids[i] = bank;
109
	    continue;
110
	} else if ((flags&PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE) == 0) {
111
	    if (pcilib_find_register_bank_by_name(ctx, banks[i].name) == PCILIB_REGISTER_BANK_INVALID)
112
		pcilib_error("The bank %s is already existing and override flag is not set", banks[i].name);
113
	    else
114
		pcilib_error("The bank with address 0x%lx is already existing and override flag is not set", banks[i].addr);
315 by Suren A. Chilingaryan
Support properties of arbitrary type
115
	    memset(ctx->banks + ctx->num_banks, 0, sizeof(pcilib_register_bank_description_t));
303 by Suren A. Chilingaryan
Initial integration of XML support
116
	    return PCILIB_ERROR_EXIST;
117
	}
118
	
119
	memcpy(ctx->banks + bank,  banks + i, sizeof(pcilib_register_bank_description_t));
120
	if (ids) ids[i] = bank;
121
	
122
	if (banks[i].addr == PCILIB_REGISTER_BANK_DYNAMIC) {
123
	    ctx->banks[bank].addr = PCILIB_REGISTER_BANK_DYNAMIC + dyn_banks + 1;
124
	    dyn_banks++;
125
	}
126
    }
315 by Suren A. Chilingaryan
Support properties of arbitrary type
127
303 by Suren A. Chilingaryan
Initial integration of XML support
128
    ctx->num_banks = num_banks;
236 by Suren A. Chilingaryan
Big redign of model structures
129
130
	// If banks are already initialized, we need to re-run the initialization code
131
    if (ctx->reg_bar_mapped) {
132
	ctx->reg_bar_mapped = 0;
315 by Suren A. Chilingaryan
Support properties of arbitrary type
133
        err = pcilib_init_register_banks(ctx);
134
        if (err) {
135
            ctx->num_banks = cur_banks;
136
	    memset(ctx->banks + ctx->num_banks, 0, sizeof(pcilib_register_bank_description_t));
137
            return err;
138
        }
236 by Suren A. Chilingaryan
Big redign of model structures
139
    }
315 by Suren A. Chilingaryan
Support properties of arbitrary type
140
141
    ctx->dyn_banks = dyn_banks;
142
236 by Suren A. Chilingaryan
Big redign of model structures
143
    return 0;
144
}
145
303 by Suren A. Chilingaryan
Initial integration of XML support
146
int pcilib_add_register_protocols(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_protocol_description_t *protocols, pcilib_register_protocol_t *ids) {
242 by Suren A. Chilingaryan
Initial support for event engines
147
	// DS: Override existing banks 
148
	
149
    if (!n) {
150
	for (n = 0; protocols[n].api; n++);
151
    }
152
153
    if ((ctx->num_protocols + n + 1) > PCILIB_MAX_REGISTER_PROTOCOLS)
154
	return PCILIB_ERROR_TOOBIG;
155
	
156
    memcpy(ctx->protocols + ctx->num_protocols, protocols, n * sizeof(pcilib_register_protocol_description_t));
157
    ctx->num_protocols += n;
158
159
    return 0;
160
}
161
303 by Suren A. Chilingaryan
Initial integration of XML support
162
int pcilib_add_register_ranges(pcilib_t *ctx, pcilib_model_modification_flags_t flags, size_t n, const pcilib_register_range_t *ranges) {
242 by Suren A. Chilingaryan
Initial support for event engines
163
    if (!n) {
164
	for (n = 0; ranges[n].end; n++);
165
    }
166
167
    if ((ctx->num_ranges + n + 1) > PCILIB_MAX_REGISTER_RANGES)
168
	return PCILIB_ERROR_TOOBIG;
169
	
170
    memcpy(ctx->ranges + ctx->num_ranges, ranges, n * sizeof(pcilib_register_range_t));
171
    ctx->num_ranges += n;
172
173
    return 0;
174
}
175
236 by Suren A. Chilingaryan
Big redign of model structures
176
pcilib_register_bank_t pcilib_find_register_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
177
    pcilib_register_bank_t i;
178
303 by Suren A. Chilingaryan
Initial integration of XML support
179
    for (i = 0; ctx->banks[i].access; i++)
180
	if (ctx->banks[i].addr == bank) return i;
236 by Suren A. Chilingaryan
Big redign of model structures
181
182
    return PCILIB_REGISTER_BANK_INVALID;
183
}
184
185
pcilib_register_bank_t pcilib_find_register_bank_by_name(pcilib_t *ctx, const char *bankname) {
186
    pcilib_register_bank_t i;
187
303 by Suren A. Chilingaryan
Initial integration of XML support
188
    for (i = 0; ctx->banks[i].access; i++)
189
	if (!strcasecmp(ctx->banks[i].name, bankname)) return i;
236 by Suren A. Chilingaryan
Big redign of model structures
190
191
    return PCILIB_REGISTER_BANK_INVALID;
192
}
193
194
pcilib_register_bank_t pcilib_find_register_bank(pcilib_t *ctx, const char *bank) {
195
    pcilib_register_bank_t res;
196
    unsigned long addr;
197
    
198
    if (!bank) {
199
        const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
200
	const pcilib_register_bank_description_t *banks = model_info->banks;
201
	if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0;
202
	return PCILIB_REGISTER_BANK_INVALID;
203
    }
204
    
205
    if (pcilib_isxnumber(bank)&&(sscanf(bank,"%lx", &addr) == 1)) {
206
	res = pcilib_find_register_bank_by_addr(ctx, addr);
207
	if (res != PCILIB_REGISTER_BANK_INVALID) return res;
208
    }
209
    
210
    return pcilib_find_register_bank_by_name(ctx, bank);
211
}
212
213
    // DS: FIXME create hash during map_register space
214
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) {
215
    pcilib_register_t i;
216
    pcilib_register_bank_t bank_id;
217
    pcilib_register_bank_addr_t bank_addr = 0;
310 by Suren A. Chilingaryan
Introduce hashes
218
    pcilib_register_context_t *reg_ctx;
236 by Suren A. Chilingaryan
Big redign of model structures
219
220
    const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
221
    const pcilib_register_description_t *registers =  model_info->registers;
222
    
223
    if (bank) {
224
	bank_id = pcilib_find_register_bank(ctx, bank);
225
	if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
226
	    pcilib_error("Invalid bank (%s) is specified", bank);
227
	    return PCILIB_REGISTER_INVALID;
228
	}
229
	
230
	bank_addr = model_info->banks[bank_id].addr;
310 by Suren A. Chilingaryan
Introduce hashes
231
232
            // ToDo: we can use additionaly per-bank hashes
233
        for (i = 0; registers[i].bits; i++) {
234
	    if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i;
235
        }
236
    } else {
237
        HASH_FIND_STR(ctx->reg_hash, reg, reg_ctx);
238
        if (reg_ctx) return reg_ctx->reg;
239
    }
240
236 by Suren A. Chilingaryan
Big redign of model structures
241
242
    return PCILIB_REGISTER_INVALID;
243
};
244
245
pcilib_register_protocol_t pcilib_find_register_protocol_by_addr(pcilib_t *ctx, pcilib_register_protocol_addr_t protocol) {
246
    pcilib_register_protocol_t i;
247
303 by Suren A. Chilingaryan
Initial integration of XML support
248
    for (i = 0; ctx->protocols[i].api; i++)
249
	if (ctx->protocols[i].addr == protocol) return i;
236 by Suren A. Chilingaryan
Big redign of model structures
250
251
    return PCILIB_REGISTER_PROTOCOL_INVALID;
252
}
253
254
pcilib_register_protocol_t pcilib_find_register_protocol_by_name(pcilib_t *ctx, const char *name) {
255
    pcilib_register_protocol_t i;
256
303 by Suren A. Chilingaryan
Initial integration of XML support
257
    for (i = 0; ctx->protocols[i].api; i++)
258
	if (!strcasecmp(ctx->protocols[i].name, name)) return i;
236 by Suren A. Chilingaryan
Big redign of model structures
259
260
    return PCILIB_REGISTER_PROTOCOL_INVALID;
261
}
262
263
pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const char *protocol) {
264
    pcilib_register_bank_t res;
265
    unsigned long addr;
266
267
    if (pcilib_isxnumber(protocol)&&(sscanf(protocol,"%lx", &addr) == 1)) {
268
	res = pcilib_find_register_protocol_by_addr(ctx, addr);
269
	if (res != PCILIB_REGISTER_BANK_INVALID) return res;
270
    }
271
272
    return pcilib_find_register_protocol_by_name(ctx, protocol);
273
}
318 by Suren A. Chilingaryan
Support reading/writting register views by id
274
332 by Suren A. Chilingaryan
Provide API calls for register and bank address resolution
275
uintptr_t pcilib_resolve_bank_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_bank_t bank) {
276
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[bank];
277
278
    if (!bctx->api->resolve)
279
	return PCILIB_ADDRESS_INVALID;
280
	
281
    return bctx->api->resolve(ctx, bctx, flags, PCILIB_REGISTER_ADDRESS_INVALID);
282
}
283
284
uintptr_t pcilib_resolve_bank_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank) {
285
    pcilib_register_bank_t bank_id = pcilib_find_register_bank(ctx, bank);
286
    if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
287
	if (bank) pcilib_error("Invalid register bank is specified (%s)", bank);
288
	else pcilib_error("Register bank should be specified");
289
	return PCILIB_ADDRESS_INVALID;
290
    }
291
292
    return pcilib_resolve_bank_address_by_id(ctx, flags, bank_id);
293
}
294
295
uintptr_t pcilib_resolve_register_address_by_id(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, pcilib_register_t reg) {
296
    pcilib_register_bank_context_t *bctx = ctx->bank_ctx[ctx->register_ctx[reg].bank];
297
298
    if (!bctx->api->resolve)
299
	return PCILIB_ADDRESS_INVALID;
300
301
    return bctx->api->resolve(ctx, bctx, 0, ctx->registers[reg].addr);
302
}
303
304
uintptr_t pcilib_resolve_register_address(pcilib_t *ctx, pcilib_address_resolution_flags_t flags, const char *bank, const char *regname) {
305
    pcilib_register_t reg = pcilib_find_register(ctx, bank, regname);
306
    if (reg == PCILIB_REGISTER_INVALID) {
307
	pcilib_error("Register (%s) is not found", regname);
308
	return PCILIB_ADDRESS_INVALID;
309
    }
310
311
    return pcilib_resolve_register_address_by_id(ctx, flags, reg);
312
}
313
318 by Suren A. Chilingaryan
Support reading/writting register views by id
314
int pcilib_get_register_bank_attr_by_id(pcilib_t *ctx, pcilib_register_bank_t bank, const char *attr, pcilib_value_t *val) {
315
    assert(bank < ctx->num_banks);
316
317
    return pcilib_get_xml_attr(ctx, ctx->bank_ctx[bank]->xml, attr, val);
318
}
319
320
int pcilib_get_register_bank_attr(pcilib_t *ctx, const char *bankname, const char *attr, pcilib_value_t *val) {
321
    pcilib_register_bank_t bank;
322
323
    bank = pcilib_find_register_bank_by_name(ctx, bankname);
324
    if (bank == PCILIB_REGISTER_BANK_INVALID) {
325
        pcilib_error("Bank (%s) is not found", bankname);
326
        return PCILIB_ERROR_NOTFOUND;
327
    }
328
329
    return pcilib_get_register_bank_attr_by_id(ctx, bank, attr, val);
330
}