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; |
|
22 |
||
23 |
err = pcilib_map_register_space(ctx); |
|
24 |
if (err) return err; |
|
25 |
||
26 |
for (; ctx->num_banks_init < ctx->num_banks; ctx->num_banks_init++) { |
|
27 |
pcilib_register_bank_context_t *bank_ctx; |
|
28 |
pcilib_register_protocol_t protocol; |
|
29 |
const pcilib_register_protocol_api_description_t *bapi; |
|
30 |
||
31 |
protocol = pcilib_find_register_protocol_by_addr(ctx, ctx->banks[ctx->num_banks_init].protocol); |
|
32 |
if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) { |
|
33 |
const char *name = ctx->banks[ctx->num_banks_init].name; |
|
34 |
if (!name) name = "unnamed"; |
|
35 |
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); |
|
36 |
return PCILIB_ERROR_INVALID_BANK; |
|
37 |
}
|
|
38 |
||
39 |
bapi = ctx->protocols[protocol].api; |
|
40 |
||
41 |
if (bapi->init) |
|
42 |
bank_ctx = bapi->init(ctx, ctx->num_banks_init, ctx->protocols[protocol].model, ctx->protocols[protocol].args); |
|
43 |
else
|
|
44 |
bank_ctx = (pcilib_register_bank_context_t*)malloc(sizeof(pcilib_register_bank_context_t)); |
|
45 |
||
46 |
if (!bank_ctx) |
|
47 |
return PCILIB_ERROR_FAILED; |
|
48 |
||
49 |
bank_ctx->bank = ctx->banks + ctx->num_banks_init; |
|
50 |
bank_ctx->api = bapi; |
|
51 |
ctx->bank_ctx[ctx->num_banks_init] = bank_ctx; |
|
52 |
}
|
|
53 |
||
54 |
return 0; |
|
55 |
}
|
|
56 |
||
57 |
void pcilib_free_register_banks(pcilib_t *ctx) { |
|
58 |
size_t i; |
|
59 |
||
60 |
for (i = 0; i < ctx->num_banks_init; i++) { |
|
61 |
const pcilib_register_protocol_api_description_t *bapi = ctx->bank_ctx[i]->api; |
|
62 |
||
63 |
if (ctx->bank_ctx[i]) { |
|
64 |
if (bapi->free) |
|
65 |
bapi->free(ctx->bank_ctx[i]); |
|
66 |
else
|
|
67 |
free(ctx->bank_ctx[i]); |
|
68 |
||
69 |
ctx->bank_ctx[i] = NULL; |
|
70 |
}
|
|
71 |
}
|
|
72 |
||
73 |
ctx->num_banks_init = 0; |
|
74 |
}
|
|
75 |
||
76 |
||
77 |
int pcilib_add_register_banks(pcilib_t *ctx, size_t n, const pcilib_register_bank_description_t *banks) { |
|
78 |
// DS: What we are doing if bank exists?
|
|
79 |
||
80 |
if (!n) { |
|
81 |
for (n = 0; banks[n].access; n++); |
|
82 |
}
|
|
83 |
||
84 |
if ((ctx->num_banks + n + 1) > PCILIB_MAX_REGISTER_BANKS) |
|
85 |
return PCILIB_ERROR_TOOBIG; |
|
86 |
||
87 |
memset(ctx->banks + ctx->num_banks + n, 0, sizeof(pcilib_register_bank_description_t)); |
|
88 |
memcpy(ctx->banks + ctx->num_banks, banks, n * sizeof(pcilib_register_bank_description_t)); |
|
89 |
ctx->num_banks += n; |
|
90 |
||
91 |
// If banks are already initialized, we need to re-run the initialization code
|
|
92 |
// DS: Locking is currently missing
|
|
93 |
if (ctx->reg_bar_mapped) { |
|
94 |
ctx->reg_bar_mapped = 0; |
|
95 |
return pcilib_init_register_banks(ctx); |
|
96 |
}
|
|
97 |
||
98 |
return 0; |
|
99 |
}
|
|
100 |
||
101 |
pcilib_register_bank_t pcilib_find_register_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) { |
|
102 |
pcilib_register_bank_t i; |
|
103 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
104 |
const pcilib_register_bank_description_t *banks = model_info->banks; |
|
105 |
||
106 |
for (i = 0; banks[i].access; i++) |
|
107 |
if (banks[i].addr == bank) return i; |
|
108 |
||
109 |
return PCILIB_REGISTER_BANK_INVALID; |
|
110 |
}
|
|
111 |
||
112 |
pcilib_register_bank_t pcilib_find_register_bank_by_name(pcilib_t *ctx, const char *bankname) { |
|
113 |
pcilib_register_bank_t i; |
|
114 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
115 |
const pcilib_register_bank_description_t *banks = model_info->banks; |
|
116 |
||
117 |
for (i = 0; banks[i].access; i++) |
|
118 |
if (!strcasecmp(banks[i].name, bankname)) return i; |
|
119 |
||
120 |
return PCILIB_REGISTER_BANK_INVALID; |
|
121 |
}
|
|
122 |
||
123 |
pcilib_register_bank_t pcilib_find_register_bank(pcilib_t *ctx, const char *bank) { |
|
124 |
pcilib_register_bank_t res; |
|
125 |
unsigned long addr; |
|
126 |
||
127 |
if (!bank) { |
|
128 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
129 |
const pcilib_register_bank_description_t *banks = model_info->banks; |
|
130 |
if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0; |
|
131 |
return PCILIB_REGISTER_BANK_INVALID; |
|
132 |
}
|
|
133 |
||
134 |
if (pcilib_isxnumber(bank)&&(sscanf(bank,"%lx", &addr) == 1)) { |
|
135 |
res = pcilib_find_register_bank_by_addr(ctx, addr); |
|
136 |
if (res != PCILIB_REGISTER_BANK_INVALID) return res; |
|
137 |
}
|
|
138 |
||
139 |
return pcilib_find_register_bank_by_name(ctx, bank); |
|
140 |
}
|
|
141 |
||
142 |
// DS: FIXME create hash during map_register space
|
|
143 |
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) { |
|
144 |
pcilib_register_t i; |
|
145 |
pcilib_register_bank_t bank_id; |
|
146 |
pcilib_register_bank_addr_t bank_addr = 0; |
|
147 |
||
148 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
149 |
const pcilib_register_description_t *registers = model_info->registers; |
|
150 |
||
151 |
if (bank) { |
|
152 |
bank_id = pcilib_find_register_bank(ctx, bank); |
|
153 |
if (bank_id == PCILIB_REGISTER_BANK_INVALID) { |
|
154 |
pcilib_error("Invalid bank (%s) is specified", bank); |
|
155 |
return PCILIB_REGISTER_INVALID; |
|
156 |
}
|
|
157 |
||
158 |
bank_addr = model_info->banks[bank_id].addr; |
|
159 |
}
|
|
160 |
||
161 |
for (i = 0; registers[i].bits; i++) { |
|
162 |
if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; |
|
163 |
}
|
|
164 |
||
165 |
return PCILIB_REGISTER_INVALID; |
|
166 |
};
|
|
167 |
||
168 |
||
169 |
pcilib_register_protocol_t pcilib_find_register_protocol_by_addr(pcilib_t *ctx, pcilib_register_protocol_addr_t protocol) { |
|
170 |
pcilib_register_protocol_t i; |
|
171 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
172 |
const pcilib_register_protocol_description_t *protocols = model_info->protocols; |
|
173 |
||
174 |
for (i = 0; protocols[i].api; i++) |
|
175 |
if (protocols[i].addr == protocol) return i; |
|
176 |
||
177 |
return PCILIB_REGISTER_PROTOCOL_INVALID; |
|
178 |
}
|
|
179 |
||
180 |
pcilib_register_protocol_t pcilib_find_register_protocol_by_name(pcilib_t *ctx, const char *name) { |
|
181 |
pcilib_register_protocol_t i; |
|
182 |
const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); |
|
183 |
const pcilib_register_protocol_description_t *protocols = model_info->protocols; |
|
184 |
||
185 |
for (i = 0; protocols[i].api; i++) |
|
186 |
if (!strcasecmp(protocols[i].name, name)) return i; |
|
187 |
||
188 |
return PCILIB_REGISTER_PROTOCOL_INVALID; |
|
189 |
}
|
|
190 |
||
191 |
pcilib_register_protocol_t pcilib_find_register_protocol(pcilib_t *ctx, const char *protocol) { |
|
192 |
pcilib_register_bank_t res; |
|
193 |
unsigned long addr; |
|
194 |
||
195 |
if (pcilib_isxnumber(protocol)&&(sscanf(protocol,"%lx", &addr) == 1)) { |
|
196 |
res = pcilib_find_register_protocol_by_addr(ctx, addr); |
|
197 |
if (res != PCILIB_REGISTER_BANK_INVALID) return res; |
|
198 |
}
|
|
199 |
||
200 |
return pcilib_find_register_protocol_by_name(ctx, protocol); |
|
201 |
}
|