/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
1
#define _POSIX_C_SOURCE 199309L
2
#include <stdio.h>
3
#include <string.h>
4
#include <strings.h>
5
#include <stdlib.h>
6
#include <stdint.h>
7
#include <stdarg.h>
8
#include <fcntl.h>
9
#include <unistd.h>
10
#include <sys/ioctl.h>
11
#include <sys/mman.h>
12
#include <arpa/inet.h>
13
#include <errno.h>
14
#include <assert.h>
15
16
#include "pci.h"
17
18
#include "tools.h"
19
#include "error.h"
20
21
pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) {
22
    int i;
23
    pcilib_register_bank_t res;
24
    unsigned long addr;
25
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
26
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
27
    pcilib_event_description_t *events = model_info->events;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
28
    
29
    for (i = 0; events[i].name; i++) {
30
	if (!strcasecmp(events[i].name, event)) return (1<<i);
31
    }
32
33
    return (pcilib_event_t)-1;
34
}
35
36
37
int pcilib_reset(pcilib_t *ctx) {
38
    pcilib_event_api_description_t *api;
39
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
40
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
41
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
42
    api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
43
    if (!api) {
44
	pcilib_error("Event API is not supported by the selected model");
45
	return PCILIB_ERROR_NOTSUPPORTED;
46
    }
47
    
48
    if (api->reset) 
49
	return api->reset(ctx->event_ctx);
50
	
51
    return 0;
52
}
53
54
int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user) {
55
    pcilib_event_api_description_t *api;
56
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
57
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
58
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
59
    api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
60
    if (!api) {
61
	pcilib_error("Event API is not supported by the selected model");
62
	return PCILIB_ERROR_NOTSUPPORTED;
63
    }
64
65
    if (api->start) 
66
	return api->start(ctx->event_ctx, event_mask, callback, user);
67
68
    return 0;
69
}
70
71
int pcilib_stop(pcilib_t *ctx) {
72
    pcilib_event_api_description_t *api;
73
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
74
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
75
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
76
    api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
77
    if (!api) {
78
	pcilib_error("Event API is not supported by the selected model");
79
	return PCILIB_ERROR_NOTSUPPORTED;
80
    }
81
82
    if (api->stop) 
83
	return api->stop(ctx->event_ctx);
84
85
    return 0;
86
}
87
88
pcilib_event_id_t pcilib_get_next_event(pcilib_t *ctx, pcilib_event_t event_mask, const struct timespec *timeout) {
89
    pcilib_event_api_description_t *api;
90
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
91
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
92
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
93
    api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
94
    if (!api) {
95
	pcilib_error("Event API is not supported by the selected model");
96
	return PCILIB_ERROR_NOTSUPPORTED;
97
    }
98
99
    if (api->next_event) 
100
	return api->next_event(ctx->event_ctx, event_mask, timeout);
101
102
    pcilib_error("Event enumeration is not suppored by API");
103
    return PCILIB_EVENT_ID_INVALID;
104
}
105
106
int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
107
    pcilib_event_api_description_t *api;
108
    
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
109
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
110
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
111
    api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
112
    if (!api) {
113
	pcilib_error("Event API is not supported by the selected model");
114
	return PCILIB_ERROR_NOTSUPPORTED;
115
    }
116
117
    if (api->trigger) 
118
	return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data);
119
120
    pcilib_error("Self triggering is not supported by the selected model");
121
    return PCILIB_ERROR_NOTSUPPORTED;
122
}
123
124
125
void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) {
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
126
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
127
128
    pcilib_event_api_description_t *api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
129
    if (!api) {
130
	pcilib_error("Event API is not supported by the selected model");
131
	return NULL;
132
    }
133
134
    if (api->get_data) 
135
	return api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, size);
136
137
    return NULL;
138
}
139
140
void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) {
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
141
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
142
143
    pcilib_event_api_description_t *api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
144
    if (!api) {
145
	pcilib_error("Event API is not supported by the selected model");
146
	return NULL;
147
    }
148
149
    if (api->get_data) 
150
	return api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, size);
151
152
    return NULL;
153
}
154
155
int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id) {
54 by Suren A. Chilingaryan
Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers
156
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
157
    
158
    pcilib_event_api_description_t *api = model_info->event_api;
47 by Suren A. Chilingaryan
Support FIFO reading/writting, code restructurization, few fixes
159
    if (!api) {
160
	pcilib_error("Event API is not supported by the selected model");
161
	return PCILIB_ERROR_NOTSUPPORTED;
162
    }
163
164
    if (api->return_data) 
165
	return api->return_data(ctx->event_ctx, event_id);
166
167
    return 0;
168
}
169
170
171
typedef struct {
172
    pcilib_t *ctx;
173
    
174
    size_t *size;
175
    void **data;
176
} pcilib_grab_callback_user_data_t;
177
178
static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) {
179
    int err;
180
    void *data;
181
    size_t size;
182
    int allocated = 0;
183
184
    pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser;
185
186
    data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size);
187
    if (!data) {
188
	pcilib_error("Error getting event data");
189
	return PCILIB_ERROR_FAILED;
190
    }
191
    
192
    if (*(user->data)) {
193
	if ((user->size)&&(*(user->size) < size)) {
194
	    pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size);
195
	    return PCILIB_ERROR_MEMORY;
196
	}
197
198
	*(user->size) = size;
199
    } else {
200
	*(user->data) = malloc(size);
201
	if (!*(user->data)) {
202
	    pcilib_error("Memory allocation (%i bytes) for event data is failed");
203
	    return PCILIB_ERROR_MEMORY;
204
	}
205
	if (*(user->size)) *(user->size) = size;
206
	allocated = 1;
207
    }
208
    
209
    memcpy(*(user->data), data, size);
210
    
211
    err = pcilib_return_data(user->ctx, event_id);
212
    if (err) {
213
	if (allocated) {
214
	    free(*(user->data));
215
	    *(user->data) = NULL;
216
	}
217
	pcilib_error("The event data had been overwritten before it was returned, data corruption may occur");
218
	return err;
219
    }
220
    
221
    return 0;
222
}
223
224
int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout) {
225
    int err;
226
    
227
    pcilib_grab_callback_user_data_t user = {ctx, size, data};
228
    
229
    err = pcilib_start(ctx, event_mask, pcilib_grab_callback, &user);
230
    if (!err) {
231
	if (timeout) nanosleep(timeout, NULL);
232
        else err = pcilib_trigger(ctx, event_mask, 0, NULL);
233
    }
234
    pcilib_stop(ctx);
235
    return 0;
236
}