Line data Source code
1 : #include <sys/types.h>
2 : #include <sys/stat.h>
3 : #include <fcntl.h>
4 : #include <cstdio>
5 : #include <cstdlib>
6 : #include <chrono>
7 : #include <thread>
8 :
9 : #include "block.h"
10 : #include "fifo.h"
11 : #include "felix/felix_fid.h"
12 :
13 : extern "C" {
14 : #include "flx_api.h"
15 : #include "cmem_buffer.h"
16 : #include "log.h"
17 : }
18 :
19 44 : void flx_init_cmem_buffer(struct cmem_buffer* buf, size_t size, char* cmem_name) {
20 44 : if (buf->vmem) {
21 42 : vmem_buffer_init(buf, size);
22 : } else {
23 2 : cmem_buffer_init(buf, size, cmem_name);
24 : }
25 44 : }
26 :
27 44 : void flx_close_cmem_buffer(struct cmem_buffer* buf) {
28 44 : if (buf->vmem) {
29 42 : vmem_buffer_close(buf);
30 : } else {
31 2 : cmem_buffer_close(buf);
32 : }
33 44 : }
34 :
35 : int
36 44 : flx_init_card(struct flx* flx, struct config* cfg)
37 : {
38 44 : LOG_INFO("> flx_init_card(file=%s, full_mode=%d)", cfg->file, cfg->full_mode);
39 44 : flx->device = cfg->device;
40 44 : flx->co = cfg->co;
41 44 : flx->vid = cfg->vid;
42 44 : flx->did = cfg->did;
43 44 : flx->cid = cfg->cid;
44 44 : flx->flxcard = NULL; // card is ignored, it is used in tohost
45 :
46 : // use open rather than fopen for fifos
47 44 : int fd = open(cfg->file, O_RDONLY | O_NONBLOCK);
48 44 : flx->fp = fdopen(fd, "r");
49 : // flx->fp = fopen(file, "r");
50 44 : if (flx->fp == NULL) {
51 0 : fprintf(stderr, "felix: error: could not open file %s\n", cfg->file);
52 0 : return 1;
53 : }
54 :
55 56 : LOG_INFO("Input from file %s in %s mode", cfg->file, cfg->repeat ? "repeat" : "non-repeat");
56 :
57 44 : flx->regmap_version = cfg->regmap;
58 44 : u_long major = (flx->regmap_version & 0xFF00) >> 8;
59 44 : u_long minor = (flx->regmap_version & 0x00FF) >> 0;
60 44 : LOG_INFO(" regmap version %lu.%lu", major, minor);
61 44 : flx->mode = cfg->full_mode ? FLX_MODE_FULL : FLX_MODE_GBT;
62 44 : flx->no_of_channels = 12;
63 :
64 44 : flx->ttc2h_enable = cfg->ttc2h_enable;
65 44 : flx->block_rate = cfg->block_rate;
66 44 : if (flx->regmap_version < 0x500){
67 23 : flx->trailer_size = 2;
68 23 : flx->block_size = 1024;
69 : } else {
70 21 : flx->block_size = cfg->block_size;
71 21 : flx->trailer_size = 4;
72 : }
73 :
74 : // elinks
75 44 : flx->num_elinks = cfg->num_elinks;
76 44 : flx->has_streams = cfg->has_streams;
77 44 : flx->elinks = cfg->elinks;
78 :
79 44 : flx->repeat = cfg->repeat;
80 :
81 44 : return 0;
82 : }
83 :
84 0 : int flx_get_toflx_dmaid(struct config* cfg){
85 0 : return cfg->dmaid;
86 : }
87 :
88 : void
89 44 : flx_close_card(struct flx* flx)
90 : {
91 44 : LOG_INFO("Closing felix device");
92 44 : fclose(flx->fp);
93 44 : }
94 :
95 :
96 : void
97 44 : flx_start_circular_dma(struct flx* flx, struct cmem_buffer* buf, unsigned dmaid)
98 : {
99 44 : LOG_INFO("> flx_start_circular_dma(dmaid=%d)", dmaid);
100 44 : flx->dmaid = dmaid;
101 :
102 : // flx->flxcard->dma_stop(dmaid);
103 : // flx->flxcard->dma_to_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND);
104 :
105 44 : buf->pstart = buf->paddr;
106 44 : buf->pend = buf->pstart + buf->size;
107 44 : buf->pc_ptr = buf->pstart; // flx->flxcard->dma_get_read_ptr(dmaid);
108 :
109 44 : flx->fw_ptr = buf->pstart;
110 :
111 44 : LOG_INFO(" cmem buffer [0x%x,0x%x] %lu Blocks", buf->pstart, buf->pend, buf->size/1024);
112 44 : LOG_INFO(" cmem virtual address 0x%x", buf->vaddr);
113 44 : LOG_INFO(" fw_ptr 0x%x", flx->fw_ptr);
114 44 : LOG_INFO(" pc_ptr 0x%x", buf->pc_ptr);
115 44 : }
116 :
117 : void
118 9073479 : flx_wait_data_available(struct flx* flx, struct cmem_buffer* buf)
119 : {
120 9073479 : LOG_TRACE("flx_wait_data_available");
121 9073479 : if (flx->repeat) {
122 : // just return after 500 ns, data is always available
123 6116703 : std::this_thread::sleep_for(std::chrono::nanoseconds(500));
124 : } else {
125 : // FIXME for fifo we should rely on inotify, option should be called flx->fifo, which infers no-repeat
126 2956776 : std::this_thread::sleep_for(std::chrono::nanoseconds(500));
127 : // std::this_thread::sleep_for(std::chrono::seconds(3));
128 : }
129 9073479 : }
130 :
131 : void
132 44 : flx_cancel_irqs(struct flx* flx)
133 : {
134 : // ignore
135 44 : }
136 :
137 :
138 : int
139 0 : flx_dma_cmp_even_bits(struct flx* flx)
140 : {
141 0 : LOG_ERR("< flx_check_dma_cmp_even_bits() NOT IMPLEMENTED\n");
142 0 : return 0;
143 : }
144 :
145 : void
146 5750323 : flx_read_and_update_fw_ptr(struct flx* flx, struct cmem_buffer* buf)
147 : {
148 5750323 : LOG_TRACE("flx_read_and_update_fw_ptr");
149 : // File READ
150 5750323 : void *ptr = (void*)(buf->vaddr + (flx->fw_ptr - buf->pstart));
151 5750323 : size_t block_size = flx->block_size;
152 5750323 : size_t max_count;
153 5750323 : if (flx->block_rate == 0) {
154 5748875 : max_count = (buf->pend - flx->fw_ptr)/block_size;
155 1448 : } else if (flx->block_rate < 6000){
156 : max_count = 1;
157 0 : } else if (flx->block_rate < 12000){
158 : max_count = 2;
159 0 : } else if (flx->block_rate < 120000){
160 : max_count = 10;
161 : } else {
162 0 : max_count = 32;
163 : }
164 5750323 : std::chrono::time_point<std::chrono::system_clock> start, end;
165 :
166 5750323 : start = std::chrono::system_clock::now();
167 5750323 : size_t count = fread(ptr, block_size, max_count, flx->fp);
168 5750323 : end = std::chrono::system_clock::now();
169 :
170 : //so reading a block takes
171 5750323 : if(flx->block_rate > 0 && count > 0){
172 1444 : std::chrono::nanoseconds elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
173 1444 : long block_read_time = elapsed_time.count()/count;
174 1444 : long target_time = 1.0e9*(1.0/(double)flx->block_rate);
175 1444 : long sleep_time = target_time - block_read_time;
176 1444 : std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_time));
177 : }
178 :
179 5750323 : if ((count == 0) && (flx->repeat)) {
180 1401377 : LOG_TRACE("Reset file");
181 1401377 : fseek(flx->fp, 0, SEEK_SET);
182 : }
183 5750323 : flx->fw_ptr += block_size*count;
184 5750323 : if(flx->fw_ptr == buf->pend){
185 4116 : flx->fw_ptr = buf->pstart;
186 4116 : flx->odd = !flx->odd;
187 4116 : LOG_TRACE("Odd %d", flx->odd);
188 : }
189 5750323 : }
190 :
191 : size_t
192 3082487 : flx_bytes_available(struct flx* flx, struct cmem_buffer* buf)
193 : {
194 3082487 : flx_read_and_update_fw_ptr(flx, buf);
195 :
196 3082487 : u_long dma_ptr = flx->fw_ptr; // flx->flxcard->dma_get_current_address(flx->dmaid);
197 3082487 : size_t available;
198 :
199 3082487 : if(!flx->odd) // if(flx->flxcard->dma_cmp_even_bits(flx->dmaid))
200 : {
201 3013881 : LOG_TRACE("< flx_bytes_available(even) %d", dma_ptr - buf->pc_ptr);
202 3013881 : available = dma_ptr - buf->pc_ptr;
203 : }
204 : else
205 : {
206 68606 : LOG_TRACE("< flx_bytes_available(odd) %d", buf->size + dma_ptr - buf->pc_ptr);
207 68606 : available = buf->size + dma_ptr - buf->pc_ptr;
208 : }
209 3082487 : return available;
210 : }
211 :
212 : size_t
213 0 : flx_bytes_available_to_read(struct flx* flx, struct cmem_buffer* buf)
214 : {
215 0 : size_t available = flx_bytes_available(flx, buf);
216 0 : available = MIN(available, buf->pend - buf->pc_ptr);
217 0 : LOG_TRACE("< flx_bytes_available_to_read() %d", available);
218 0 : return available;
219 : }
220 :
221 : void*
222 2667836 : flx_get_write_ptr(struct flx* flx, struct cmem_buffer* buf)
223 : {
224 2667836 : flx_read_and_update_fw_ptr(flx, buf);
225 :
226 2667836 : u_long dma_ptr = flx->fw_ptr; // flx->flxcard->dma_get_current_address(flx->dmaid);
227 2667836 : LOG_TRACE("< flx_get_write_ptr() 0x%x", dma_ptr);
228 2667836 : return (void*)(buf->vaddr + (dma_ptr - buf->pstart));
229 : }
230 :
231 : void*
232 2667836 : flx_get_read_ptr(struct flx* flx, struct cmem_buffer* buf)
233 : {
234 2667836 : u_long dma_ptr = buf->pc_ptr;
235 2667836 : LOG_TRACE("< flx_get_read_ptr() 0x%x", dma_ptr);
236 2667836 : return (void*)(buf->vaddr + (dma_ptr - buf->pstart));
237 : }
238 :
239 : void
240 2668969 : flx_set_read_ptr(struct flx* flx, struct cmem_buffer* buf, void* ptr)
241 : {
242 2668969 : LOG_TRACE("x %x %x %x", ptr, buf->pc_ptr, flx->fw_ptr);
243 2668969 : uint64_t pnew = buf->pstart + ((uint64_t)ptr - buf->vaddr);
244 2668969 : LOG_TRACE("> flx_set_read_ptr(ptr=0x%x)", pnew);
245 2668969 : buf->pc_ptr = pnew; // flx->flxcard->dma_set_ptr(flx->dmaid, pnew);
246 2668969 : }
247 :
248 : void
249 3082487 : flx_advance_read_ptr(struct flx* flx, struct cmem_buffer* buf, size_t bytes)
250 : {
251 3082487 : buf->pc_ptr += bytes;
252 3082487 : if(buf->pc_ptr == buf->pend){
253 3367 : buf->pc_ptr = buf->pstart;
254 : }
255 3082487 : LOG_TRACE("> flx_advance_read_ptr(bytes=%d) 0x%x", bytes, buf->pc_ptr);
256 : // flx->flxcard->dma_set_ptr(flx->dmaid, buf->pc_ptr);
257 3082487 : }
258 :
259 44 : int flx_get_regmap_version(struct flx* flx) {
260 : // 4.10 formatted as 0x040A
261 44 : return flx->regmap_version;
262 : }
263 :
264 : int
265 88 : flx_get_mode(struct flx* flx)
266 : {
267 88 : LOG_INFO("< flx_get_mode() %d", flx->mode);
268 88 : return flx->mode;
269 : }
270 :
271 27 : int flx_get_number_of_channels(struct flx* flx)
272 : {
273 27 : LOG_INFO("< flx_get_number_of_channels() %d", flx->no_of_channels);
274 27 : return flx->no_of_channels;
275 : }
276 :
277 0 : int flx_get_wide_mode(struct flx* flx)
278 : {
279 0 : LOG_INFO("< flx_get_wide_mode() %d", 0);
280 0 : return 0;
281 : }
282 :
283 44 : uint64_t flx_get_blocksize(struct flx* flx)
284 : {
285 44 : return flx->block_size;
286 : }
287 :
288 44 : int flx_get_trailer_size(struct flx* flx)
289 : {
290 44 : return flx->trailer_size;
291 : }
292 :
293 0 : int flx_is_enabled(struct flx* flx, u_int channel, u_int egroup, u_int epath, u_int is_to_flx)
294 : {
295 0 : LOG_INFO("< flx_is_enabled() %d", 1);
296 0 : return 1;
297 : }
298 :
299 0 : int flx_has_stream_id(struct flx* flx, u_int channel, u_int egroup, u_int epath)
300 : {
301 0 : LOG_INFO("< flx_has_stream_id() %d", 1);
302 0 : return 1;
303 : }
304 :
305 0 : void flx_dma_from_host(struct flx* flx, struct cmem_buffer* dma_buffer, uint64_t buffer, size_t size, unsigned int wraparound)
306 : {
307 0 : LOG_ERR("> flx_dma_from_host NOT IMPLEMENTED");
308 : // flx->flxcard->dma_from_host(flx->dmaid, buffer, size, 0);
309 0 : exit(1);
310 : }
311 :
312 0 : void flx_dma_wait(struct flx* flx, struct cmem_buffer* buf)
313 : {
314 0 : LOG_ERR("> flx_dma_wait NOT IMPLEMENTED");
315 : // flx->flxcard->dma_wait(flx->dmaid);
316 0 : exit(1);
317 : }
318 :
319 0 : int flx_dma_max_tlp_bytes(struct flx* flx)
320 : {
321 0 : LOG_INFO("< flx_dma_max_tlp_bytes() %d", 256);
322 0 : return 256; // flx->flxcard->dma_max_tlp_bytes();
323 : }
324 :
325 0 : void flx_cfg_set_option(struct flx* flx, const char *key, u_long value)
326 : {
327 0 : LOG_ERR("> flx_cfg_set_option NOT IMPLEMENTED %s 0x%x", key, value);
328 : // flx->flxcard->cfg_set_option(key, value);
329 0 : exit(1);
330 : }
331 :
332 0 : u_long flx_cfg_get_option(struct flx* flx, const char *key)
333 : {
334 0 : LOG_ERR("< flx_cfg_get_option NOT IMPLEMENTED %s", key);
335 : // return flx->flxcard->cfg_get_option(key);
336 0 : return 0;
337 : }
338 :
339 220 : bool flx_cfg_check_option(struct flx* flx, const char *key)
340 : {
341 220 : LOG_ERR("< flx_cfg_get_option NOT IMPLEMENTED %s", key);
342 220 : return false;
343 : }
344 :
345 : uint64_t
346 64512 : flx_dma_get_read_ptr(struct flx* flx, struct cmem_buffer* buf)
347 : {
348 64512 : u_long dma_ptr = buf->pc_ptr;
349 64512 : return dma_ptr;
350 : }
351 :
352 : uint64_t
353 64512 : flx_dma_get_current_address(struct flx* flx, struct cmem_buffer* buf)
354 : {
355 64512 : return 0;
356 : //return flx->flxcard->dma_get_current_address(flx->dmaid);
357 : }
358 :
359 : #define BLOCK_EGROUP_MASK 0x0038
360 : #define BLOCK_EGROUP_SHIFT 3
361 :
362 44 : unsigned int flx_read_elink_config(struct flx* flx, struct elink_descr** elinks, unsigned int is_to_flx) {
363 44 : unsigned num_elinks = 0;
364 :
365 : // plus 1 for the TTC2H
366 44 : unsigned number_of_paths = flx->num_elinks + 1;
367 44 : *elinks = (struct elink_descr*)malloc(number_of_paths * sizeof(elink_descr));
368 :
369 : //TTC-to-Host link = #Nchannels group #7 path #3
370 44 : if (flx->ttc2h_enable) {
371 4 : struct elink_descr* e = *elinks + num_elinks++;
372 4 : unsigned no_of_channels = flx_get_number_of_channels(flx);
373 4 : e->elink = TTC2HOST_LINK(no_of_channels);
374 4 : e->type = elink_type::TTC;
375 4 : e->has_streams = 0;
376 4 : LOG_INFO("TTC2H E-Link %d:\t 0x%02X", num_elinks-1, e->elink);
377 : }
378 :
379 : uint8_t stream = 0; // NOTE, the full elink, no streams
380 : uint8_t virt = 0;
381 :
382 101 : for (unsigned i=0; i<flx->num_elinks; i++) {
383 57 : struct elink_descr* e = *elinks + num_elinks++;
384 57 : e->elink = flx->elinks[i];
385 57 : e->has_streams = flx->has_streams[i];
386 57 : int egroupnr = (flx->elinks[i] & BLOCK_EGROUP_MASK) >> BLOCK_EGROUP_SHIFT;
387 57 : if (egroupnr < 7) {
388 57 : e->type = elink_type::DAQ;
389 167 : LOG_INFO("DAQ E-Link %d: %d 0x%x fid: 0x%lx, has streams: %c", i, e->elink, e->elink, get_fid(flx->co, e->elink, stream, flx->vid, is_to_flx, virt), e->has_streams ? 'y' : 'n');
390 : }
391 : else {
392 0 : e->type = elink_type::DCS;
393 0 : LOG_INFO("DCS E-Link %d: %d 0x%x fid: 0x%lx, has streams: %c", i, e->elink, e->elink, get_fid(flx->co, e->elink, stream, flx->vid, is_to_flx, virt), e->has_streams ? 'y' : 'n');
394 : }
395 : }
396 44 : return num_elinks;
397 : }
398 :
399 44 : void flx_irq_data_enable(struct flx* flx){
400 44 : LOG_DBG("Enabling IRQ_DATA_AVAILABLE interrupt");
401 44 : }
402 :
403 88 : void flx_irq_data_disable(struct flx* flx){
404 88 : LOG_DBG("Disabling IRQ_DATA_AVAILABLE interrupt");
405 88 : }
406 :
407 44 : void flx_irq_busy_enable(struct flx* flx){
408 44 : LOG_DBG("Enabling IRQ_BUSY_CHANGE_TO_HOST interrupt");
409 44 : }
410 :
411 44 : void flx_irq_busy_disable(struct flx* flx){
412 44 : LOG_DBG("Disabling IRQ_BUSY_CHANGE_TO_HOST interrupt");
413 44 : }
|