diff options
Diffstat (limited to 'host/lib/usrp/x300/x300_impl.cpp')
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 50a7f3ded..d6e2a6fdc 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -18,6 +18,7 @@ #include "x300_impl.hpp" #include "x300_lvbitx.hpp" #include "x310_lvbitx.hpp" +#include "x300_mb_eeprom.hpp" #include "apply_corrections.hpp" #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> @@ -121,12 +122,16 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint) false /* Suppress timeout errors */ ); - if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process new_addr["fpga"] = get_fpga_option(zpu_ctrl); i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - i2c_iface::sptr eeprom16 = zpu_i2c->eeprom16(); - const mboard_eeprom_t mb_eeprom(*eeprom16, "X300"); + x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom(*eeprom_iface, "X300"); + if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) + { + // Skip device claimed by another process + continue; + } new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; switch (x300_impl::get_mb_type_from_eeprom(mb_eeprom)) { @@ -221,7 +226,6 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu //We don't put this zpu_ctrl in the registry because we need //a persistent niriok_proxy associated with the object } - if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process //Attempt to autodetect the FPGA type if (not hint.has_key("fpga")) { @@ -229,8 +233,13 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu } i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - i2c_iface::sptr eeprom16 = zpu_i2c->eeprom16(); - const mboard_eeprom_t mb_eeprom(*eeprom16, "X300"); + x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom(*eeprom_iface, "X300"); + if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) + { + // Skip device claimed by another process + continue; + } new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; } @@ -307,12 +316,7 @@ device_addrs_t x300_find(const device_addr_t &hint_) { UHD_MSG(error) << "X300 Network discovery unknown error " << std::endl; } - BOOST_FOREACH(const device_addr_t &reply_addr, reply_addrs) - { - device_addrs_t new_addrs = x300_find_with_addr(reply_addr); - addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end()); - } - return addrs; + return reply_addrs; } if (!hint.has_key("resource")) @@ -671,6 +675,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); } + // Claim device + if (not try_to_claim(mb.zpu_ctrl)) { + throw uhd::runtime_error("Failed to claim device"); + } mb.claimer_task = uhd::task::make(boost::bind(&x300_impl::claimer_loop, this, mb.zpu_ctrl)); //extract the FW path for the X300 @@ -726,7 +734,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) // setup the mboard eeprom //////////////////////////////////////////////////////////////////// UHD_MSG(status) << "Loading values from EEPROM..." << std::endl; - i2c_iface::sptr eeprom16 = mb.zpu_i2c->eeprom16(); + x300_mb_eeprom_iface::sptr eeprom16 = x300_mb_eeprom_iface::make(mb.zpu_ctrl, mb.zpu_i2c); if (dev_addr.has_key("blank_eeprom")) { UHD_MSG(warning) << "Obliterating the motherboard EEPROM..." << std::endl; @@ -1011,8 +1019,7 @@ x300_impl::~x300_impl(void) mb.claimer_task.reset(); { //Critical section boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), 0); - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0); + release(mb.zpu_ctrl); //If the process is killed, the entire registry will disappear so we //don't need to worry about unclean shutdowns here. get_pcie_zpu_iface_registry().pop(mb.get_pri_eth().addr); @@ -1465,24 +1472,58 @@ void x300_impl::set_mb_eeprom(i2c_iface::sptr i2c, const mboard_eeprom_t &mb_eep void x300_impl::claimer_loop(wb_iface::sptr iface) { - { //Critical section - boost::mutex::scoped_lock(claimer_mutex); - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), uint32_t(time(NULL))); - iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); - } + claim(iface); boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second } -bool x300_impl::is_claimed(wb_iface::sptr iface) +x300_impl::claim_status_t x300_impl::claim_status(wb_iface::sptr iface) { - boost::mutex::scoped_lock(claimer_mutex); - - //If timed out then device is definitely unclaimed - if (iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_STATUS)) == 0) - return false; + //If timed out, then device is definitely unclaimed + if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) + return UNCLAIMED; //otherwise check claim src to determine if another thread with the same src has claimed the device - return iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC)) != get_process_hash(); + uint32_t hash = iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC)); + return (hash == get_process_hash() ? CLAIMED_BY_US : CLAIMED_BY_OTHER); +} + +void x300_impl::claim(wb_iface::sptr iface) +{ + iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), uint32_t(time(NULL))); + iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); +} + +bool x300_impl::try_to_claim(wb_iface::sptr iface, long timeout) +{ + boost::system_time start_time = boost::get_system_time(); + while (1) + { + claim_status_t status = claim_status(iface); + if (status == UNCLAIMED) + { + claim(iface); + // It takes the claimer 10ms to update status, so wait 20ms before verifying claim + boost::this_thread::sleep(boost::posix_time::milliseconds(20)); + continue; + } + if (status == CLAIMED_BY_US) + { + break; + } + if (boost::get_system_time() - start_time > boost::posix_time::milliseconds(timeout)) + { + // Another process owns the device - give up + return false; + } + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + return true; +} + +void x300_impl::release(wb_iface::sptr iface) +{ + iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), 0); + iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), 0); } /*********************************************************************** |