/alps/pcitool

To get this branch, use:
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
}