Line data Source code
1 : #include <cstdint>
2 :
3 : #include "device.hpp"
4 :
5 : #include "flxcard/FlxException.h"
6 : #include "DFDebug/DFDebug.h"
7 :
8 : #include "felix/felix_fid.h"
9 : #include "regmap/regmap.h"
10 : #include "block.hpp"
11 : #include "log.hpp"
12 :
13 :
14 0 : FlxDevice::FlxDevice(Config& cfg, unsigned dev_no)
15 0 : : Device(dev_no, cfg.resource.vid, cfg.resource.did, cfg.get_device_cid(dev_no))
16 0 : { }
17 :
18 :
19 0 : FlxDevice::FlxDevice(unsigned dev_no)
20 0 : : Device(dev_no, 1, 0, dev_no)
21 0 : { }
22 :
23 :
24 0 : int FlxDevice::open_device(u_int lock_mask)
25 : {
26 0 : u_int current_lock{0};
27 0 : LOG_DBG("Initializing device %u asking for lock 0x%x", m_device_number, lock_mask);
28 0 : try {
29 0 : current_lock = m_dev.get_lock_mask(m_device_number);
30 0 : LOG_DBG("Device %d had locks 0x%x", m_device_number, current_lock);
31 : }
32 0 : catch(FlxException &ex) {
33 0 : LOG_ERR("Cannot get lock mask for device %u", m_device_number);
34 0 : LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str());
35 0 : return ex.getErrorId();
36 0 : }
37 :
38 0 : try {
39 0 : m_dev.card_open(m_device_number, lock_mask);
40 : }
41 0 : catch(FlxException &ex) {
42 0 : LOG_ERR("Could not open device %u", m_device_number);
43 0 : LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str());
44 0 : return ex.getErrorId();
45 0 : }
46 :
47 : // Clear various latched signals
48 0 : if (current_lock == 0) {
49 0 : m_dev.m_bar2->TTC_BUSY_CLEAR = 1;
50 0 : uint64_t c;
51 0 : c = m_dev.m_bar2->XOFF_FM_HIGH_THRESH.CROSS_LATCHED;
52 0 : m_dev.m_bar2->XOFF_FM_HIGH_THRESH.CROSS_LATCHED = c;
53 0 : c = m_dev.m_bar2->DMA_BUSY_STATUS.ENABLE;
54 0 : m_dev.m_bar2->DMA_BUSY_STATUS.ENABLE = c;
55 0 : c = m_dev.m_bar2->FM_BUSY_CHANNEL_STATUS.BUSY;
56 0 : m_dev.m_bar2->FM_BUSY_CHANNEL_STATUS.BUSY = c;
57 0 : c = m_dev.m_bar2->BUSY_MAIN_OUTPUT_FIFO_STATUS.HIGH_THRESH_CROSSED_LATCHED;
58 0 : m_dev.m_bar2->BUSY_MAIN_OUTPUT_FIFO_STATUS.HIGH_THRESH_CROSSED_LATCHED = c;
59 : }
60 :
61 0 : m_firmware_type = m_dev.firmware_type();
62 0 : return 0;
63 : }
64 :
65 :
66 0 : void FlxDevice::close_device()
67 : {
68 : //stop all DMAs ?
69 : //flxcard->dma_stop(dmaid);
70 0 : LOG_DBG("Closing device %d", m_device_number);
71 0 : m_dev.card_close();
72 0 : }
73 :
74 :
75 0 : bool FlxDevice::is_primary()
76 : {
77 0 : return not static_cast<bool>(m_dev.m_bar2->PCIE_ENDPOINT);
78 : }
79 :
80 :
81 0 : unsigned int FlxDevice::get_card_endpoints()
82 : {
83 0 : return m_dev.m_bar2->NUMBER_OF_PCIE_ENDPOINTS;
84 : }
85 :
86 :
87 0 : unsigned int FlxDevice::get_card_model()
88 : {
89 0 : return m_dev.m_bar2->CARD_TYPE;
90 : }
91 :
92 :
93 0 : u_int FlxDevice::get_regmap_version()
94 : {
95 0 : return m_dev.m_bar2->REG_MAP_VERSION;
96 : }
97 :
98 :
99 0 : u_int FlxDevice::get_number_of_channels()
100 : {
101 0 : return m_dev.m_bar2->NUM_OF_CHANNELS;
102 : }
103 :
104 :
105 0 : bool FlxDevice::get_wide_mode()
106 : {
107 0 : return (m_dev.m_bar2->WIDE_MODE == 1 ? true : false);
108 : }
109 :
110 :
111 0 : u_int FlxDevice::get_block_size()
112 : {
113 0 : return m_dev.m_bar2->BLOCKSIZE;
114 : }
115 :
116 :
117 0 : u_int FlxDevice::get_trailer_size()
118 : {
119 0 : u_int tsize = m_dev.m_bar2->CHUNK_TRAILER_32B == 1 ? 4 : 2;
120 0 : if( tsize != sizeof(subchunk_trailer_t) ){
121 0 : throw std::runtime_error("SW/FW trailer size mismatch");
122 : }
123 0 : return tsize;
124 : }
125 :
126 :
127 0 : flx_fromhost_format FlxDevice::get_fromhost_data_format()
128 : {
129 : #if REGMAP_VERSION < 0x0500
130 : m_fromHostDataFormat = static_cast<flx_fromhost_format>(FROMHOST_FORMAT_REGMAP4);
131 : #else
132 0 : m_fromHostDataFormat = static_cast<flx_fromhost_format>(m_dev.m_bar2->FROMHOST_DATA_FORMAT);
133 : #endif
134 0 : return m_fromHostDataFormat;
135 : }
136 :
137 :
138 0 : flx_tohost_format FlxDevice::get_tohost_data_format()
139 : {
140 : #if REGMAP_VERSION < 0x0500
141 : return TOHOST_SUBCHUNK_TRAILER;
142 : #else
143 0 : return static_cast<flx_tohost_format>(m_dev.m_bar2->TOHOST_DATA_FORMAT);
144 : #endif
145 : }
146 :
147 :
148 0 : int FlxDevice::get_fromhost_dmaid()
149 : {
150 0 : if (m_dev.m_bar2 == nullptr) {
151 0 : LOG_ERR("m_dev.m_bar2 is null");
152 0 : return -1;
153 : }
154 :
155 0 : int dmaid = m_dev.m_bar2->GENERIC_CONSTANTS.DESCRIPTORS - 1;
156 0 : if (dmaid < 0) {
157 0 : LOG_ERR("Invalid ToFLx DMA ID %d", dmaid);
158 : } else {
159 : LOG_TRACE("ToFlx dmaid %d", dmaid);
160 : }
161 : return dmaid;
162 : }
163 :
164 :
165 0 : int FlxDevice::get_trickle_dmaid()
166 : {
167 : #if REGMAP_VERSION >= 0x0500
168 0 : int dmaid = m_dev.m_bar2->GENERIC_CONSTANTS.TRICKLE_DESCRIPTOR_INDEX;
169 : //int trickle_offset = m_dev.m_bar2->GENERIC_CONSTANTS.TRICKLE_DESCRIPTOR_INDEX;
170 : //dmaid = dmaid + trickle_offset;
171 :
172 0 : if (dmaid < 0) {
173 : LOG_ERR("Invalid ToFLx DMA ID %d", dmaid);
174 : }
175 0 : LOG_TRACE("Trickle dmaid %d", dmaid);
176 0 : return dmaid;
177 : #endif
178 :
179 : return -1;
180 : }
181 :
182 :
183 0 : int FlxDevice::dma_max_tlp_bytes()
184 : {
185 0 : return m_dev.dma_max_tlp_bytes();
186 : }
187 :
188 :
189 0 : void FlxDevice::set_register(const char *key, uint64_t value)
190 : {
191 0 : try {
192 0 : m_dev.cfg_set_option(key, value);
193 : }
194 0 : catch(FlxException &ex) {
195 0 : LOG_INFO("Register %s not available with current firmware version.", key);
196 0 : }
197 0 : }
198 :
199 :
200 0 : uint64_t FlxDevice::get_register(const char *key)
201 : {
202 0 : try {
203 0 : return m_dev.cfg_get_option(key);
204 : }
205 0 : catch(FlxException &ex) {
206 0 : LOG_INFO("Register %s not available with current firmware version.", key);
207 0 : return 0;
208 0 : }
209 : }
210 :
211 :
212 0 : bool FlxDevice::check_register(const char *key)
213 : {
214 0 : try {
215 0 : m_dev.cfg_get_option(key);
216 : return true;
217 : }
218 0 : catch(FlxException &ex) {
219 0 : LOG_INFO("Register %s not available with current firmware version.", key);
220 0 : return false;
221 0 : }
222 : }
223 :
224 :
225 0 : void FlxDevice::cancel_irq(int i)
226 : {
227 0 : try{
228 0 : m_dev.irq_cancel(i);
229 : }
230 0 : catch(FlxException &ex) {
231 0 : LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str());
232 0 : }
233 0 : }
234 :
235 :
236 0 : void FlxDevice::irq_wait(int i)
237 : {
238 0 : m_dev.irq_wait(i);
239 0 : }
240 :
241 :
242 0 : void FlxDevice::irq_enable(int i)
243 : {
244 0 : try{
245 0 : m_dev.irq_enable(i);
246 : }
247 0 : catch(FlxException &ex) {
248 0 : LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str());
249 0 : }
250 0 : }
251 :
252 :
253 0 : void FlxDevice::irq_disable(int i)
254 : {
255 0 : try{
256 0 : m_dev.irq_disable(i);
257 : }
258 0 : catch(FlxException &ex) {
259 0 : LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str());
260 0 : }
261 0 : }
262 :
263 :
264 : #if REGMAP_VERSION < 0x0500
265 : encoding_t FlxDevice::elink_get_encoding(u_int channel, u_int egroup, u_int epath, bool is_to_flx)
266 : {
267 : if (!is_to_flx && (m_firmware_type == FIRMW_FULL || m_firmware_type == FIRMW_MROD)) {
268 : return ENC_8b10b;
269 : }
270 : else {
271 : int enc = 0;
272 : if (is_to_flx) {
273 : uint64_t modebits = m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_FROMHOST[egroup].FROMHOST.PATH_ENCODING;
274 : uint64_t mask = 0xF << 4*epath; // 4 bits per E-path
275 : enc = ((modebits & mask) >> 4*epath);
276 : }
277 : else {
278 : uint64_t modebits = m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_TOHOST[egroup].TOHOST.PATH_ENCODING;
279 : uint64_t mask = 0x3 << 2*epath; // 2 bits per E-path
280 : enc = ((modebits & mask) >> 2*epath);
281 : }
282 : if(enc < 0 || enc > 100){
283 : LOG_ERR("Invalid encoding type %d \
284 : for elink channel %u group %u, epath %u using DIRECT",
285 : enc, channel, egroup, epath);
286 : return ENC_DIRECT;
287 : }
288 : else {
289 : return static_cast<encoding_t>(enc);
290 : }
291 : }
292 : }
293 : #else
294 0 : encoding_t FlxDevice::elink_get_encoding(u_int channel, u_int egroup, u_int epath, bool is_to_flx)
295 : {
296 0 : if (!is_to_flx && (m_firmware_type == FIRMW_FULL)) {
297 : return ENC_8b10b;
298 : }
299 0 : else if (!is_to_flx && (m_firmware_type == FIRMW_INTERLAKEN)){
300 : return ENC_INTERLAKEN;
301 : }
302 : else {
303 0 : int enc = 0;
304 0 : if (is_to_flx) {
305 0 : uint64_t modebits = m_dev.m_bar2->ENCODING_EGROUP_CTRL_GEN[channel].ENCODING_EGROUP[egroup].ENCODING_EGROUP_CTRL.PATH_ENCODING;
306 0 : uint64_t mask = 0xF << 4*epath; // 4 bits per E-path
307 0 : enc = ((modebits & mask) >> 4*epath);
308 : }
309 : else {
310 0 : uint64_t modebits = m_dev.m_bar2->DECODING_EGROUP_CTRL_GEN[channel].DECODING_EGROUP[egroup].EGROUP.PATH_ENCODING;
311 0 : uint64_t mask = 0xF << 4*epath; // 4 bits per E-path
312 0 : enc = ((modebits & mask) >> 4*epath);
313 : }
314 0 : if(enc < 0 || enc > 100){
315 0 : LOG_ERR("Invalid encoding type %d \
316 : for elink channel %u group %u, epath %u using DIRECT",
317 : enc, channel, egroup, epath);
318 0 : return ENC_DIRECT;
319 : }
320 : else {
321 0 : return static_cast<encoding_t>(enc);
322 : }
323 : }
324 : }
325 : #endif
326 :
327 :
328 0 : bool FlxDevice::elink_is_in_dma(local_elink_t elinknr, int dmaid)
329 : {
330 : #if REGMAP_VERSION < 0x0500
331 : return true;
332 : #else
333 0 : bool is_elink_in_dma = false;
334 0 : if (dmaid == m_dev.m_bar2->GENERIC_CONSTANTS.FROMHOST_DESCRIPTOR_INDEX){
335 : is_elink_in_dma = true;
336 : } else {
337 0 : m_dev.m_bar2->CRTOHOST_DMA_DESCRIPTOR_2.AXIS_ID = elinknr;
338 0 : unsigned int elink_dmaid = m_dev.m_bar2->CRTOHOST_DMA_DESCRIPTOR_2.DESCR_READ & 0xF;
339 0 : unsigned int max_id = m_dev.m_bar2->GENERIC_CONSTANTS.DESCRIPTORS - 1;
340 0 : if (elink_dmaid > max_id){
341 0 : LOG_ERR("Invalid DMA ID %u for E-link %u (DMA ID [0, %u]). Discarded elink.", elink_dmaid, elinknr, max_id);
342 0 : } else if (elink_dmaid == static_cast<unsigned int>(dmaid)){
343 0 : is_elink_in_dma = true;
344 : }
345 : }
346 0 : return is_elink_in_dma;
347 : #endif
348 : }
349 :
350 :
351 : #if REGMAP_VERSION < 0x0500
352 : bool FlxDevice::elink_is_enabled(u_int channel, u_int egroup, u_int epath, bool is_to_flx)
353 : {
354 : if (m_firmware_type == FIRMW_FULL) {
355 : return !is_to_flx && ((m_dev.m_bar2->CR_FM_PATH_ENA >> channel) & 1);
356 : }
357 : // MROD
358 : else if (m_firmware_type == FIRMW_MROD) {
359 : u_long eproc_ena = m_dev.m_bar2->MROD_EP0_CSMENABLE;
360 : return !is_to_flx && ((eproc_ena >> channel) & 1);
361 : }
362 : // GBT Mode
363 : else {
364 : u_long eproc_ena = is_to_flx ?
365 : m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_FROMHOST[egroup].FROMHOST.EPROC_ENA :
366 : m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_TOHOST[egroup].TOHOST.EPROC_ENA;
367 : // Central Router documentation p. 13
368 : switch (epath) {
369 : case 0: return ((eproc_ena >> 3) & 1) || ((eproc_ena >> 7) & 1);
370 : case 1: return ((eproc_ena >> 1) & 1) || ((eproc_ena >> 8) & 1);
371 : case 2: return ((eproc_ena >> 4) & 1) || ((eproc_ena >> 9) & 1);
372 : case 3: return ((eproc_ena >> 0) & 1) || ((eproc_ena >> 10) & 1);
373 : case 4: return ((eproc_ena >> 5) & 1) || ((eproc_ena >> 11) & 1);
374 : case 5: return ((eproc_ena >> 2) & 1) || ((eproc_ena >> 12) & 1);
375 : case 6: return ((eproc_ena >> 6) & 1) || ((eproc_ena >> 13) & 1);
376 : case 7: return ((eproc_ena >> 14) & 1);
377 : default: return false;
378 : }
379 : }
380 : return false;
381 : }
382 : #else
383 0 : bool FlxDevice::elink_is_enabled(u_int channel, u_int egroup, u_int epath, bool is_to_flx)
384 : {
385 0 : uint32_t enables_phase2;
386 0 : if( is_to_flx ) {
387 0 : enables_phase2 = (uint32_t) m_dev.m_bar2->ENCODING_EGROUP_CTRL_GEN[channel].ENCODING_EGROUP[egroup].ENCODING_EGROUP_CTRL.EPATH_ENA;
388 : } else {
389 0 : enables_phase2 = (uint32_t) m_dev.m_bar2->DECODING_EGROUP_CTRL_GEN[channel].DECODING_EGROUP[egroup].EGROUP.EPATH_ENA;
390 : }
391 0 : return (enables_phase2 >> epath) & 0x01;
392 :
393 : }
394 : #endif
395 :
396 0 : uint64_t FlxDevice::get_broadcast_enable_gen(u_int channel) {
397 : #if REGMAP_VERSION >= 0x0500
398 0 : return m_dev.m_bar2->BROADCAST_ENABLE_GEN[channel].BROADCAST_ENABLE;
399 : #else
400 : return 0;
401 : #endif
402 : }
403 :
404 :
405 0 : local_elink_t FlxDevice::get_ec_elink(bool is_to_flx, u_int channel)
406 : {
407 0 : std::pair<int,int> ec_indices = m_dev.ec_elink_indices();
408 0 : if( is_to_flx ) {
409 0 : return ((channel<<6) + ec_indices.second);
410 : } else {
411 0 : return ((channel<<6) + ec_indices.first);
412 : }
413 : }
414 :
415 :
416 0 : local_elink_t FlxDevice::get_ic_elink(bool is_to_flx, u_int channel)
417 : {
418 0 : std::pair<int,int> ic_indices = m_dev.ic_elink_indices();
419 0 : if( is_to_flx ) {
420 0 : return ((channel<<6) + ic_indices.second);
421 : } else {
422 0 : return ((channel<<6) + ic_indices.first);
423 : }
424 : }
425 :
426 :
427 0 : local_elink_t FlxDevice::get_aux_elink(bool is_to_flx, u_int channel)
428 : {
429 0 : local_elink_t ic_elink = get_ic_elink(is_to_flx, channel);
430 : #if REGMAP_VERSION < 0x0500
431 : return (ic_elink - 1);
432 : #else
433 0 : return (ic_elink + 1); // Not (yet) defined
434 : #endif
435 : }
436 :
437 :
438 0 : bool FlxDevice::elink_is_ec_enabled(bool is_to_flx, u_int channel)
439 : {
440 : #if REGMAP_VERSION < 0x0500
441 : if( is_to_flx ) {
442 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.ENABLE);
443 : } else {
444 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.ENABLE);
445 : }
446 : #else
447 0 : if( is_to_flx ) {
448 0 : return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.EC_ENABLE);
449 : } else {
450 0 : return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.EC_ENABLE);
451 : }
452 : #endif
453 : }
454 :
455 :
456 0 : bool FlxDevice::elink_is_ic_enabled(bool is_to_flx, u_int channel)
457 : {
458 : #if REGMAP_VERSION < 0x0500
459 : if( is_to_flx ) {
460 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.IC_ENABLE);
461 : } else {
462 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.IC_ENABLE);
463 : }
464 : #else
465 0 : if( is_to_flx ) {
466 0 : return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.IC_ENABLE);
467 : } else {
468 0 : return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.IC_ENABLE);
469 : }
470 : #endif
471 : }
472 :
473 :
474 0 : bool FlxDevice::elink_is_aux_enabled(bool is_to_flx, u_int channel)
475 : {
476 : #if REGMAP_VERSION < 0x0500
477 : if( is_to_flx ) {
478 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.SCA_AUX_ENABLE);
479 : } else {
480 : return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.SCA_AUX_ENABLE);
481 : }
482 : #else
483 0 : if( is_to_flx ) {
484 0 : return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.AUX_ENABLE);
485 : } else {
486 0 : return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.AUX_ENABLE);
487 : }
488 : #endif
489 : }
490 :
491 :
492 0 : bool FlxDevice::elink_has_stream_id(u_int channel, u_int egroup, u_int epath)
493 : {
494 0 : if(channel > get_number_of_channels()){
495 0 : LOG_ERR("Checking stream status on invalid channel %u", channel);
496 0 : return false;
497 : }
498 0 : u_long enable = 0;
499 : #if REGMAP_VERSION < 0x0500
500 : switch (egroup)
501 : {
502 : case 0:
503 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP0;
504 : break;
505 : case 1:
506 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP1;
507 : break;
508 : case 2:
509 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP2;
510 : break;
511 : case 3:
512 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP3;
513 : break;
514 : case 4:
515 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP4;
516 : break;
517 : case 5:
518 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP5;
519 : break;
520 : case 6:
521 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP6;
522 : break;
523 : default:
524 : LOG_ERR("Checking stream status on invalid egroup %u.", egroup);
525 : break;
526 : }
527 : #else
528 0 : switch (egroup)
529 : {
530 0 : case 0:
531 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP0;
532 0 : break;
533 0 : case 1:
534 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP1;
535 0 : break;
536 0 : case 2:
537 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP2;
538 0 : break;
539 0 : case 3:
540 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP3;
541 0 : break;
542 0 : case 4:
543 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP4;
544 0 : break;
545 0 : case 5:
546 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP5;
547 0 : break;
548 0 : case 6:
549 0 : enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP6;
550 0 : break;
551 0 : default:
552 0 : LOG_ERR("Checking stream status on invalid egroup %u.", egroup);
553 0 : break;
554 : }
555 : #endif
556 0 : return static_cast<bool>( (enable >> epath) & 1);
557 : }
558 :
559 :
560 0 : std::vector<Elink> FlxDevice::read_enabled_elinks(int dmaid)
561 : {
562 0 : std::vector<Elink> enabled_elinks;
563 :
564 : // If Trickle mode is active, only the Trickle E-link is enabled and returned
565 0 : bool is_trickle = (dmaid == get_trickle_dmaid()) ? true : false;
566 0 : if (is_trickle){
567 0 : local_elink_t lid = 0xffff;
568 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, lid, 0, m_vid, true, true);
569 0 : enabled_elinks.emplace_back(Elink{fid, lid, 0, elink_type_t::DAQ, encoding_t::ENC_8b10b});
570 0 : return enabled_elinks;
571 : }
572 :
573 0 : bool is_to_flx = (dmaid == get_fromhost_dmaid()) ? true : false;
574 0 : bool fullmode = is_full_mode();
575 0 : u_int no_of_channels = get_number_of_channels();
576 0 : u_int egroups_per_chan = get_egroups_per_channel(is_to_flx);
577 0 : u_int epaths_per_egroup = get_epaths_per_egroup(is_to_flx);
578 :
579 : // TTCtoHost e-link = #Nchannels group #7 path #3 (RM4) or 0x600 (RM5)
580 : #if REGMAP_VERSION < 0x0500
581 : if( !is_to_flx && m_dev.m_bar2->CR_TTC_TOHOST.ENABLE) {
582 : #else
583 0 : if( !is_to_flx && m_dev.m_bar2->TTC_TOHOST_ENABLE && elink_is_in_dma(0x600, dmaid)) {
584 : #endif
585 0 : local_elink_t lid = TTC2HOST_LINK(no_of_channels);
586 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, lid, 0, m_vid, false, true);
587 0 : bool streams = 0;
588 0 : enabled_elinks.emplace_back(Elink{fid, lid, streams, elink_type_t::TTC, encoding_t::ENC_TTC});
589 0 : LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(TTC2H)", enabled_elinks.size(), lid, fid);
590 : }
591 :
592 : // IC, EC, AUX
593 0 : if( !fullmode ) {
594 0 : for( unsigned channel = 0; channel < no_of_channels; ++channel ) {
595 :
596 0 : local_elink_t ec_elink = get_ec_elink(is_to_flx, channel);
597 0 : bool ec_enabled = elink_is_ec_enabled(is_to_flx, channel) && elink_is_in_dma(ec_elink, dmaid);
598 :
599 0 : local_elink_t ic_elink = get_ic_elink(is_to_flx, channel);
600 0 : bool ic_enabled = elink_is_ic_enabled(is_to_flx, channel) && elink_is_in_dma(ic_elink, dmaid);
601 :
602 0 : local_elink_t aux_elink = get_aux_elink(is_to_flx, channel);
603 0 : bool aux_enabled = elink_is_aux_enabled(is_to_flx, channel) && elink_is_in_dma(aux_elink, dmaid);
604 0 : if( ec_enabled ){
605 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, ec_elink, 0, m_vid, is_to_flx, false);
606 0 : enabled_elinks.emplace_back(Elink{fid, ec_elink, false, elink_type_t::DCS, encoding_t::ENC_HDLC});
607 0 : LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(EC channel %d)", enabled_elinks.size(), ec_elink, fid, channel);
608 : }
609 0 : if( ic_enabled ){
610 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, ic_elink, 0, m_vid, is_to_flx, false);
611 0 : enabled_elinks.emplace_back(Elink{fid, ic_elink, false, elink_type_t::IC, encoding_t::ENC_HDLC});
612 0 : LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(IC channel %d)", enabled_elinks.size(), ic_elink, fid, channel);
613 : }
614 0 : if( m_firmware_type == FIRMW_LTDB && aux_enabled ) {
615 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, aux_elink, 0, m_vid, is_to_flx, false);
616 0 : enabled_elinks.emplace_back(Elink{fid, aux_elink, false, elink_type_t::DCS, encoding_t::ENC_HDLC});
617 0 : LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(AUX channel %d)", enabled_elinks.size(), aux_elink, fid, channel);
618 : }
619 : }
620 : }
621 :
622 0 : for( unsigned channel = 0; channel < no_of_channels; ++channel ) {
623 0 : for( unsigned egroup = 0; egroup < egroups_per_chan; ++egroup ) {
624 0 : for( unsigned epath = 0; epath < epaths_per_egroup; ++epath ) {
625 :
626 0 : local_elink_t elinknr = get_elink(channel, egroup, epath);
627 0 : bool enabled = elink_is_enabled(channel, egroup, epath, is_to_flx);
628 0 : bool in_enabled_dma = is_to_flx ? 1 : elink_is_in_dma(elinknr, dmaid);
629 :
630 0 : if( enabled && in_enabled_dma ) {
631 0 : bool streams = !is_to_flx && elink_has_stream_id(channel, egroup, epath);
632 0 : encoding_t enc = elink_get_encoding(channel, egroup, epath, is_to_flx);
633 0 : elink_type_t type = elink_type_t::NONE_ELINK_TYPE;
634 0 : if (enc == ENC_HDLC){
635 : type = elink_type_t::DCS;
636 : } else {
637 0 : type = elink_type_t::DAQ;
638 : }
639 :
640 0 : uint64_t fid = get_fid_from_ids(m_did, m_cid, elinknr, 0, m_vid, is_to_flx, false);
641 0 : enabled_elinks.emplace_back(Elink{fid, elinknr, streams, type, enc});
642 : LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(channel %d egroup %d epath %d) type %s, streams %c",
643 : enabled_elinks.size(), elinknr, fid, channel, egroup, epath,
644 : Device::get_elink_type_str(type).c_str(),
645 0 : streams ? 'Y' : 'N');
646 : } //if enabled
647 : } //epath
648 : } //egroup
649 : } //channel
650 :
651 : #if REGMAP_VERSION >= 0x0500
652 : // Add Broadcast Elinks
653 0 : if (is_to_flx) {
654 : // Calculate Broadcast Elinks
655 0 : uint64_t broadcast_elinks[MAX_BROADCAST_ELINKS] = {0};
656 0 : unsigned no_of_broadcast_elinks = get_broadcast_elinks(broadcast_elinks, no_of_channels);
657 0 : LOG_INFO("Adding %d broadcast elinks", no_of_broadcast_elinks);
658 0 : for( unsigned i=0; i < no_of_broadcast_elinks; ++i ) {
659 0 : bool streams = 0;
660 : //broadcast elinks use the same encoding as
661 : //elinks they broadcast into
662 0 : encoding_t enc = ENC_DIRECT;
663 0 : elink_type_t type = elink_type_t::DAQ;
664 0 : local_elink_t elinknr = static_cast<local_elink_t>(broadcast_elinks[i]);
665 0 : uint64_t fid = get_fid(0, elinknr, streams, m_vid, is_to_flx, 0);
666 0 : enabled_elinks.emplace_back(Elink{fid, elinknr, streams, type, enc});
667 0 : LOG_INFO("Broadcast for %8s \t%4d using \tE-Link %d:\t0x%02X\t0x%016lx\t(channel %d egroup %d epath %d)",
668 : Device::broadcast_type_str(elinknr).c_str(), Device::broadcast_for(elinknr), enabled_elinks.size(), elinknr, fid,
669 : Device::get_channel(elinknr), Device::get_egroup(elinknr), Device::get_epath(elinknr));
670 : }
671 : }
672 : #endif
673 : return enabled_elinks;
674 0 : }
675 :
676 0 : bool FlxDevice::dma_enabled(int dmaid)
677 : {
678 0 : return m_dev.dma_enabled(dmaid);
679 : }
680 :
681 0 : void FlxDevice::dma_to_host(DmaBuffer* buf, int dmaid)
682 : {
683 0 : m_dev.dma_stop(dmaid);
684 0 : m_dev.dma_to_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND);
685 0 : buf->pend = buf->paddr + buf->size;
686 0 : buf->pc_ptr = m_dev.dma_get_ptr(dmaid);
687 0 : }
688 :
689 :
690 0 : void FlxDevice::dma_from_host(DmaBuffer* buf, int dmaid)
691 : {
692 0 : m_dev.dma_from_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND);
693 0 : buf->pend = buf->paddr + buf->size;
694 0 : buf->pc_ptr = m_dev.dma_get_ptr(dmaid);
695 0 : }
696 :
697 :
698 0 : void FlxDevice::dma_from_host_trickle(DmaBuffer* buf, int dmaid, size_t config_size)
699 : {
700 0 : if(config_size > buf->size){
701 0 : LOG_ERR("Trickle config size %lu larger than buffer size %lu", config_size, buf->size);
702 0 : return;
703 : }
704 : // DMA buffer size must be a multiple of 32 bytes
705 0 : if(config_size % 32){
706 0 : config_size += 32 - (config_size % 32);
707 : }
708 : // The firmware will read the buffer up until the config_size
709 0 : m_dev.dma_from_host(dmaid, buf->paddr, config_size, FLX_DMA_WRAPAROUND);
710 : }
711 :
712 :
713 0 : void FlxDevice::dma_set_oneshot(DmaBuffer* buf, int dmaid, size_t config_size){
714 : // DMA buffer size must be a multiple of 32 bytes
715 0 : if(config_size % 32){
716 0 : config_size += 32 - (config_size % 32);
717 : }
718 : // The firmware will read the buffer up until the config_size
719 0 : m_dev.dma_from_host(dmaid, buf->paddr, config_size, 0 /*FLX_DMA_ONESHOT*/);
720 0 : }
721 :
722 0 : uint64_t FlxDevice::dma_get_fw_ptr(int dmaid)
723 : {
724 0 : return m_dev.dma_get_fw_ptr(dmaid);
725 : }
726 :
727 :
728 0 : uint64_t FlxDevice::dma_get_sw_ptr(int dmaid)
729 : {
730 0 : return m_dev.dma_get_ptr(dmaid);
731 : }
732 :
733 :
734 0 : void FlxDevice::dma_set_sw_ptr(int dmaid, uint64_t p_phys)
735 : {
736 0 : return m_dev.dma_set_ptr(dmaid, p_phys);
737 : }
738 :
739 :
740 0 : bool FlxDevice::dma_cmp_even_bits(int dmaid)
741 : {
742 0 : return m_dev.dma_cmp_even_bits(dmaid);
743 : }
744 :
745 :
746 0 : void FlxDevice::dma_stop(unsigned int dmaid)
747 : {
748 0 : m_dev.dma_stop(dmaid);
749 0 : }
750 :
751 0 : monitoring_data_t FlxDevice::hw_get_monitoring_data(unsigned int mon_mask)
752 : {
753 0 : monitoring_data_t data;
754 : //memset(&data, 0, sizeof(data));
755 0 : try {
756 0 : data = m_dev.get_monitoring_data(mon_mask);
757 0 : } catch(const FlxException & e) {
758 0 : LOG_WARN(e.what());
759 0 : }
760 0 : return data;
761 0 : }
|