/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; 
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
}