aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/x300/x300/x300_defs.h10
-rw-r--r--host/include/uhd/transport/nirio/niriok_proxy.h2
-rw-r--r--host/include/uhd/transport/nirio/niusrprio_session.h71
-rw-r--r--host/lib/transport/nirio/niriok_proxy.cpp10
-rw-r--r--host/lib/transport/nirio/niusrprio_session.cpp57
-rw-r--r--host/lib/transport/nirio_zero_copy.cpp64
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp54
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp3
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp10
10 files changed, 220 insertions, 63 deletions
diff --git a/firmware/x300/x300/x300_defs.h b/firmware/x300/x300/x300_defs.h
index 02c3d4808..65c5d5a23 100644
--- a/firmware/x300/x300/x300_defs.h
+++ b/firmware/x300/x300/x300_defs.h
@@ -1,10 +1,10 @@
-// Copyright 2012 Ettus Research LLC
+// Copyright 2014 Ettus Research LLC
-#ifndef INCLUDED_B250_DEFS_H
-#define INCLUDED_B250_DEFS_H
+#ifndef INCLUDED_X300_DEFS_H
+#define INCLUDED_X300_DEFS_H
-#define CPU_CLOCK 175000000
+#define CPU_CLOCK 166666667
#define MAIN_RAM_BASE 0x0000
#define PKT_RAM0_BASE 0x8000
#define XGE0_BASE 0xC000
@@ -72,4 +72,4 @@ static const int BL_DATA = 1;
#define ETH_FRAMER_DST_UDP_MAC 6
#define ETH_FRAMER_DST_MAC_LO 7
-#endif /* INCLUDED_B250_DEFS_H */
+#endif /* INCLUDED_X300_DEFS_H */
diff --git a/host/include/uhd/transport/nirio/niriok_proxy.h b/host/include/uhd/transport/nirio/niriok_proxy.h
index a6b6183d1..ca6a4ba02 100644
--- a/host/include/uhd/transport/nirio/niriok_proxy.h
+++ b/host/include/uhd/transport/nirio/niriok_proxy.h
@@ -126,6 +126,8 @@ namespace uhd { namespace niusrprio
nirio_status unmap_fifo_memory(
nirio_driver_iface::rio_mmap_t& map);
+ nirio_status stop_all_fifos();
+
nirio_quirks& get_rio_quirks() {
return _rio_quirks;
}
diff --git a/host/include/uhd/transport/nirio/niusrprio_session.h b/host/include/uhd/transport/nirio/niusrprio_session.h
index c9a61ae76..c84bc75d0 100644
--- a/host/include/uhd/transport/nirio/niusrprio_session.h
+++ b/host/include/uhd/transport/nirio/niusrprio_session.h
@@ -37,31 +37,31 @@ public:
typedef uhd::usrprio_rpc::usrprio_device_info device_info;
typedef uhd::usrprio_rpc::usrprio_device_info_vtr device_info_vtr;
- static nirio_status enumerate(
+ static nirio_status enumerate(
const std::string& rpc_port_name,
device_info_vtr& device_info_vtr);
- niusrprio_session(
+ niusrprio_session(
const std::string& resource_name,
const std::string& port_name);
- virtual ~niusrprio_session();
+ virtual ~niusrprio_session();
- nirio_status open(
+ nirio_status open(
nifpga_lvbitx::sptr lvbitx,
bool force_download = false);
- void close(bool skip_reset = false);
+ void close(bool skip_reset = false);
- nirio_status reset();
+ nirio_status reset();
- template<typename data_t>
- nirio_status create_tx_fifo(
- const char* fifo_name,
- boost::shared_ptr< nirio_fifo<data_t> >& fifo)
- {
+ template<typename data_t>
+ nirio_status create_tx_fifo(
+ const char* fifo_name,
+ boost::shared_ptr< nirio_fifo<data_t> >& fifo)
+ {
if (!_session_open) return NiRio_Status_ResourceNotInitialized;
return _resource_manager.create_tx_fifo(fifo_name, fifo);
- }
+ }
template<typename data_t>
nirio_status create_tx_fifo(
@@ -73,13 +73,13 @@ public:
}
template<typename data_t>
- nirio_status create_rx_fifo(
- const char* fifo_name,
- boost::shared_ptr< nirio_fifo<data_t> >& fifo)
- {
+ nirio_status create_rx_fifo(
+ const char* fifo_name,
+ boost::shared_ptr< nirio_fifo<data_t> >& fifo)
+ {
if (!_session_open) return NiRio_Status_ResourceNotInitialized;
return _resource_manager.create_rx_fifo(fifo_name, fifo);
- }
+ }
template<typename data_t>
nirio_status create_rx_fifo(
@@ -90,9 +90,9 @@ public:
return create_rx_fifo(_lvbitx->get_input_fifo_names()[fifo_instance], fifo);
}
- niriok_proxy& get_kernel_proxy() {
- return _riok_proxy;
- }
+ niriok_proxy& get_kernel_proxy() {
+ return _riok_proxy;
+ }
nirio_status download_bitstream_to_flash(const std::string& bitstream_path);
@@ -102,21 +102,22 @@ public:
const std::string& rpc_port_name);
private:
- nirio_status _verify_signature();
- std::string _read_bitstream_checksum();
- nirio_status _write_bitstream_checksum(const std::string& checksum);
- nirio_status _wait_for_device_available();
-
- std::string _resource_name;
- nifpga_lvbitx::sptr _lvbitx;
- std::string _interface_path;
- bool _session_open;
- niriok_proxy _riok_proxy;
- nirio_resource_manager _resource_manager;
- usrprio_rpc::usrprio_rpc_client _rpc_client;
- boost::recursive_mutex _session_mutex;
-
- static const uint32_t SESSION_LOCK_TIMEOUT_IN_MS = 3000;
+ nirio_status _verify_signature();
+ std::string _read_bitstream_checksum();
+ nirio_status _write_bitstream_checksum(const std::string& checksum);
+ nirio_status _ensure_fpga_ready();
+
+ std::string _resource_name;
+ nifpga_lvbitx::sptr _lvbitx;
+ std::string _interface_path;
+ bool _session_open;
+ niriok_proxy _riok_proxy;
+ nirio_resource_manager _resource_manager;
+ usrprio_rpc::usrprio_rpc_client _rpc_client;
+ boost::recursive_mutex _session_mutex;
+
+ static const uint32_t FPGA_READY_TIMEOUT_IN_MS = 1000;
+ static const uint32_t SESSION_LOCK_TIMEOUT_IN_MS = 3000;
static const uint32_t SESSION_LOCK_RETRY_INT_IN_MS = 500;
};
diff --git a/host/lib/transport/nirio/niriok_proxy.cpp b/host/lib/transport/nirio/niriok_proxy.cpp
index 031623c9a..ac8faf0a4 100644
--- a/host/lib/transport/nirio/niriok_proxy.cpp
+++ b/host/lib/transport/nirio/niriok_proxy.cpp
@@ -293,6 +293,16 @@ namespace uhd { namespace niusrprio
{
return nirio_driver_iface::rio_munmap(map);
}
+
+ nirio_status niriok_proxy::stop_all_fifos()
+ {
+ nirio_driver_iface::nirio_syncop_in_params_t in = {};
+ nirio_driver_iface::nirio_syncop_out_params_t out = {};
+
+ in.function = nirio_driver_iface::NIRIO_FUNC::FIFO_STOP_ALL;
+
+ return sync_operation(&in, sizeof(in), &out, sizeof(out));
+ }
}}
#ifdef __GNUC__
diff --git a/host/lib/transport/nirio/niusrprio_session.cpp b/host/lib/transport/nirio/niusrprio_session.cpp
index a07bc4fdf..97d764736 100644
--- a/host/lib/transport/nirio/niusrprio_session.cpp
+++ b/host/lib/transport/nirio/niusrprio_session.cpp
@@ -77,6 +77,8 @@ nirio_status niusrprio_session::open(
std::string lvbitx_checksum(_lvbitx->get_bitstream_checksum());
boost::uint16_t download_fpga = (force_download || (_read_bitstream_checksum() != lvbitx_checksum)) ? 1 : 0;
+ nirio_status_chain(_ensure_fpga_ready(), status);
+
nirio_status_chain(_rpc_client.niusrprio_open_session(
_resource_name, bitfile_path, signature, download_fpga), status);
_session_open = nirio_status_not_fatal(status);
@@ -196,4 +198,59 @@ nirio_status niusrprio_session::_write_bitstream_checksum(const std::string& che
return status;
}
+nirio_status niusrprio_session::_ensure_fpga_ready()
+{
+ nirio_status status = NiRio_Status_Success;
+ niriok_scoped_addr_space(_riok_proxy, BUS_INTERFACE, status);
+
+ //Verify that the Ettus FPGA loaded in the device. This may not be true if the
+ //user is switching to UHD after using LabVIEW FPGA. In that case skip this check.
+ boost::uint32_t pcie_fpga_signature = 0;
+ nirio_status_chain(_riok_proxy.peek(FPGA_PCIE_SIG_REG, pcie_fpga_signature), status);
+ //@TODO: Remove X300 specific constants for future products
+ if (pcie_fpga_signature != FPGA_X3xx_SIG_VALUE) {
+ return status;
+ }
+
+ boost::uint32_t reg_data = 0xffffffff;
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK))
+ {
+ //In case this session was re-initialized *immediately* after the previous
+ //there is a small chance that the server is still finishing up cleaning up
+ //the DMA FIFOs. We currently don't have any feedback from the driver regarding
+ //this state so just wait.
+ boost::this_thread::sleep(boost::posix_time::milliseconds(FPGA_READY_TIMEOUT_IN_MS));
+
+ //Disable all FIFOs in the FPGA
+ for (size_t i = 0; i < _lvbitx->get_input_fifo_count(); i++) {
+ _riok_proxy.poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED);
+ }
+ for (size_t i = 0; i < _lvbitx->get_output_fifo_count(); i++) {
+ _riok_proxy.poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, i), DMA_CTRL_DISABLED);
+ }
+
+ //Disable all FIFOs in the kernel driver
+ _riok_proxy.stop_all_fifos();
+
+ boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time();
+ boost::posix_time::time_duration elapsed;
+ do {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //Avoid flooding the bus
+ elapsed = boost::posix_time::microsec_clock::local_time() - start_time;
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK) &&
+ elapsed.total_milliseconds() < FPGA_READY_TIMEOUT_IN_MS);
+
+ nirio_status_chain(_riok_proxy.peek(FPGA_STATUS_REG, reg_data), status);
+ if (nirio_status_not_fatal(status) && (reg_data & FPGA_STATUS_DMA_ACTIVE_MASK)) {
+ return NiRio_Status_FifoReserved;
+ }
+ }
+
+ return status;
+}
+
}}
diff --git a/host/lib/transport/nirio_zero_copy.cpp b/host/lib/transport/nirio_zero_copy.cpp
index c3c8a9368..3bb822720 100644
--- a/host/lib/transport/nirio_zero_copy.cpp
+++ b/host/lib/transport/nirio_zero_copy.cpp
@@ -24,6 +24,7 @@
#include <uhd/utils/atomic.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp> //sleep
#include <vector>
#include <algorithm> // std::max
@@ -143,6 +144,12 @@ public:
nirio_status status = 0;
size_t actual_depth = 0, actual_size = 0;
+ //Disable DMA streams in case last shutdown was unclean (cleanup, so don't status chain)
+ _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+ _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+
+ _wait_until_stream_ready();
+
//Configure frame width
nirio_status_chain(
_proxy().poke(PCIE_TX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance),
@@ -152,14 +159,14 @@ public:
_proxy().poke(PCIE_RX_DMA_REG(DMA_FRAME_SIZE_REG, _fifo_instance),
static_cast<uint32_t>(_xport_params.recv_frame_size/sizeof(fifo_data_t))),
status);
- //Config 32-bit word flipping and Reset DMA streams
+ //Config 32-bit word flipping and enable DMA streams
nirio_status_chain(
_proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
- DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET),
+ DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED),
status);
nirio_status_chain(
_proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance),
- DMA_CTRL_SW_BUF_U32 | DMA_CTRL_RESET),
+ DMA_CTRL_SW_BUF_U32 | DMA_CTRL_ENABLED),
status);
//Create FIFOs
@@ -189,10 +196,6 @@ public:
nirio_status_chain(_send_fifo->start(), status);
if (nirio_status_not_fatal(status)) {
- //Flush RX kernel buffers in case some cruft was
- //left behind from the last run
- _flush_rx_buff();
-
//allocate re-usable managed receive buffers
for (size_t i = 0; i < get_num_recv_frames(); i++){
_mrb_pool.push_back(boost::shared_ptr<nirio_zero_copy_mrb>(new nirio_zero_copy_mrb(
@@ -216,9 +219,9 @@ public:
{
_proxy().get_rio_quirks().remove_tx_fifo(_fifo_instance);
- //Reset DMA streams (Teardown, so don't status chain)
- _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET);
- _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_RESET);
+ //Disable DMA streams (cleanup, so don't status chain)
+ _proxy().poke(PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
+ _proxy().poke(PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), DMA_CTRL_DISABLED);
_flush_rx_buff();
@@ -284,6 +287,47 @@ private:
}
}
+ UHD_INLINE void _wait_until_stream_ready()
+ {
+ static const uint32_t TIMEOUT_IN_MS = 100;
+
+ uint32_t reg_data = 0xffffffff;
+ bool tx_busy = true, rx_busy = true;
+ boost::posix_time::ptime start_time;
+ boost::posix_time::time_duration elapsed;
+ nirio_status status = NiRio_Status_Success;
+
+ nirio_status_chain(_proxy().peek(
+ PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ tx_busy = (reg_data & DMA_STATUS_BUSY);
+ nirio_status_chain(_proxy().peek(
+ PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ rx_busy = (reg_data & DMA_STATUS_BUSY);
+
+ if (nirio_status_not_fatal(status) && (tx_busy || rx_busy)) {
+ start_time = boost::posix_time::microsec_clock::local_time();
+ do {
+ boost::this_thread::sleep(boost::posix_time::microsec(50)); //Avoid flooding the bus
+ elapsed = boost::posix_time::microsec_clock::local_time() - start_time;
+ nirio_status_chain(_proxy().peek(
+ PCIE_TX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ tx_busy = (reg_data & DMA_STATUS_BUSY);
+ nirio_status_chain(_proxy().peek(
+ PCIE_RX_DMA_REG(DMA_CTRL_STATUS_REG, _fifo_instance), reg_data), status);
+ rx_busy = (reg_data & DMA_STATUS_BUSY);
+ } while (
+ nirio_status_not_fatal(status) &&
+ (tx_busy || rx_busy) &&
+ elapsed.total_milliseconds() < TIMEOUT_IN_MS);
+
+ if (tx_busy || rx_busy) {
+ nirio_status_chain(NiRio_Status_FpgaBusy, status);
+ }
+
+ nirio_status_to_exception(status, "Could not create nirio_zero_copy transport.");
+ }
+ }
+
//memory management -> buffers and fifos
niusrprio::niusrprio_session::sptr _fpga_session;
uint32_t _fifo_instance;
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index 632391644..0bbaee319 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -31,7 +31,7 @@ extern "C" {
#define X300_FW_COMPAT_MAJOR 3
#define X300_FW_COMPAT_MINOR 0
-#define X300_FPGA_COMPAT_MAJOR 4
+#define X300_FPGA_COMPAT_MAJOR 6
//shared memory sections - in between the stack and the program space
#define X300_FW_SHMEM_BASE 0x6000
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 6a9de1f30..e931b7983 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -135,6 +135,12 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint)
return addrs;
}
+//We need a zpu xport registry to ensure synchronization between the static finder method
+//and the instances of the x300_impl class.
+typedef uhd::dict< std::string, boost::weak_ptr<wb_iface> > pcie_zpu_iface_registry_t;
+UHD_SINGLETON_FCN(pcie_zpu_iface_registry_t, get_pcie_zpu_iface_registry)
+static boost::mutex pcie_zpu_iface_registry_mutex;
+
static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_query)
{
std::string rpc_port_name(NIUSRPRIO_DEFAULT_RPC_PORT);
@@ -167,17 +173,30 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu
}
niriok_proxy kernel_proxy;
- kernel_proxy.open(dev_info.interface_path);
//Attempt to read the name from the EEPROM and perform filtering.
//This operation can throw due to compatibility mismatch.
try
{
- //This call could throw an exception if the user is switching to using UHD
+ //This block could throw an exception if the user is switching to using UHD
//after LabVIEW FPGA. In that case, skip reading the name and serial and pick
//a default FPGA flavor. During make, a new image will be loaded and everything
//will be OK
- wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy);
+
+ wb_iface::sptr zpu_ctrl;
+
+ //Hold on to the registry mutex as long as zpu_ctrl is alive
+ //to prevent any use by different threads while enumerating
+ boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex);
+
+ if (get_pcie_zpu_iface_registry().has_key(resource_d)) {
+ zpu_ctrl = get_pcie_zpu_iface_registry()[resource_d].lock();
+ } else {
+ kernel_proxy.open(dev_info.interface_path);
+ zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy);
+ //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
@@ -465,7 +484,13 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
//create basic communication
UHD_MSG(status) << "Setup basic communication..." << std::endl;
if (mb.xport_path == "nirio") {
- mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy());
+ boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex);
+ if (get_pcie_zpu_iface_registry().has_key(mb.addr)) {
+ throw uhd::assertion_error("Someone else has a ZPU transport to the device open. Internal error!");
+ } else {
+ mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy());
+ get_pcie_zpu_iface_registry()[mb.addr] = boost::weak_ptr<wb_iface>(mb.zpu_ctrl);
+ }
} else {
mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected(mb.addr,
BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)));
@@ -834,8 +859,14 @@ x300_impl::~x300_impl(void)
//kill the claimer task and unclaim the device
mb.claimer_task.reset();
- 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);
+ { //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);
+ //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.addr);
+ }
}
}
catch(...)
@@ -1461,13 +1492,18 @@ void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const std::string &attr, c
void x300_impl::claimer_loop(wb_iface::sptr iface)
{
- iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL));
- iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash());
- boost::this_thread::sleep(boost::posix_time::milliseconds(1500)); //1.5 seconds
+ { //Critical section
+ boost::mutex::scoped_lock(claimer_mutex);
+ iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_TIME), time(NULL));
+ iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), get_process_hash());
+ }
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); //1 second
}
bool x300_impl::is_claimed(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;
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 4b3efc845..90aed2fdb 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -53,7 +53,7 @@
static const std::string X300_FW_FILE_NAME = "usrp_x300_fw.bin";
static const double X300_DEFAULT_TICK_RATE = 200e6; //Hz
-static const double X300_BUS_CLOCK_RATE = 175e6; //Hz
+static const double X300_BUS_CLOCK_RATE = 166.666667e6; //Hz
static const size_t X300_TX_HW_BUFF_SIZE = 0x90000; //576KiB
static const size_t X300_TX_FC_RESPONSE_FREQ = 8; //per flow-control window
@@ -152,6 +152,7 @@ public:
bool recv_async_msg(uhd::async_metadata_t &, double);
// used by x300_find_with_addr to find X300 devices.
+ static boost::mutex claimer_mutex; //All claims and checks in this process are serialized
static bool is_claimed(uhd::wb_iface::sptr);
enum x300_mboard_t {
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index fb1786deb..cf1e33695 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -124,9 +124,12 @@ static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000);
static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004);
static const uint32_t FPGA_CNTR_HI_REG = PCIE_FPGA_REG(0x0008);
static const uint32_t FPGA_CNTR_FREQ_REG = PCIE_FPGA_REG(0x000C);
+static const uint32_t FPGA_STATUS_REG = PCIE_FPGA_REG(0x0020);
static const uint32_t FPGA_USR_SIG_REG_BASE = PCIE_FPGA_REG(0x0030);
static const uint32_t FPGA_USR_SIG_REG_SIZE = 16;
+static const uint32_t FPGA_STATUS_DMA_ACTIVE_MASK = 0x3F3F0000;
+
static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200);
static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400);
@@ -139,12 +142,15 @@ static const uint32_t DMA_PKT_COUNT_REG = 0xC;
#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG)
#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG)
-static const uint32_t DMA_CTRL_RESET = 1;
+static const uint32_t DMA_CTRL_DISABLED = 0x00000000;
+static const uint32_t DMA_CTRL_ENABLED = 0x00000002;
+static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001;
static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4);
static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4);
static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4);
static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4);
-static const uint32_t DMA_STATUS_ERROR = 1;
+static const uint32_t DMA_STATUS_ERROR = 0x00000001;
+static const uint32_t DMA_STATUS_BUSY = 0x00000002;
static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500);
#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + X)