bzr branch
http://suren.me/webbzr/alps/pcitool
275
by Suren A. Chilingaryan
Integration of software registers |
1 |
#include <stdio.h> |
2 |
#include <unistd.h> |
|
3 |
#include <stdlib.h> |
|
273.1.1
by zilio nicolas
added soft_reg |
4 |
#include <string.h> |
5 |
#include <sys/file.h> |
|
280
by Suren A. Chilingaryan
Integrate locking subsystem from Nicolas Zilio |
6 |
|
330
by Suren A. Chilingaryan
Support for 64-bit registes |
7 |
|
8 |
#include "tools.h" |
|
273.1.1
by zilio nicolas
added soft_reg |
9 |
#include "model.h" |
10 |
#include "error.h" |
|
11 |
#include "kmem.h" |
|
12 |
#include "pcilib.h" |
|
13 |
#include "pci.h" |
|
330
by Suren A. Chilingaryan
Support for 64-bit registes |
14 |
#include "datacpy.h" |
273.1.1
by zilio nicolas
added soft_reg |
15 |
|
275
by Suren A. Chilingaryan
Integration of software registers |
16 |
typedef struct pcilib_software_register_bank_context_s pcilib_software_register_bank_context_t; |
17 |
||
305.1.5
by zilio nicolas
reviewd old tasks comments for doxygen and update |
18 |
/**
|
19 |
* structure defining the context of software registers
|
|
20 |
*/
|
|
275
by Suren A. Chilingaryan
Integration of software registers |
21 |
struct pcilib_software_register_bank_context_s { |
307
by Suren A. Chilingaryan
Finalyze XML support and provide initial support for views (only descriptions so far) |
22 |
pcilib_register_bank_context_t bank_ctx; /**< the bank context associated with the software registers */ |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
23 |
pcilib_kmem_handle_t *kmem; /**< the kernel memory for software registers */ |
370
by Suren A. Chilingaryan
RPM generation |
24 |
volatile void *addr; /**< the virtual adress of the allocated kernel memory*/ |
275
by Suren A. Chilingaryan
Integration of software registers |
25 |
};
|
26 |
||
27 |
void pcilib_software_registers_close(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx) { |
|
28 |
if (((pcilib_software_register_bank_context_t*)bank_ctx)->kmem) |
|
280
by Suren A. Chilingaryan
Integrate locking subsystem from Nicolas Zilio |
29 |
pcilib_free_kernel_memory(ctx, ((pcilib_software_register_bank_context_t*)bank_ctx)->kmem, PCILIB_KMEM_FLAG_REUSE); |
275
by Suren A. Chilingaryan
Integration of software registers |
30 |
free(bank_ctx); |
31 |
}
|
|
273.1.1
by zilio nicolas
added soft_reg |
32 |
|
275
by Suren A. Chilingaryan
Integration of software registers |
33 |
pcilib_register_bank_context_t* pcilib_software_registers_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) { |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
34 |
int err; |
275
by Suren A. Chilingaryan
Integration of software registers |
35 |
pcilib_software_register_bank_context_t *bank_ctx; |
273.1.4
by zilio nicolas
new version of software_registers |
36 |
pcilib_kmem_handle_t *handle; |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
37 |
pcilib_lock_t *lock; |
275
by Suren A. Chilingaryan
Integration of software registers |
38 |
pcilib_kmem_reuse_state_t reused; |
39 |
||
40 |
const pcilib_register_bank_description_t *bank_desc = ctx->banks + bank; |
|
41 |
||
42 |
if (bank_desc->size > PCILIB_KMEM_PAGE_SIZE) { |
|
43 |
pcilib_error("Currently software register banks are limited to %lu bytes, but %lu requested", PCILIB_KMEM_PAGE_SIZE, bank_desc->size); |
|
44 |
return NULL; |
|
45 |
}
|
|
46 |
||
47 |
bank_ctx = calloc(1, sizeof(pcilib_software_register_bank_context_t)); |
|
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
48 |
if (!bank_ctx) { |
49 |
pcilib_error("Memory allocation for bank context has failed"); |
|
50 |
return NULL; |
|
51 |
}
|
|
52 |
||
305.1.5
by zilio nicolas
reviewd old tasks comments for doxygen and update |
53 |
/*we get a lock to protect the creation of the kernel space for software registers against multiple creations*/
|
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
54 |
lock = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "softreg/%s", bank_desc->name); |
55 |
if (!lock) { |
|
288
by Suren A. Chilingaryan
Minor fix for software registers |
56 |
pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
57 |
pcilib_error("Failed to initialize a lock to protect bank %s with software registers", bank_desc->name); |
58 |
return NULL; |
|
59 |
}
|
|
60 |
||
61 |
err = pcilib_lock(lock); |
|
62 |
if (err) { |
|
63 |
pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, lock); |
|
288
by Suren A. Chilingaryan
Minor fix for software registers |
64 |
pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
65 |
pcilib_error("Error (%i) obtaining lock on bank %s with software registers", err, bank_desc->name); |
66 |
return NULL; |
|
67 |
}
|
|
68 |
||
305.1.5
by zilio nicolas
reviewd old tasks comments for doxygen and update |
69 |
/*creation of the kernel space*/
|
281
by Suren A. Chilingaryan
Use bank addresses as kernel memory subtypes of software registers instead of indexes in array |
70 |
handle = pcilib_alloc_kernel_memory(ctx, PCILIB_KMEM_TYPE_PAGE, 1, PCILIB_KMEM_PAGE_SIZE, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_SOFTWARE_REGISTERS, bank_desc->addr), PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); |
275
by Suren A. Chilingaryan
Integration of software registers |
71 |
if (!handle) { |
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
72 |
pcilib_unlock(lock); |
73 |
pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, lock); |
|
288
by Suren A. Chilingaryan
Minor fix for software registers |
74 |
pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); |
275
by Suren A. Chilingaryan
Integration of software registers |
75 |
pcilib_error("Allocation of kernel memory for software registers has failed"); |
76 |
return NULL; |
|
77 |
}
|
|
78 |
||
79 |
bank_ctx->kmem = handle; |
|
80 |
bank_ctx->addr = pcilib_kmem_get_block_ua(ctx, handle, 0); |
|
81 |
reused = pcilib_kmem_is_reused(ctx, handle); |
|
82 |
||
83 |
if ((reused & PCILIB_KMEM_REUSE_REUSED) == 0) { |
|
84 |
pcilib_register_t i; |
|
85 |
||
86 |
if (reused & PCILIB_KMEM_REUSE_PARTIAL) { |
|
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
87 |
pcilib_unlock(lock); |
88 |
pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, lock); |
|
288
by Suren A. Chilingaryan
Minor fix for software registers |
89 |
pcilib_software_registers_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); |
275
by Suren A. Chilingaryan
Integration of software registers |
90 |
pcilib_error("Inconsistent software registers are found (only part of required buffers is available)"); |
91 |
return NULL; |
|
92 |
}
|
|
305.1.5
by zilio nicolas
reviewd old tasks comments for doxygen and update |
93 |
|
94 |
/* here we fill the software registers with their default value*/
|
|
275
by Suren A. Chilingaryan
Integration of software registers |
95 |
for (i = 0; ctx->model_info.registers[i].name != NULL; i++) { |
96 |
if ((ctx->model_info.registers[i].bank == ctx->banks[bank].addr)&&(ctx->model_info.registers[i].type == PCILIB_REGISTER_STANDARD)) { |
|
280
by Suren A. Chilingaryan
Integrate locking subsystem from Nicolas Zilio |
97 |
*(pcilib_register_value_t*)(bank_ctx->addr + ctx->model_info.registers[i].addr) = ctx->model_info.registers[i].defvalue; |
275
by Suren A. Chilingaryan
Integration of software registers |
98 |
}
|
99 |
}
|
|
100 |
}
|
|
280
by Suren A. Chilingaryan
Integrate locking subsystem from Nicolas Zilio |
101 |
|
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
102 |
pcilib_unlock(lock); |
103 |
pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, lock); |
|
104 |
||
275
by Suren A. Chilingaryan
Integration of software registers |
105 |
return (pcilib_register_bank_context_t*)bank_ctx; |
273.1.1
by zilio nicolas
added soft_reg |
106 |
}
|
107 |
||
332
by Suren A. Chilingaryan
Provide API calls for register and bank address resolution |
108 |
uintptr_t pcilib_software_registers_resolve(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_address_resolution_flags_t flags, pcilib_register_addr_t addr) { |
109 |
if (addr == PCILIB_REGISTER_ADDRESS_INVALID) addr = 0; |
|
110 |
||
111 |
switch (flags&PCILIB_ADDRESS_RESOLUTION_MASK_ADDRESS_TYPE) { |
|
112 |
case 0: |
|
113 |
return (uintptr_t)((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr; |
|
114 |
||
115 |
case PCILIB_ADDRESS_RESOLUTION_FLAG_PHYS_ADDRESS: |
|
116 |
return pcilib_kmem_get_block_pa(ctx, ((pcilib_software_register_bank_context_t*)bank_ctx)->kmem, 0) + addr; |
|
117 |
}
|
|
118 |
||
119 |
return PCILIB_ADDRESS_INVALID; |
|
120 |
}
|
|
121 |
||
122 |
||
275
by Suren A. Chilingaryan
Integration of software registers |
123 |
int pcilib_software_registers_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value){ |
330
by Suren A. Chilingaryan
Support for 64-bit registes |
124 |
const pcilib_register_bank_description_t *b = bank_ctx->bank; |
125 |
int access = b->access / 8; |
|
126 |
||
127 |
pcilib_register_value_t val = 0; |
|
128 |
||
129 |
if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { |
|
130 |
pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); |
|
131 |
return PCILIB_ERROR_INVALID_ADDRESS; |
|
132 |
}
|
|
133 |
||
370
by Suren A. Chilingaryan
RPM generation |
134 |
pcilib_datacpy(&val, (void*)((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr, access, 1, b->raw_endianess); |
330
by Suren A. Chilingaryan
Support for 64-bit registes |
135 |
*value = val; |
136 |
||
137 |
return 0; |
|
273.1.1
by zilio nicolas
added soft_reg |
138 |
}
|
139 |
||
283
by Suren A. Chilingaryan
Protect with locks the initialization of software registers |
140 |
int pcilib_software_registers_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) { |
330
by Suren A. Chilingaryan
Support for 64-bit registes |
141 |
const pcilib_register_bank_description_t *b = bank_ctx->bank; |
142 |
int access = b->access / 8; |
|
143 |
||
144 |
if ((addr + sizeof(pcilib_register_value_t)) > bank_ctx->bank->size) { |
|
145 |
pcilib_error("Trying to access space outside of the define register bank (bank: %s, addr: 0x%lx)", bank_ctx->bank->name, addr); |
|
146 |
return PCILIB_ERROR_INVALID_ADDRESS; |
|
147 |
}
|
|
148 |
||
149 |
// we consider this atomic operation and, therefore, do no locking
|
|
370
by Suren A. Chilingaryan
RPM generation |
150 |
pcilib_datacpy((void*)((pcilib_software_register_bank_context_t*)bank_ctx)->addr + addr, &value, access, 1, b->raw_endianess); |
330
by Suren A. Chilingaryan
Support for 64-bit registes |
151 |
|
152 |
return 0; |
|
273.1.1
by zilio nicolas
added soft_reg |
153 |
}
|