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