34
static void (*Error)(const char *msg, ...) = pcilib_print_error;
36
int pcilib_open(const char *device) {
37
int handle = open(device, O_RDWR);
41
void pcilib_close(int handle) {
54
void (*pcilib_error)(const char *msg, ...) = pcilib_print_error;
55
void (*pcilib_warning)(const char *msg, ...) = pcilib_print_error;
45
57
int pcilib_set_error_handler(void (*err)(const char *msg, ...)) {
49
const pci_board_info *pcilib_get_board_info(int handle) {
61
pcilib_t *pcilib_open(const char *device, pcilib_model_t model) {
62
pcilib_t *ctx = malloc(sizeof(pcilib_t));
65
ctx->handle = open(device, O_RDWR);
66
ctx->page_mask = (uintptr_t)-1;
68
ctx->reg_space = NULL;
74
const pci_board_info *pcilib_get_board_info(pcilib_t *ctx) {
53
ret = ioctl( handle, PCIDRIVER_IOC_PCI_INFO, &board_info );
54
if (ret) Error("PCIDRIVER_IOC_PCI_INFO ioctl have failed");
77
if (ctx->page_mask == (uintptr_t)-1) {
78
ret = ioctl( ctx->handle, PCIDRIVER_IOC_PCI_INFO, &ctx->board_info );
79
if (ret) pcilib_error("PCIDRIVER_IOC_PCI_INFO ioctl have failed");
56
page_mask = get_page_mask();
81
ctx->page_mask = pcilib_get_page_mask();
84
return &ctx->board_info;
63
pcilib_model_t pcilib_detect_model(int handle) {
88
pcilib_model_t pcilib_get_model(pcilib_t *ctx) {
89
if (ctx->model == PCILIB_MODEL_DETECT) {
64
90
unsigned short vendor_id;
65
91
unsigned short device_id;
67
pcilib_get_board_info(handle);
93
const pci_board_info *board_info = pcilib_get_board_info(ctx);
69
if ((board_info.vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info.device_id == PCIE_IPECAMERA_DEVICE_ID)) return PCILIB_MODEL_IPECAMERA;
70
return PCILIB_MODEL_PCI;
95
if ((board_info->vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info->device_id == PCIE_IPECAMERA_DEVICE_ID))
96
ctx->model = PCILIB_MODEL_IPECAMERA;
98
ctx->model = PCILIB_MODEL_PCI;
73
static int pcilib_detect_bar(int handle, unsigned long addr, int size) {
104
static int pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) {
76
pcilib_get_board_info(handle);
107
const pci_board_info *board_info = pcilib_get_board_info(ctx);
78
109
for (i = 0; i < PCILIB_MAX_BANKS; i++) {
79
if ((addr >= board_info.bar_start[i])&&((board_info.bar_start[i] + board_info.bar_length[i]) >= (addr + size))) return i;
110
if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i;
85
static void *pcilib_detect_address(int handle, int *bar, unsigned long *addr, int size) {
87
*bar = pcilib_detect_bar(handle, *addr, size);
88
if (*bar < 0) Error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
116
static void pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size) {
117
const pci_board_info *board_info = pcilib_get_board_info(ctx);
119
if (*bar == PCILIB_BAR_DETECT) {
120
*bar = pcilib_detect_bar(ctx, *addr, size);
121
if (*bar < 0) pcilib_error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
90
pcilib_get_board_info(handle);
92
if ((*addr < board_info.bar_start[*bar])||((board_info.bar_start[*bar] + board_info.bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
93
if ((board_info.bar_length[*bar]) >= (((uintptr_t)*addr) + size))
94
*addr += board_info.bar_start[*bar];
123
if ((*addr < board_info->bar_start[*bar])||((board_info->bar_start[*bar] + board_info->bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
124
if ((board_info->bar_length[*bar]) >= (((uintptr_t)*addr) + size))
125
*addr += board_info->bar_start[*bar];
96
Error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info.bar_start[*bar], board_info.bar_length[*bar]);
127
pcilib_error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]);
100
*addr -= board_info.bar_start[*bar];
101
*addr += board_info.bar_start[*bar] & page_mask;
131
*addr -= board_info->bar_start[*bar];
132
*addr += board_info->bar_start[*bar] & ctx->page_mask;
109
void *pcilib_map_bar(int handle, int bar) {
135
void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) {
113
pcilib_get_board_info(handle);
139
const pci_board_info *board_info = pcilib_get_board_info(ctx);
115
ret = ioctl( handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
116
if (ret) Error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
118
ret = ioctl( handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
119
if (ret) Error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
122
file_io_handle = open("/root/drivers/pciDriver/data", O_RDWR);
123
res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, file_io_handle, 0 );
141
ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
142
if (ret) pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
144
ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
145
if (ret) pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
147
#ifdef PCILIB_FILE_IO
148
file_io_handle = open("/root/data", O_RDWR);
149
res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->file_io_handle, 0 );
125
res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, handle, 0 );
151
res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 );
127
if ((!res)||(res == MAP_FAILED)) Error("Failed to mmap data bank %i", bar);
153
if ((!res)||(res == MAP_FAILED)) pcilib_error("Failed to mmap data bank %i", bar);
133
void pcilib_unmap_bar(int handle, int bar, void *data) {
134
munmap(data, board_info.bar_length[bar]);
136
close(file_io_handle);
159
void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) {
160
const pci_board_info *board_info = pcilib_get_board_info(ctx);
162
munmap(data, board_info->bar_length[bar]);
163
#ifdef PCILIB_FILE_IO
164
close(ctx->file_io_handle);
140
int pcilib_read(void *buf, int handle, int bar, unsigned long addr, int size) {
168
int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
143
171
unsigned int offset;
144
172
char local_buf[size];
148
pcilib_detect_address(handle, &bar, &addr, size);
149
data = pcilib_map_bar(handle, bar);
175
pcilib_detect_address(ctx, &bar, &addr, size);
176
data = pcilib_map_bar(ctx, bar);
152
179
for (i = 0; i < size/4; i++) {
157
184
pcilib_memcpy(buf, data + addr, size);
159
pcilib_unmap_bar(handle, bar, data);
186
pcilib_unmap_bar(ctx, bar, data);
162
int pcilib_write(void *buf, int handle, int bar, unsigned long addr, int size) {
189
int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
165
192
unsigned int offset;
166
193
char local_buf[size];
169
pcilib_detect_address(handle, &bar, &addr, size);
170
data = pcilib_map_bar(handle, bar);
196
pcilib_detect_address(ctx, &bar, &addr, size);
197
data = pcilib_map_bar(ctx, bar);
172
199
pcilib_memcpy(data + addr, buf, size);
174
pcilib_unmap_bar(handle, bar, data);
201
pcilib_unmap_bar(ctx, bar, data);
178
int pcilib_find_register(pcilib_model_t model, const char *reg) {
181
pcilib_register_t *registers = pcilib_model_description[model].registers;
183
for (i = 0; registers[i].size; i++) {
205
// FIXME create hash during map_register space
206
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg) {
209
pcilib_model_t model = pcilib_get_model(ctx);
211
pcilib_register_description_t *registers = pcilib_model[model].registers;
213
for (i = 0; registers[i].bits; i++) {
184
214
if (!strcasecmp(registers[i].name, reg)) return i;
220
static pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
221
pcilib_register_bank_t i;
222
pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
224
for (i = 0; banks[i].access; i++)
225
if (banks[i].addr == bank) return i;
231
static int pcilib_map_register_space(pcilib_t *ctx) {
232
if (!ctx->reg_space) {
233
pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
235
if ((banks)&&(banks[0].access)) {
238
uintptr_t addr = banks[0].read_addr;
239
pcilib_bar_t bar = PCILIB_BAR_DETECT;
241
pcilib_detect_address(ctx, &bar, &addr, 1);
242
reg_space = pcilib_map_bar(ctx, bar);
245
pcilib_memcpy(&buf, reg_space, 8);
249
ctx->reg_space = reg_space;
262
static void pcilib_unmap_register_space(pcilib_t *ctx) {
263
if (ctx->reg_space) {
264
pcilib_unmap_bar(ctx, ctx->reg_bar, ctx->reg_space);
265
ctx->reg_space = NULL;
269
char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {
270
size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];
271
if (offset < ctx->board_info.bar_length[ctx->reg_bar]) {
272
return ctx->reg_space + offset + (ctx->board_info.bar_start[ctx->reg_bar] & ctx->page_mask);
278
void pcilib_close(pcilib_t *ctx) {
280
if (ctx->reg_space) pcilib_unmap_register_space(ctx);
289
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) {
294
pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
296
assert(bits < 8 * sizeof(pcilib_register_value_t));
298
err = pcilib_map_register_space(ctx);
300
pcilib_error("Failed to map the register space");
304
//n += bits / b->access;
307
for (i = 0; i < n; i++) {
308
err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, b->access, buf + i);
312
if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, bits, buf + n);
317
int pcilib_read_register_space(pcilib_t *ctx, pcilib_register_bank_addr_t bank_addr, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
318
pcilib_register_bank_t bank = pcilib_find_bank(ctx, bank_addr);
319
return pcilib_read_register_space_internal(ctx, bank, addr, n, 0, buf);
322
int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value) {
325
pcilib_register_value_t res;
326
pcilib_register_description_t *r;
327
pcilib_register_bank_description_t *b;
329
r = pcilib_model[ctx->model].registers + reg;
330
b = pcilib_model[ctx->model].banks + r->bank;
332
n = r->bits / b->access;
333
bits = r->bits % b->access;
335
pcilib_register_value_t buf[n + 1];
336
err = pcilib_read_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
339
pcilib_error("Big-endian byte order support is not implemented");
340
return PCILIB_ERROR_NOTSUPPORTED;
344
for (i = 0; i < n; i++) {
345
res |= buf[i] << (i * b->access);
355
int pcilib_read_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t *value) {
359
reg = pcilib_find_register(ctx, regname);
361
pcilib_error("Register (%s) is not found", regname);
362
return PCILIB_ERROR_NOTFOUND;
365
return pcilib_read_register_by_id(ctx, reg, value);
367
// registers[reg].bank
368
// printf("%li %li", sizeof(pcilib_model[ctx->model].banks), sizeof(pcilib_register_bank_description_t));
372
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) {
377
pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
379
assert(bits < 8 * sizeof(pcilib_register_value_t));
381
err = pcilib_map_register_space(ctx);
383
pcilib_error("Failed to map the register space");
387
//n += bits / b->access;
390
for (i = 0; i < n; i++) {
391
err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, b->access, buf[i]);
395
if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, bits, buf[n]);
400
int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value) {
403
pcilib_register_value_t res;
404
pcilib_register_description_t *r;
405
pcilib_register_bank_description_t *b;
407
r = pcilib_model[ctx->model].registers + reg;
408
b = pcilib_model[ctx->model].banks + r->bank;
410
n = r->bits / b->access;
411
bits = r->bits % b->access;
413
pcilib_register_value_t buf[n + 1];
414
memset(buf, 0, (n + 1) * sizeof(pcilib_register_value_t));
417
pcilib_error("Big-endian byte order support is not implemented");
418
return PCILIB_ERROR_NOTSUPPORTED;
420
for (i = 0, res = value; (res > 0)&&(i <= n); ++i) {
421
buf[i] = res & BIT_MASK(b->access);
426
pcilib_error("Value %i is to big to fit in the register %s", value, r->name);
427
return PCILIB_ERROR_OUTOFRANGE;
431
err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
435
int pcilib_write_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t value) {
439
reg = pcilib_find_register(ctx, regname);
440
if (reg < 0) pcilib_error("Register (%s) is not found", regname);
442
return pcilib_write_register_by_id(ctx, reg, value);