LCOV - code coverage report
Current view: top level - src - device_flx.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 334 0.0 %
Date: 2025-11-14 15:45:10 Functions: 0 47 0.0 %

          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 : }

Generated by: LCOV version 1.0