.. _program_listing_file_device_flx.cpp: Program Listing for File device_flx.cpp ======================================= |exhale_lsh| :ref:`Return to documentation for file ` (``device_flx.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include "device.hpp" #include "flxcard/FlxException.h" #include "DFDebug/DFDebug.h" #include "felix/felix_fid.h" #include "regmap/regmap.h" #include "block.hpp" #include "log.hpp" FlxDevice::FlxDevice(Config& cfg, unsigned dev_no) : Device(dev_no, cfg.resource.vid, cfg.resource.did, cfg.get_device_cid(dev_no)) { } FlxDevice::FlxDevice(unsigned dev_no) : Device(dev_no, 1, 0, dev_no) { } int FlxDevice::open_device(u_int lock_mask) { u_int current_lock{0}; LOG_DBG("Initializing device %u asking for lock 0x%x", m_device_number, lock_mask); try { current_lock = m_dev.get_lock_mask(m_device_number); LOG_DBG("Device %d had locks 0x%x", m_device_number, current_lock); } catch(FlxException &ex) { LOG_ERR("Cannot get lock mask for device %u", m_device_number); LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str()); return ex.getErrorId(); } try { m_dev.card_open(m_device_number, lock_mask); } catch(FlxException &ex) { LOG_ERR("Could not open device %u", m_device_number); LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str()); return ex.getErrorId(); } // Clear various latched signals if (current_lock == 0) { m_dev.m_bar2->TTC_BUSY_CLEAR = 1; uint64_t c; c = m_dev.m_bar2->XOFF_FM_HIGH_THRESH.CROSS_LATCHED; m_dev.m_bar2->XOFF_FM_HIGH_THRESH.CROSS_LATCHED = c; c = m_dev.m_bar2->DMA_BUSY_STATUS.ENABLE; m_dev.m_bar2->DMA_BUSY_STATUS.ENABLE = c; c = m_dev.m_bar2->FM_BUSY_CHANNEL_STATUS.BUSY; m_dev.m_bar2->FM_BUSY_CHANNEL_STATUS.BUSY = c; c = m_dev.m_bar2->BUSY_MAIN_OUTPUT_FIFO_STATUS.HIGH_THRESH_CROSSED_LATCHED; m_dev.m_bar2->BUSY_MAIN_OUTPUT_FIFO_STATUS.HIGH_THRESH_CROSSED_LATCHED = c; } m_firmware_type = m_dev.firmware_type(); return 0; } void FlxDevice::close_device() { //stop all DMAs ? //flxcard->dma_stop(dmaid); LOG_DBG("Closing device %d", m_device_number); m_dev.card_close(); } bool FlxDevice::is_primary() { return not static_cast(m_dev.m_bar2->PCIE_ENDPOINT); } unsigned int FlxDevice::get_card_endpoints() { return m_dev.m_bar2->NUMBER_OF_PCIE_ENDPOINTS; } unsigned int FlxDevice::get_card_model() { return m_dev.m_bar2->CARD_TYPE; } u_int FlxDevice::get_regmap_version() { return m_dev.m_bar2->REG_MAP_VERSION; } u_int FlxDevice::get_number_of_channels() { return m_dev.m_bar2->NUM_OF_CHANNELS; } bool FlxDevice::get_wide_mode() { return (m_dev.m_bar2->WIDE_MODE == 1 ? true : false); } u_int FlxDevice::get_block_size() { return m_dev.m_bar2->BLOCKSIZE; } u_int FlxDevice::get_trailer_size() { u_int tsize = m_dev.m_bar2->CHUNK_TRAILER_32B == 1 ? 4 : 2; if( tsize != sizeof(subchunk_trailer_t) ){ throw std::runtime_error("SW/FW trailer size mismatch"); } return tsize; } flx_fromhost_format FlxDevice::get_fromhost_data_format() { #if REGMAP_VERSION < 0x0500 m_fromHostDataFormat = static_cast(FROMHOST_FORMAT_REGMAP4); #else m_fromHostDataFormat = static_cast(m_dev.m_bar2->FROMHOST_DATA_FORMAT); #endif return m_fromHostDataFormat; } flx_tohost_format FlxDevice::get_tohost_data_format() { #if REGMAP_VERSION < 0x0500 return TOHOST_SUBCHUNK_TRAILER; #else return static_cast(m_dev.m_bar2->TOHOST_DATA_FORMAT); #endif } int FlxDevice::get_fromhost_dmaid() { if (m_dev.m_bar2 == nullptr) { LOG_ERR("m_dev.m_bar2 is null"); return -1; } int dmaid = m_dev.m_bar2->GENERIC_CONSTANTS.DESCRIPTORS - 1; if (dmaid < 0) { LOG_ERR("Invalid ToFLx DMA ID %d", dmaid); } else { LOG_TRACE("ToFlx dmaid %d", dmaid); } return dmaid; } int FlxDevice::get_trickle_dmaid() { #if REGMAP_VERSION >= 0x0500 int dmaid = m_dev.m_bar2->GENERIC_CONSTANTS.TRICKLE_DESCRIPTOR_INDEX; //int trickle_offset = m_dev.m_bar2->GENERIC_CONSTANTS.TRICKLE_DESCRIPTOR_INDEX; //dmaid = dmaid + trickle_offset; if (dmaid < 0) { LOG_ERR("Invalid ToFLx DMA ID %d", dmaid); } LOG_TRACE("Trickle dmaid %d", dmaid); return dmaid; #endif return -1; } int FlxDevice::dma_max_tlp_bytes() { return m_dev.dma_max_tlp_bytes(); } void FlxDevice::set_register(const char *key, uint64_t value) { try { m_dev.cfg_set_option(key, value); } catch(FlxException &ex) { LOG_INFO("Register %s not available with current firmware version.", key); } } uint64_t FlxDevice::get_register(const char *key) { try { return m_dev.cfg_get_option(key); } catch(FlxException &ex) { LOG_INFO("Register %s not available with current firmware version.", key); return 0; } } bool FlxDevice::check_register(const char *key) { try { m_dev.cfg_get_option(key); return true; } catch(FlxException &ex) { LOG_INFO("Register %s not available with current firmware version.", key); return false; } } void FlxDevice::cancel_irq(int i) { try{ m_dev.irq_cancel(i); } catch(FlxException &ex) { LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str()); } } void FlxDevice::irq_wait(int i) { m_dev.irq_wait(i); } void FlxDevice::irq_enable(int i) { try{ m_dev.irq_enable(i); } catch(FlxException &ex) { LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str()); } } void FlxDevice::irq_disable(int i) { try{ m_dev.irq_disable(i); } catch(FlxException &ex) { LOG_ERR("%s", ex.errorString(ex.getErrorId()).c_str()); } } #if REGMAP_VERSION < 0x0500 encoding_t FlxDevice::elink_get_encoding(u_int channel, u_int egroup, u_int epath, bool is_to_flx) { if (!is_to_flx && (m_firmware_type == FIRMW_FULL || m_firmware_type == FIRMW_MROD)) { return ENC_8b10b; } else { int enc = 0; if (is_to_flx) { uint64_t modebits = m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_FROMHOST[egroup].FROMHOST.PATH_ENCODING; uint64_t mask = 0xF << 4*epath; // 4 bits per E-path enc = ((modebits & mask) >> 4*epath); } else { uint64_t modebits = m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_TOHOST[egroup].TOHOST.PATH_ENCODING; uint64_t mask = 0x3 << 2*epath; // 2 bits per E-path enc = ((modebits & mask) >> 2*epath); } if(enc < 0 || enc > 100){ LOG_ERR("Invalid encoding type %d \ for elink channel %u group %u, epath %u using DIRECT", enc, channel, egroup, epath); return ENC_DIRECT; } else { return static_cast(enc); } } } #else encoding_t FlxDevice::elink_get_encoding(u_int channel, u_int egroup, u_int epath, bool is_to_flx) { if (!is_to_flx && (m_firmware_type == FIRMW_FULL)) { return ENC_8b10b; } else if (!is_to_flx && (m_firmware_type == FIRMW_INTERLAKEN)){ return ENC_INTERLAKEN; } else { int enc = 0; if (is_to_flx) { uint64_t modebits = m_dev.m_bar2->ENCODING_EGROUP_CTRL_GEN[channel].ENCODING_EGROUP[egroup].ENCODING_EGROUP_CTRL.PATH_ENCODING; uint64_t mask = 0xF << 4*epath; // 4 bits per E-path enc = ((modebits & mask) >> 4*epath); } else { uint64_t modebits = m_dev.m_bar2->DECODING_EGROUP_CTRL_GEN[channel].DECODING_EGROUP[egroup].EGROUP.PATH_ENCODING; uint64_t mask = 0xF << 4*epath; // 4 bits per E-path enc = ((modebits & mask) >> 4*epath); } if(enc < 0 || enc > 100){ LOG_ERR("Invalid encoding type %d \ for elink channel %u group %u, epath %u using DIRECT", enc, channel, egroup, epath); return ENC_DIRECT; } else { return static_cast(enc); } } } #endif bool FlxDevice::elink_is_in_dma(local_elink_t elinknr, int dmaid) { #if REGMAP_VERSION < 0x0500 return true; #else bool is_elink_in_dma = false; if (dmaid == m_dev.m_bar2->GENERIC_CONSTANTS.FROMHOST_DESCRIPTOR_INDEX){ is_elink_in_dma = true; } else { m_dev.m_bar2->CRTOHOST_DMA_DESCRIPTOR_2.AXIS_ID = elinknr; unsigned int elink_dmaid = m_dev.m_bar2->CRTOHOST_DMA_DESCRIPTOR_2.DESCR_READ & 0xF; unsigned int max_id = m_dev.m_bar2->GENERIC_CONSTANTS.DESCRIPTORS - 1; if (elink_dmaid > max_id){ LOG_ERR("Invalid DMA ID %u for E-link %u (DMA ID [0, %u]). Discarded elink.", elink_dmaid, elinknr, max_id); } else if (elink_dmaid == static_cast(dmaid)){ is_elink_in_dma = true; } } return is_elink_in_dma; #endif } #if REGMAP_VERSION < 0x0500 bool FlxDevice::elink_is_enabled(u_int channel, u_int egroup, u_int epath, bool is_to_flx) { if (m_firmware_type == FIRMW_FULL) { return !is_to_flx && ((m_dev.m_bar2->CR_FM_PATH_ENA >> channel) & 1); } // MROD else if (m_firmware_type == FIRMW_MROD) { u_long eproc_ena = m_dev.m_bar2->MROD_EP0_CSMENABLE; return !is_to_flx && ((eproc_ena >> channel) & 1); } // GBT Mode else { u_long eproc_ena = is_to_flx ? m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_FROMHOST[egroup].FROMHOST.EPROC_ENA : m_dev.m_bar2->CR_GBT_CTRL[channel].EGROUP_TOHOST[egroup].TOHOST.EPROC_ENA; // Central Router documentation p. 13 switch (epath) { case 0: return ((eproc_ena >> 3) & 1) || ((eproc_ena >> 7) & 1); case 1: return ((eproc_ena >> 1) & 1) || ((eproc_ena >> 8) & 1); case 2: return ((eproc_ena >> 4) & 1) || ((eproc_ena >> 9) & 1); case 3: return ((eproc_ena >> 0) & 1) || ((eproc_ena >> 10) & 1); case 4: return ((eproc_ena >> 5) & 1) || ((eproc_ena >> 11) & 1); case 5: return ((eproc_ena >> 2) & 1) || ((eproc_ena >> 12) & 1); case 6: return ((eproc_ena >> 6) & 1) || ((eproc_ena >> 13) & 1); case 7: return ((eproc_ena >> 14) & 1); default: return false; } } return false; } #else bool FlxDevice::elink_is_enabled(u_int channel, u_int egroup, u_int epath, bool is_to_flx) { uint32_t enables_phase2; if( is_to_flx ) { enables_phase2 = (uint32_t) m_dev.m_bar2->ENCODING_EGROUP_CTRL_GEN[channel].ENCODING_EGROUP[egroup].ENCODING_EGROUP_CTRL.EPATH_ENA; } else { enables_phase2 = (uint32_t) m_dev.m_bar2->DECODING_EGROUP_CTRL_GEN[channel].DECODING_EGROUP[egroup].EGROUP.EPATH_ENA; } return (enables_phase2 >> epath) & 0x01; } #endif uint64_t FlxDevice::get_broadcast_enable_gen(u_int channel) { #if REGMAP_VERSION >= 0x0500 return m_dev.m_bar2->BROADCAST_ENABLE_GEN[channel].BROADCAST_ENABLE; #else return 0; #endif } local_elink_t FlxDevice::get_ec_elink(bool is_to_flx, u_int channel) { std::pair ec_indices = m_dev.ec_elink_indices(); if( is_to_flx ) { return ((channel<<6) + ec_indices.second); } else { return ((channel<<6) + ec_indices.first); } } local_elink_t FlxDevice::get_ic_elink(bool is_to_flx, u_int channel) { std::pair ic_indices = m_dev.ic_elink_indices(); if( is_to_flx ) { return ((channel<<6) + ic_indices.second); } else { return ((channel<<6) + ic_indices.first); } } local_elink_t FlxDevice::get_aux_elink(bool is_to_flx, u_int channel) { local_elink_t ic_elink = get_ic_elink(is_to_flx, channel); #if REGMAP_VERSION < 0x0500 return (ic_elink - 1); #else return (ic_elink + 1); // Not (yet) defined #endif } bool FlxDevice::elink_is_ec_enabled(bool is_to_flx, u_int channel) { #if REGMAP_VERSION < 0x0500 if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.ENABLE); } #else if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.EC_ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.EC_ENABLE); } #endif } bool FlxDevice::elink_is_ic_enabled(bool is_to_flx, u_int channel) { #if REGMAP_VERSION < 0x0500 if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.IC_ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.IC_ENABLE); } #else if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.IC_ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.IC_ENABLE); } #endif } bool FlxDevice::elink_is_aux_enabled(bool is_to_flx, u_int channel) { #if REGMAP_VERSION < 0x0500 if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_FROMHOST.SCA_AUX_ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_CTRL[channel].EC_TOHOST.SCA_AUX_ENABLE); } #else if( is_to_flx ) { return(m_dev.m_bar2->MINI_EGROUP_FROMHOST_GEN[channel].MINI_EGROUP_FROMHOST.AUX_ENABLE); } else { return(m_dev.m_bar2->MINI_EGROUP_TOHOST_GEN[channel].MINI_EGROUP_TOHOST.AUX_ENABLE); } #endif } bool FlxDevice::elink_has_stream_id(u_int channel, u_int egroup, u_int epath) { if(channel > get_number_of_channels()){ LOG_ERR("Checking stream status on invalid channel %u", channel); return false; } u_long enable = 0; #if REGMAP_VERSION < 0x0500 switch (egroup) { case 0: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP0; break; case 1: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP1; break; case 2: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP2; break; case 3: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP3; break; case 4: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP4; break; case 5: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP5; break; case 6: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].TOHOST.EGROUP6; break; default: LOG_ERR("Checking stream status on invalid egroup %u.", egroup); break; } #else switch (egroup) { case 0: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP0; break; case 1: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP1; break; case 2: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP2; break; case 3: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP3; break; case 4: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP4; break; case 5: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP5; break; case 6: enable = m_dev.m_bar2->PATH_HAS_STREAM_ID[channel].HAS_STREAM_ID.EGROUP6; break; default: LOG_ERR("Checking stream status on invalid egroup %u.", egroup); break; } #endif return static_cast( (enable >> epath) & 1); } std::vector FlxDevice::read_enabled_elinks(int dmaid) { std::vector enabled_elinks; // If Trickle mode is active, only the Trickle E-link is enabled and returned bool is_trickle = (dmaid == get_trickle_dmaid()) ? true : false; if (is_trickle){ local_elink_t lid = 0xffff; uint64_t fid = get_fid_from_ids(m_did, m_cid, lid, 0, m_vid, true, true); enabled_elinks.emplace_back(Elink{fid, lid, 0, elink_type_t::DAQ, encoding_t::ENC_8b10b}); return enabled_elinks; } bool is_to_flx = (dmaid == get_fromhost_dmaid()) ? true : false; bool fullmode = is_full_mode(); u_int no_of_channels = get_number_of_channels(); u_int egroups_per_chan = get_egroups_per_channel(is_to_flx); u_int epaths_per_egroup = get_epaths_per_egroup(is_to_flx); // TTCtoHost e-link = #Nchannels group #7 path #3 (RM4) or 0x600 (RM5) #if REGMAP_VERSION < 0x0500 if( !is_to_flx && m_dev.m_bar2->CR_TTC_TOHOST.ENABLE) { #else if( !is_to_flx && m_dev.m_bar2->TTC_TOHOST_ENABLE && elink_is_in_dma(0x600, dmaid)) { #endif local_elink_t lid = TTC2HOST_LINK(no_of_channels); uint64_t fid = get_fid_from_ids(m_did, m_cid, lid, 0, m_vid, false, true); bool streams = 0; enabled_elinks.emplace_back(Elink{fid, lid, streams, elink_type_t::TTC, encoding_t::ENC_TTC}); LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(TTC2H)", enabled_elinks.size(), lid, fid); } // IC, EC, AUX if( !fullmode ) { for( unsigned channel = 0; channel < no_of_channels; ++channel ) { local_elink_t ec_elink = get_ec_elink(is_to_flx, channel); bool ec_enabled = elink_is_ec_enabled(is_to_flx, channel) && elink_is_in_dma(ec_elink, dmaid); local_elink_t ic_elink = get_ic_elink(is_to_flx, channel); bool ic_enabled = elink_is_ic_enabled(is_to_flx, channel) && elink_is_in_dma(ic_elink, dmaid); local_elink_t aux_elink = get_aux_elink(is_to_flx, channel); bool aux_enabled = elink_is_aux_enabled(is_to_flx, channel) && elink_is_in_dma(aux_elink, dmaid); if( ec_enabled ){ uint64_t fid = get_fid_from_ids(m_did, m_cid, ec_elink, 0, m_vid, is_to_flx, false); enabled_elinks.emplace_back(Elink{fid, ec_elink, false, elink_type_t::DCS, encoding_t::ENC_HDLC}); LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(EC channel %d)", enabled_elinks.size(), ec_elink, fid, channel); } if( ic_enabled ){ uint64_t fid = get_fid_from_ids(m_did, m_cid, ic_elink, 0, m_vid, is_to_flx, false); enabled_elinks.emplace_back(Elink{fid, ic_elink, false, elink_type_t::IC, encoding_t::ENC_HDLC}); LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(IC channel %d)", enabled_elinks.size(), ic_elink, fid, channel); } if( m_firmware_type == FIRMW_LTDB && aux_enabled ) { uint64_t fid = get_fid_from_ids(m_did, m_cid, aux_elink, 0, m_vid, is_to_flx, false); enabled_elinks.emplace_back(Elink{fid, aux_elink, false, elink_type_t::DCS, encoding_t::ENC_HDLC}); LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(AUX channel %d)", enabled_elinks.size(), aux_elink, fid, channel); } } } for( unsigned channel = 0; channel < no_of_channels; ++channel ) { for( unsigned egroup = 0; egroup < egroups_per_chan; ++egroup ) { for( unsigned epath = 0; epath < epaths_per_egroup; ++epath ) { local_elink_t elinknr = get_elink(channel, egroup, epath); bool enabled = elink_is_enabled(channel, egroup, epath, is_to_flx); bool in_enabled_dma = is_to_flx ? 1 : elink_is_in_dma(elinknr, dmaid); if( enabled && in_enabled_dma ) { bool streams = !is_to_flx && elink_has_stream_id(channel, egroup, epath); encoding_t enc = elink_get_encoding(channel, egroup, epath, is_to_flx); elink_type_t type = elink_type_t::NONE_ELINK_TYPE; if (enc == ENC_HDLC){ type = elink_type_t::DCS; } else { type = elink_type_t::DAQ; } uint64_t fid = get_fid_from_ids(m_did, m_cid, elinknr, 0, m_vid, is_to_flx, false); enabled_elinks.emplace_back(Elink{fid, elinknr, streams, type, enc}); LOG_TRACE("E-Link %d:\t0x%02X\t0x%016lx\t(channel %d egroup %d epath %d) type %s, streams %c", enabled_elinks.size(), elinknr, fid, channel, egroup, epath, Device::get_elink_type_str(type).c_str(), streams ? 'Y' : 'N'); } //if enabled } //epath } //egroup } //channel #if REGMAP_VERSION >= 0x0500 // Add Broadcast Elinks if (is_to_flx) { // Calculate Broadcast Elinks uint64_t broadcast_elinks[MAX_BROADCAST_ELINKS] = {0}; unsigned no_of_broadcast_elinks = get_broadcast_elinks(broadcast_elinks, no_of_channels); LOG_INFO("Adding %d broadcast elinks", no_of_broadcast_elinks); for( unsigned i=0; i < no_of_broadcast_elinks; ++i ) { bool streams = 0; //broadcast elinks use the same encoding as //elinks they broadcast into encoding_t enc = ENC_DIRECT; elink_type_t type = elink_type_t::DAQ; local_elink_t elinknr = static_cast(broadcast_elinks[i]); uint64_t fid = get_fid(0, elinknr, streams, m_vid, is_to_flx, 0); enabled_elinks.emplace_back(Elink{fid, elinknr, streams, type, enc}); LOG_INFO("Broadcast for %8s \t%4d using \tE-Link %d:\t0x%02X\t0x%016lx\t(channel %d egroup %d epath %d)", Device::broadcast_type_str(elinknr).c_str(), Device::broadcast_for(elinknr), enabled_elinks.size(), elinknr, fid, Device::get_channel(elinknr), Device::get_egroup(elinknr), Device::get_epath(elinknr)); } } #endif return enabled_elinks; } bool FlxDevice::dma_enabled(int dmaid) { return m_dev.dma_enabled(dmaid); } void FlxDevice::dma_to_host(DmaBuffer* buf, int dmaid) { m_dev.dma_stop(dmaid); m_dev.dma_to_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND); buf->pend = buf->paddr + buf->size; buf->pc_ptr = m_dev.dma_get_ptr(dmaid); } void FlxDevice::dma_from_host(DmaBuffer* buf, int dmaid) { m_dev.dma_from_host(dmaid, buf->paddr, buf->size, FLX_DMA_WRAPAROUND); buf->pend = buf->paddr + buf->size; buf->pc_ptr = m_dev.dma_get_ptr(dmaid); } void FlxDevice::dma_from_host_trickle(DmaBuffer* buf, int dmaid, size_t config_size) { if(config_size > buf->size){ LOG_ERR("Trickle config size %lu larger than buffer size %lu", config_size, buf->size); return; } // DMA buffer size must be a multiple of 32 bytes if(config_size % 32){ config_size += 32 - (config_size % 32); } // The firmware will read the buffer up until the config_size m_dev.dma_from_host(dmaid, buf->paddr, config_size, FLX_DMA_WRAPAROUND); } void FlxDevice::dma_set_oneshot(DmaBuffer* buf, int dmaid, size_t config_size){ // DMA buffer size must be a multiple of 32 bytes if(config_size % 32){ config_size += 32 - (config_size % 32); } // The firmware will read the buffer up until the config_size m_dev.dma_from_host(dmaid, buf->paddr, config_size, 0 /*FLX_DMA_ONESHOT*/); } uint64_t FlxDevice::dma_get_fw_ptr(int dmaid) { return m_dev.dma_get_fw_ptr(dmaid); } uint64_t FlxDevice::dma_get_sw_ptr(int dmaid) { return m_dev.dma_get_ptr(dmaid); } void FlxDevice::dma_set_sw_ptr(int dmaid, uint64_t p_phys) { return m_dev.dma_set_ptr(dmaid, p_phys); } bool FlxDevice::dma_cmp_even_bits(int dmaid) { return m_dev.dma_cmp_even_bits(dmaid); } void FlxDevice::dma_stop(unsigned int dmaid) { m_dev.dma_stop(dmaid); } monitoring_data_t FlxDevice::hw_get_monitoring_data(unsigned int mon_mask) { monitoring_data_t data; //memset(&data, 0, sizeof(data)); try { data = m_dev.get_monitoring_data(mon_mask); } catch(const FlxException & e) { LOG_WARN(e.what()); } return data; }