Program Listing for File device.cpp
↰ Return to documentation for file (device.cpp
)
#include <algorithm>
#include "device.hpp"
#include "log.hpp"
#define BROADCAST_NONE 0
#define BROADCAST_ALL 1
#define BROADCAST_CHANNEL 2
#define BROADCAST_ELINK 3
#define MAX_BROADCAST_CHANNELS (32)
#define MAX_BROADCAST_ELINKS (1 + 32 + 64)
Device::Device(unsigned dev_no, uint8_t vid, uint16_t did, uint16_t cid)
: m_device_number(dev_no), m_vid(vid), m_did(did), m_cid(cid) {}
bool Device::has_wrong_rm() {
unsigned int regmap = get_regmap_version();
#if REGMAP_VERSION < 0x0500
return ((regmap < 0x0400) || (regmap >= 0x0500));
#else
return ((regmap < 0x0500) || (regmap >= 0x0600));
#endif
}
bool Device::is_full_mode() {
return (m_firmware_type == FIRMW_FULL or m_firmware_type == FIRMW_MROD or m_firmware_type == FIRMW_INTERLAKEN);
}
bool Device::is_lpgbt_mode() {
u_int mode = m_firmware_type;
return (mode == FIRMW_PIXEL or mode == FIRMW_STRIP or mode == FIRMW_LPGBT or mode == FIRMW_HGTD_LUMI or mode == FIRMW_BCM_PRIME);
}
uint64_t Device::get_elink(u_int channel, u_int egroup, u_int epath) {
bool lpgbt = this->is_lpgbt_mode();
int egroup_shift = (lpgbt) ? 2 : 3;
return (channel << 6) + (egroup << egroup_shift) + epath;
}
uint32_t Device::get_channel(uint32_t elink) {
return (elink >> 6);
}
uint32_t Device::get_egroup(uint32_t elink) {
bool lpgbt = this->is_lpgbt_mode();
int egroup_shift = (lpgbt) ? 2 : 3;
return (elink & 0x3f) >> egroup_shift;
}
uint32_t Device::get_epath(uint32_t elink) {
bool lpgbt = this->is_lpgbt_mode();
int egroup_shift = (lpgbt) ? 2 : 3;
return egroup_shift == 2 ? elink & 0x03 : elink & 0x07;
}
u_int Device::get_egroups_per_channel(u_int is_to_flx) {
u_int egroups_per_chan;
if( is_to_flx == 0 ) {
// tohost
if( this->is_full_mode() )
egroups_per_chan = 1;
else if( this->is_lpgbt_mode() )
egroups_per_chan = 7;
else if( this->get_wide_mode() )
egroups_per_chan = 7;
else
egroups_per_chan = 5;
} else {
// toflx
if( this->is_full_mode() )
egroups_per_chan = 5;
else if( this->is_lpgbt_mode() )
egroups_per_chan = 4;
else if( this->get_wide_mode() )
egroups_per_chan = 3;
else
egroups_per_chan = 5;
}
return egroups_per_chan;
}
u_int Device::get_epaths_per_egroup(u_int is_to_flx) {
int epaths_per_egroup;
if( is_to_flx == 0 ) {
// tohost
if( this->is_full_mode() )
epaths_per_egroup = 1;
else if( this->is_lpgbt_mode() )
epaths_per_egroup = 4;
else if( this->get_wide_mode())
epaths_per_egroup = 8;
else
epaths_per_egroup = 8;
} else {
// toflx
if( this->is_full_mode() )
epaths_per_egroup = 8;
else if( this->is_lpgbt_mode() and this->get_firmware_type() != FIRMW_STRIP )
epaths_per_egroup = 4;
else if( this->is_lpgbt_mode() and this->get_firmware_type() == FIRMW_STRIP )
epaths_per_egroup = 5;
else if( this->get_wide_mode() )
epaths_per_egroup = 8;
else
epaths_per_egroup = 8;
}
return epaths_per_egroup;
}
u_int Device::get_ctrl_elinks_per_channel() {
if( m_firmware_type == FIRMW_LTDB )
return 3; // IC, EC, AUX
else
return 2; // IC, EC
}
const std::string Device::get_elink_type_str(elink_type_t encoding) {
switch(encoding) {
case NONE_ELINK_TYPE: return "NONE_ELINK_TYPE";
case DAQ: return "DAQ";
case TTC: return "TTC";
case DCS: return "DCS";
case IC: return "IC";
default: return "UNKNOWN";
}
}
std::vector<Elink> Device::get_enabled_elinks_of_type(int dmaid, elink_type_t t)
{
auto all_elinks = read_enabled_elinks(dmaid);
std::vector<Elink> ret;
std::copy_if(all_elinks.begin(), all_elinks.end(), std::back_inserter(ret), [t](Elink e) { return e.type == t; });
// for (auto& e : all_elinks){
// if ( e.type == t ){
// ret.emplace_back(e);
// }
// }
return ret;
}
unsigned int Device::make_dma_lock_mask(const std::vector<int>& dmaids)
{
unsigned int lock_mask(LOCK_NONE);
for(int id : dmaids){
lock_mask |= LOCK_DMA(id);
}
return lock_mask;
}
int64_t Device::broadcast_for(uint64_t elink) {
if ((elink & 0x7ff) == 0x7ff) return -1;
if ((elink & 0x3f) == 0x3f) return (elink >> 6) & 0x1f;
if ((elink & (0x1f << 6)) == (0x1f << 6)) return elink & 0x3f;
return elink;
}
int Device::broadcast_type(uint64_t elink) {
if ((elink & 0x7ff) == 0x7ff) return BROADCAST_ALL;
if ((elink & 0x3f) == 0x3f) return BROADCAST_CHANNEL;
if ((elink & (0x1f << 6)) == (0x1f << 6)) return BROADCAST_ELINK;
return BROADCAST_NONE;
}
const std::string Device::broadcast_type_str(uint64_t elink) {
switch(Device::broadcast_type(elink)) {
case BROADCAST_NONE:
return "None";
case BROADCAST_ALL:
return "All";
case BROADCAST_CHANNEL:
return "Channel";
case BROADCAST_ELINK:
return "E-Link";
default:
return "Unknown";
}
}
// Note allow an array of MAX_BROADCAST_ELINKS for bc_elinks.
unsigned Device::broadcast_elinks(uint64_t broadcast_elinks[], const uint64_t broadcast_enable_registers[], uint32_t num_of_channels) {
unsigned no_of_broadcast_elinks = 0;
int broadcast_to_all = 0;
int broadcast_to_elink[64] = {0};
for (uint32_t channel = 0; channel < num_of_channels; channel++) {
if (broadcast_enable_registers[channel] > 0) {
// Save Broadcast to All
broadcast_to_all = 1;
// Add Broadcast to all e-links of one link
broadcast_elinks[no_of_broadcast_elinks] = ((channel << 6) | 0x03F);
// LOG_INFO("Broadcast for link %d to 0x%x", link, broadcast_elinks[no_of_broadcast_elinks]);
no_of_broadcast_elinks++;
// Save Broadcast to 1 e-link of all links
for (uint32_t elink = 0; elink < 64; elink++) {
if (broadcast_enable_registers[channel] & (1UL << elink)) {
// LOG_INFO("Adding for link %d, elink %d, based on 0x%x and mask 0x%x", link, elink, broadcast_enable_registers[link], (1 << elink));
broadcast_to_elink[elink] = 1;
}
}
}
}
// Add Broadcast to 1 e-link of all links
for (uint32_t elink = 0; elink < 64; elink++) {
if (broadcast_to_elink[elink]) {
broadcast_elinks[no_of_broadcast_elinks] = ((0x1F << 6) | elink);
//LOG_INFO("Broadcast for elink 0x%x to 0x%x", elink, broadcast_elinks[no_of_broadcast_elinks]);
no_of_broadcast_elinks++;
}
}
// Add Broadcast to All if needed
if (broadcast_to_all) {
broadcast_elinks[no_of_broadcast_elinks] = 0x7ff;
//LOG_INFO("Broadcast all for links to 0x%x", broadcast_elinks[no_of_broadcast_elinks]);
no_of_broadcast_elinks++;
}
return no_of_broadcast_elinks;
}
u_int Device::get_broadcast_elinks(uint64_t broadcast_elinks[], uint32_t num_of_channels) {
uint64_t broadcast_enable_registers[MAX_BROADCAST_CHANNELS];
for( unsigned channel=0; channel < num_of_channels; ++channel ) {
broadcast_enable_registers[channel] = get_broadcast_enable_gen(channel);
}
unsigned no_of_broadcast_elinks = Device::broadcast_elinks(broadcast_elinks, broadcast_enable_registers, num_of_channels);
LOG_INFO("Deduced %d broadcast elinks", no_of_broadcast_elinks);
return no_of_broadcast_elinks;
}