Line data Source code
1 : #include <sys/types.h>
2 : #include <sys/stat.h>
3 : #include <algorithm>
4 : #include <fcntl.h>
5 : #include <cstdio>
6 : #include <cstdlib>
7 : #include <unistd.h>
8 : #include <errno.h>
9 : #include <string.h>
10 : #include <limits.h>
11 :
12 : #include "block.h"
13 : #include "felix-star/client.h"
14 : #include "felix/felix_fid.h"
15 :
16 : extern "C" {
17 : #include "flx_api.h"
18 : #include "cmem_buffer.h"
19 : #include "log.h"
20 : #include "fifo.h"
21 : }
22 :
23 39 : void flx_init_cmem_buffer(struct cmem_buffer* buf, size_t size, char* cmem_name) {
24 39 : if (buf->vmem) {
25 37 : vmem_buffer_init(buf, size);
26 : } else {
27 2 : cmem_buffer_init(buf, size, cmem_name);
28 : }
29 39 : }
30 :
31 39 : void flx_close_cmem_buffer(struct cmem_buffer* buf) {
32 39 : if (buf->vmem) {
33 37 : vmem_buffer_close(buf);
34 : } else {
35 2 : cmem_buffer_close(buf);
36 : }
37 39 : }
38 :
39 : int
40 39 : flx_init_card(struct flx* flx, struct config* cfg) {
41 39 : LOG_INFO("> flx_init_card(toflx)");
42 39 : flx->device = cfg->device;
43 39 : flx->flxcard = NULL; // card is ignored, it is used in tohost and toflx
44 39 : flx->co = cfg->co;
45 39 : flx->vid = cfg->vid;
46 39 : flx->did = cfg->did;
47 39 : flx->cid = cfg->cid;
48 :
49 39 : flx->mode = FLX_MODE_GBT;
50 39 : flx->no_of_channels = 12;
51 39 : flx->regmap_version = cfg->regmap;
52 39 : u_long major = (flx->regmap_version & 0xFF00) >> 8;
53 39 : u_long minor = (flx->regmap_version & 0x00FF) >> 0;
54 39 : LOG_INFO(" regmap version %lu.%lu", major, minor);
55 :
56 : // elinks
57 39 : flx->num_elinks = cfg->num_elinks;
58 39 : flx->elinks = cfg->elinks;
59 :
60 39 : flx->fd = is_fifo(cfg->file) ? open_fifo(cfg->file) : open_file(cfg->file);
61 :
62 39 : flx->raw = cfg->raw;
63 66 : LOG_INFO("Output in %s file %s", cfg->raw ? "raw" : "json", cfg->file);
64 :
65 39 : return 0;
66 : }
67 :
68 : void
69 39 : flx_close_card(struct flx* flx)
70 : {
71 39 : LOG_INFO("> flx_close_card()");
72 39 : close(flx->fd);
73 39 : }
74 :
75 37 : int flx_get_toflx_dmaid(struct config* cfg){
76 37 : return cfg->dmaid;
77 : }
78 :
79 :
80 : void
81 0 : flx_start_circular_dma(struct flx* flx, struct cmem_buffer* buf, unsigned dmaid)
82 : {
83 0 : LOG_INFO("> flx_start_circular_dma(dmaid=%d): NOT TO BE USED in toflx", dmaid);
84 0 : exit(1);
85 : // flx->dmaid = dmaid;
86 :
87 : // // flx->flxcard->dma_stop(dmaid);
88 : // // flx->flxcard->dma_to_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND);
89 :
90 : // buf->pstart = buf->paddr;
91 : // buf->pend = buf->pstart + buf->size;
92 : // buf->pc_ptr = buf->pstart; // flx->flxcard->dma_get_read_ptr(dmaid);
93 :
94 : // flx->fw_ptr = buf->pstart;
95 :
96 : // LOG_INFO(" cmem buffer [0x%x,0x%x] %lu Blocks", buf->pstart, buf->pend, buf->size/1024);
97 : // LOG_INFO(" cmem virtual address 0x%x", buf->vaddr);
98 : // LOG_INFO(" fw_ptr 0x%x", flx->fw_ptr);
99 : // LOG_INFO(" pc_ptr 0x%x", buf->pc_ptr);
100 : }
101 :
102 : void
103 0 : flx_wait_data_available(struct flx* flx, struct cmem_buffer* buf)
104 : {
105 0 : LOG_ERR("< flx_wait_data_available() NOT IMPLEMENTED\n");
106 : // flx->flxcard->irq_wait(IRQ_DATA_AVAILABLE);
107 0 : exit(1);
108 : }
109 :
110 : void
111 0 : flx_cancel_irqs(struct flx* flx)
112 : {
113 0 : LOG_INFO("< flx_cancel_irqs(), ignored\n");
114 0 : }
115 :
116 : size_t
117 0 : flx_bytes_available(struct flx* flx, struct cmem_buffer* buf)
118 : {
119 0 : LOG_ERR("< flx_bytes_available() NOT IMPLEMENTED\n");
120 0 : return 0;
121 : }
122 :
123 : int
124 0 : flx_dma_cmp_even_bits(struct flx* flx)
125 : {
126 0 : LOG_ERR("< flx_check_dma_cmp_even_bits() NOT IMPLEMENTED\n");
127 0 : return 0;
128 : }
129 :
130 : void
131 0 : flx_read_and_update_fw_ptr(struct flx* flx, struct cmem_buffer* buf)
132 : {
133 0 : LOG_ERR("< flx_read_and_update_fw_ptr() NOT IMPLEMENTED\n");
134 0 : }
135 :
136 : size_t
137 0 : flx_bytes_available_to_read(struct flx* flx, struct cmem_buffer* buf)
138 : {
139 0 : LOG_ERR("< flx_bytes_available_to_read() NOT IMPLEMENTED\n");
140 0 : return 0;
141 : }
142 :
143 : void*
144 0 : flx_get_write_ptr(struct flx* flx, struct cmem_buffer* buf)
145 : {
146 0 : LOG_ERR("< flx_get_write_ptr() NOT IMPLEMENTED\n");
147 0 : return nullptr;
148 : }
149 :
150 : void*
151 0 : flx_get_read_ptr(struct flx* flx, struct cmem_buffer* buf)
152 : {
153 0 : LOG_ERR("< flx_get_read_ptr() NOT IMPLEMENTED\n");
154 0 : return nullptr;
155 : }
156 :
157 : void
158 0 : flx_set_read_ptr(struct flx* flx, struct cmem_buffer* buf, void* ptr)
159 : {
160 0 : LOG_ERR("< flx_set_read_ptr() NOT IMPLEMENTED\n");
161 0 : }
162 :
163 : void
164 0 : flx_advance_read_ptr(struct flx* flx, struct cmem_buffer* buf, size_t bytes)
165 : {
166 0 : LOG_ERR("< flx_advance_read_ptr() NOT IMPLEMENTED\n");
167 0 : }
168 :
169 673 : int flx_get_regmap_version(struct flx* flx) {
170 : // 4.10 formatted as 0x040A
171 673 : return flx->regmap_version;
172 : }
173 :
174 : int
175 0 : flx_get_mode(struct flx* flx)
176 : {
177 0 : LOG_INFO("< flx_get_mode() %d", flx->mode);
178 0 : return flx->mode;
179 : }
180 :
181 0 : int flx_get_number_of_channels(struct flx* flx)
182 : {
183 0 : LOG_INFO("< flx_get_number_of_channels() %d", flx->no_of_channels);
184 0 : return flx->no_of_channels;
185 : }
186 :
187 0 : int flx_get_wide_mode(struct flx* flx)
188 : {
189 0 : LOG_INFO("< flx_get_wide_mode() %d", 0);
190 0 : return 0;
191 : }
192 :
193 0 : uint64_t flx_get_blocksize(struct flx* flx)
194 : {
195 0 : LOG_ERR("> flx_get_blocksize NOT IMPLEMENTED");
196 0 : return 0;
197 : }
198 :
199 0 : int flx_get_trailer_size(struct flx* flx)
200 : {
201 0 : LOG_ERR("> flx_get_trailer_size NOT IMPLEMENTED");
202 0 : return 0;
203 : }
204 :
205 0 : int flx_is_enabled(struct flx* flx, u_int channel, u_int egroup, u_int epath, u_int is_to_flx)
206 : {
207 0 : LOG_INFO("< flx_is_enabled() %d", 1);
208 0 : return 1;
209 : }
210 :
211 0 : int flx_has_stream_id(struct flx* flx, u_int channel, u_int egroup, u_int epath)
212 : {
213 0 : LOG_INFO("< flx_has_stream_id() %d", 1);
214 0 : return 1;
215 : }
216 :
217 162 : void flx_dma_from_host_rm4(struct flx* flx, struct cmem_buffer* dma_buffer, u_long buffer, size_t size)
218 : {
219 162 : LOG_INFO("> flx_dma_from_host_rm4(0x%lx, %d)", buffer, size);
220 162 : LOG_INFO("> cmem paddr 0x%lx vaddr 0x%lx", dma_buffer->paddr, dma_buffer->vaddr);
221 :
222 162 : if (size > 8192) {
223 1 : LOG_ERR("Size %d larger than buffer 8192, output discarded");
224 152 : return;
225 : }
226 :
227 161 : uint8_t data[8192];
228 161 : uint16_t data_size = 0;
229 161 : uint64_t offset = buffer - dma_buffer->paddr;
230 161 : uint8_t *ptr = (uint8_t*)(dma_buffer->vaddr + offset);
231 :
232 161 : if (flx->raw) {
233 150 : int result = write(flx->fd, ptr, size);
234 150 : if (result < 0) {
235 0 : LOG_ERR("errno=%d str=%s", errno, strerror(errno));
236 0 : exit(1);
237 : }
238 150 : fsync(flx->fd);
239 : }
240 :
241 : // decode
242 : uint8_t last = 0;
243 : uint16_t elink = 0;
244 326 : while(!last) {
245 165 : uint16_t hdr = (*(ptr + 31) << 8) | (*(ptr + 30));
246 165 : uint16_t part_size = hdr & 0x001E;
247 165 : elink = ((hdr & 0xFFE0) >> 5);
248 165 : last = hdr & 0x0001;
249 : // printf("Hdr 0x%x\n", hdr);
250 : // printf("elink 0x%x\n", elink);
251 : // printf("size %d\n", part_size);
252 : // printf("last %d\n", last);
253 :
254 : // copy bytes in inverted mode
255 965 : for (uint16_t i = 0; i < part_size; i++) {
256 800 : data[data_size] = *(ptr + 29 - i);
257 800 : data_size++;
258 : }
259 :
260 165 : ptr += 32;
261 : }
262 :
263 161 : if (flx->raw) {
264 : return;
265 : }
266 :
267 : // add zero so that it writes as string
268 11 : data[data_size++] = 0;
269 :
270 : // write (partial) results as json
271 11 : char json[PIPE_BUF];
272 11 : int count = snprintf(json, PIPE_BUF, "{\"elink\": \"0x%x\", \"data\": \"%s\"}", elink, data);
273 11 : int result = write(flx->fd, json, count);
274 : // int result = write(flx->fd, data, data_size);
275 11 : if (result < 0) {
276 0 : LOG_ERR("errno=%d str=%s", errno, strerror(errno));
277 0 : exit(1);
278 : }
279 11 : fsync(flx->fd);
280 : }
281 :
282 317 : void flx_dma_from_host(struct flx* flx, struct cmem_buffer* dma_buffer, u_long buffer, size_t size, u_int wraparound)
283 : {
284 317 : LOG_INFO("> flx_dma_from_host(0x%lx, %d, %d)", buffer, size, wraparound);
285 317 : LOG_INFO("> regmap 0x%lx", flx_get_regmap_version(flx));
286 317 : if (flx_get_regmap_version(flx) < 0x0500) {
287 162 : flx_dma_from_host_rm4(flx, dma_buffer, buffer, size);
288 468 : return;
289 : }
290 :
291 155 : if (size > 8192) {
292 1 : LOG_ERR("Size %d larger than buffer 8192, output discarded");
293 1 : return;
294 : }
295 :
296 : // regmap 0x0500 and beyond, see FLX-1355
297 154 : uint8_t data[8192];
298 154 : uint16_t data_size = 0;
299 154 : LOG_INFO("> cmem paddr 0x%lx vaddr 0x%lx", dma_buffer->paddr, dma_buffer->vaddr);
300 154 : uint64_t offset = buffer - dma_buffer->paddr;
301 154 : uint8_t *ptr = (uint8_t*)(dma_buffer->vaddr + offset);
302 :
303 154 : if (flx->raw) {
304 143 : int result = write(flx->fd, ptr, size);
305 143 : if (result < 0) {
306 0 : LOG_ERR("errno=%d str=%s", errno, strerror(errno));
307 0 : exit(1);
308 : }
309 143 : fsync(flx->fd);
310 : }
311 :
312 : // decode
313 : uint8_t last = 0;
314 : uint16_t elink = 0;
315 312 : while(!last) {
316 158 : uint16_t hdr = (*(ptr + 31) << 8) | (*(ptr + 30));
317 158 : uint16_t part_size = hdr & 0x001F;
318 158 : elink = ((hdr & 0xFFE0) >> 5);
319 158 : last = part_size != 0x001F;
320 158 : part_size = part_size == 0x001F ? 0x001E : part_size;
321 : // printf("Hdr 0x%x\n", hdr);
322 : // printf("elink 0x%x\n", elink);
323 : // printf("size %d\n", part_size);
324 : // printf("last %d\n", last);
325 :
326 : // copy bytes in inverted mode
327 928 : for (uint16_t i = 0; i < part_size; i++) {
328 770 : data[data_size] = *(ptr + 29 - i);
329 770 : data_size++;
330 : }
331 :
332 158 : ptr += 32;
333 : }
334 :
335 154 : if (flx->raw) {
336 : return;
337 : }
338 :
339 : // add zero so that it writes as string
340 11 : data[data_size++] = 0;
341 :
342 : // write (partial) results as json
343 11 : char json[PIPE_BUF];
344 11 : int count = snprintf(json, PIPE_BUF, "{\"elink\": \"0x%x\", \"data\": \"%s\"}", elink, data);
345 11 : int result = write(flx->fd, json, count);
346 : // int result = write(flx->fd, data, data_size);
347 11 : if (result < 0) {
348 0 : LOG_ERR("errno=%d str=%s", errno, strerror(errno));
349 0 : exit(1);
350 : }
351 11 : fsync(flx->fd);
352 : }
353 :
354 0 : void flx_dma_wait(struct flx* flx, struct cmem_buffer* dma_buffer)
355 : {
356 : // LOG_ERR("> flx_dma_wait, ignored");
357 : // flx->flxcard->dma_wait(flx->dmaid);
358 0 : }
359 :
360 313 : bool flx_dma_enabled(struct flx* flx, struct cmem_buffer* dma_buffer)
361 : {
362 : // DMA is done instantly...
363 313 : return false;
364 : }
365 :
366 39 : int flx_dma_max_tlp_bytes(struct flx* flx)
367 : {
368 39 : LOG_INFO("< flx_dma_max_tlp_bytes() %d", 256);
369 39 : return 256; // flx->flxcard->dma_max_tlp_bytes();
370 : }
371 :
372 0 : void flx_cfg_set_option(struct flx* flx, const char *key, u_long value)
373 : {
374 0 : LOG_ERR("> flx_cfg_set_option NOT IMPLEMENTED %s 0x%x", key, value);
375 : // flx->flxcard->cfg_set_option(key, value);
376 0 : exit(1);
377 : }
378 :
379 0 : u_long flx_cfg_get_option(struct flx* flx, const char *key)
380 : {
381 :
382 : // return flx->flxcard->cfg_get_option(key);
383 0 : exit(1);
384 : }
385 :
386 0 : bool flx_cfg_check_option(struct flx* flx, const char *key)
387 : {
388 0 : LOG_ERR("< flx_cfg_get_option NOT IMPLEMENTED %s", key);
389 0 : return false;
390 : }
391 :
392 :
393 39 : unsigned flx_read_elink_config(struct flx* flx, struct elink_descr** elinks, u_int is_to_flx) {
394 39 : *elinks = (struct elink_descr*)malloc(flx->num_elinks * sizeof(elink_descr));
395 :
396 105 : for (unsigned i=0; i<flx->num_elinks; i++) {
397 66 : struct elink_descr* e = *elinks + i;
398 66 : e->elink = flx->elinks[i];
399 66 : e->type = elink_type::DAQ;
400 66 : e->has_streams = false;
401 66 : uint8_t stream = 0;
402 66 : uint8_t virt = 0;
403 132 : LOG_INFO("E-Link %d: %d 0x%x fid: 0x%lx, has streams: %c", flx->num_elinks, e->elink, e->elink, get_fid(flx->co, e->elink, stream, flx->vid, is_to_flx, virt), e->has_streams ? 'y' : 'n');
404 : }
405 : /* TODO */
406 39 : return flx->num_elinks;
407 : }
408 :
409 : uint64_t
410 2 : flx_dma_get_read_ptr(struct flx* flx, struct cmem_buffer* dma_buffer)
411 : {
412 2 : u_long dma_ptr = dma_buffer->pc_ptr;
413 2 : LOG_DBG("< flx_dma_get_read_ptr() 0x%x", dma_ptr);
414 2 : return dma_ptr;
415 : }
416 :
417 : uint64_t
418 2 : flx_dma_get_current_address(struct flx* flx, struct cmem_buffer* dma_buffer)
419 : {
420 2 : LOG_ERR("< flx_dma_get_current_address() NOT IMPLEMENTED\n");
421 2 : return 0;
422 : //return flx->flxcard->dma_get_current_address(flx->dmaid);
423 : }
424 :
425 : void
426 2 : flx_dma_set_ptr(struct flx* flx, struct cmem_buffer* dma_buffer, uint64_t pnew)
427 : {
428 : // FIXME only correct for one transfer
429 2 : flx_dma_from_host(flx, dma_buffer, dma_buffer->paddr, pnew, 0);
430 2 : }
431 :
432 0 : void flx_irq_data_enable(struct flx* flx){
433 0 : LOG_DBG("Enabling IRQ_DATA_AVAILABLE interrupt");
434 0 : }
435 :
436 0 : void flx_irq_data_disable(struct flx* flx){
437 0 : LOG_DBG("Disabling IRQ_DATA_AVAILABLE interrupt");
438 0 : }
439 :
440 0 : void flx_irq_busy_enable(struct flx* flx){
441 0 : LOG_DBG("Enabling IRQ_BUSY_CHANGE_TO_HOST interrupt");
442 0 : }
443 :
444 0 : void flx_irq_busy_disable(struct flx* flx){
445 0 : LOG_DBG("Disabling IRQ_BUSY_CHANGE_TO_HOST interrupt");
446 0 : }
|