Fixup for what didn't apply from git format-patch series:
0019-x300-added-channel-mapping-capabilities.patch
0022-Removed-spurious-UHD_VAR.patch
0030-uhd-Addressed-Balints-and-Bens-comments-for-subdev-a.patch
to bring source in line with 6962543fec1b186bed4ad1332ee601eff07af1e1

diff -p1 -u -r host/lib/usrp/multi_usrp.cpp ../UPSTREAM/uhd/host/lib/usrp/multi_usrp.cpp
--- host/lib/usrp/multi_usrp.cpp	2014-03-29 21:18:43.000000000 -0400
+++ uhd/host/lib/usrp/multi_usrp.cpp	2014-03-29 19:49:15.000000000 -0400
@@ -636,3 +636,2 @@ public:
         if (chan != ALL_CHANS){
-            UHD_MSG(status) << "multi_usrp::set_rx_rate()   rate=" << rate << "  dsproot=" << rx_dsp_root(chan) << std::endl;
             _tree->access<double>(rx_dsp_root(chan) / "rate" / "value").set(rate);
@@ -1066,3 +1065,3 @@ private:
             std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "rx_chan_dsp_mapping").get();
-            UHD_ASSERT_THROW(map.size() >= mcp.chan);
+            UHD_ASSERT_THROW(map.size() > mcp.chan);
             mcp.chan = map[mcp.chan];
@@ -1086,3 +1085,3 @@ private:
             std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "tx_chan_dsp_mapping").get();
-            UHD_ASSERT_THROW(map.size() >= mcp.chan);
+            UHD_ASSERT_THROW(map.size() > mcp.chan);
             mcp.chan = map[mcp.chan];
diff -p1 -u -r host/lib/usrp/x300/x300_impl.cpp uhd/host/lib/usrp/x300/x300_impl.cpp
--- host/lib/usrp/x300/x300_impl.cpp	2014-03-29 21:18:43.000000000 -0400
+++ uhd/host/lib/usrp/x300/x300_impl.cpp	2014-03-29 19:49:15.000000000 -0400
@@ -460,4 +460,2 @@ void x300_impl::setup_mb(const size_t mb
 
-    const std::vector<std::string> DB_NAMES = boost::assign::list_of("A")("B");
-
     //create basic communication
@@ -677,4 +675,4 @@ void x300_impl::setup_mb(const size_t mb
     UHD_MSG(status) << "Initialize Radio control..." << std::endl;
-    this->setup_radio(mb_i, 0, DB_NAMES[0]);
-    this->setup_radio(mb_i, 1, DB_NAMES[1]);
+    this->setup_radio(mb_i, "A");
+    this->setup_radio(mb_i, "B");
 
@@ -745,2 +743,5 @@ void x300_impl::setup_mb(const size_t mb
     ////////////////////////////////////////////////////////////////////
+    std::vector<size_t> default_map(2, 0); default_map[1] = 1;
+    _tree->create<std::vector<size_t> >(mb_path / "rx_chan_dsp_mapping").set(default_map);
+    _tree->create<std::vector<size_t> >(mb_path / "tx_chan_dsp_mapping").set(default_map);
     _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
@@ -849,8 +850,9 @@ static void check_adc(wb_iface::sptr ifa
 
-void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string &db_name)
+void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name)
 {
     const fs_path mb_path = "/mboards/"+boost::lexical_cast<std::string>(mb_i);
+    UHD_ASSERT_THROW(mb_i < _mb.size());
     mboard_members_t &mb = _mb[mb_i];
-    radio_perifs_t &perif = mb.radio_perifs[i];
-    const size_t dspno = i;
+    const size_t radio_index = mb.get_radio_index(slot_name);
+    radio_perifs_t &perif = mb.radio_perifs[radio_index];
 
@@ -859,6 +861,6 @@ void x300_impl::setup_radio(const size_t
     ////////////////////////////////////////////////////////////////////
-    uint8_t dest = (i == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+    uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
     boost::uint32_t ctrl_sid;
     both_xports_t xport = this->make_transport(mb_i, dest, X300_RADIO_DEST_PREFIX_CTRL, device_addr_t(), ctrl_sid);
-    perif.ctrl = radio_ctrl_core_3000::make(mb.if_pkt_is_big_endian, xport.recv, xport.send, ctrl_sid, db_name);
+    perif.ctrl = radio_ctrl_core_3000::make(mb.if_pkt_is_big_endian, xport.recv, xport.send, ctrl_sid, slot_name);
     perif.ctrl->poke32(TOREG(SR_MISC_OUTS), (1 << 2)); //reset adc + dac
@@ -908,9 +910,9 @@ void x300_impl::setup_radio(const size_t
     ////////////////////////////////////////////////////////////////
-    _tree->create<int>(mb_path / "rx_codecs" / db_name / "gains"); //phony property so this dir exists
-    _tree->create<int>(mb_path / "tx_codecs" / db_name / "gains"); //phony property so this dir exists
-    _tree->create<std::string>(mb_path / "rx_codecs" / db_name / "name").set("ads62p48");
-    _tree->create<std::string>(mb_path / "tx_codecs" / db_name / "name").set("ad9146");
+    _tree->create<int>(mb_path / "rx_codecs" / slot_name / "gains"); //phony property so this dir exists
+    _tree->create<int>(mb_path / "tx_codecs" / slot_name / "gains"); //phony property so this dir exists
+    _tree->create<std::string>(mb_path / "rx_codecs" / slot_name / "name").set("ads62p48");
+    _tree->create<std::string>(mb_path / "tx_codecs" / slot_name / "name").set("ad9146");
 
-    _tree->create<meta_range_t>(mb_path / "rx_codecs" / db_name / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5));
-    _tree->create<double>(mb_path / "rx_codecs" / db_name / "gains" / "digital" / "value")
+    _tree->create<meta_range_t>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5));
+    _tree->create<double>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "value")
         .subscribe(boost::bind(&x300_adc_ctrl::set_gain, perif.adc, _1)).set(0);
@@ -921,3 +923,3 @@ void x300_impl::setup_radio(const size_t
     perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, TOREG(SR_RX_FRONT));
-    const fs_path rx_fe_path = mb_path / "rx_frontends" / db_name;
+    const fs_path rx_fe_path = mb_path / "rx_frontends" / slot_name;
     _tree->create<std::complex<double> >(rx_fe_path / "dc_offset" / "value")
@@ -933,3 +935,3 @@ void x300_impl::setup_radio(const size_t
     perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, TOREG(SR_TX_FRONT));
-    const fs_path tx_fe_path = mb_path / "tx_frontends" / db_name;
+    const fs_path tx_fe_path = mb_path / "tx_frontends" / slot_name;
     _tree->create<std::complex<double> >(tx_fe_path / "dc_offset" / "value")
@@ -952,3 +954,3 @@ void x300_impl::setup_radio(const size_t
         .subscribe(boost::bind(&rx_dsp_core_3000::set_tick_rate, perif.ddc, _1));
-    const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % dspno);
+    const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % radio_index);
     _tree->create<meta_range_t>(rx_dsp_path / "rate" / "range")
@@ -957,3 +959,3 @@ void x300_impl::setup_radio(const size_t
         .coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1))
-        .subscribe(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), dspno, _1))
+        .subscribe(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), radio_index, _1))
         .set(1e6);
@@ -976,3 +978,3 @@ void x300_impl::setup_radio(const size_t
         .subscribe(boost::bind(&tx_dsp_core_3000::set_tick_rate, perif.duc, _1));
-    const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % dspno);
+    const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % radio_index);
     _tree->create<meta_range_t>(tx_dsp_path / "rate" / "range")
@@ -981,3 +983,3 @@ void x300_impl::setup_radio(const size_t
         .coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1))
-        .subscribe(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), dspno, _1))
+        .subscribe(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), radio_index, _1))
         .set(1e6);
@@ -1000,4 +1002,4 @@ void x300_impl::setup_radio(const size_t
     ////////////////////////////////////////////////////////////////////
-    const fs_path db_path = (mb_path / "dboards" / db_name);
-    const size_t j = (db_name == "B")? 0x2 : 0x0;
+    const fs_path db_path = (mb_path / "dboards" / slot_name);
+    const size_t j = (slot_name == "B")? 0x2 : 0x0;
     _tree->create<dboard_eeprom_t>(db_path / "rx_eeprom")
@@ -1020,5 +1022,5 @@ void x300_impl::setup_radio(const size_t
     db_config.clock = mb.clock;
-    db_config.which_rx_clk = (db_name == "A")? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX;
-    db_config.which_tx_clk = (db_name == "A")? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX;
-    db_config.dboard_slot = (db_name == "A")? 0 : 1;
+    db_config.which_rx_clk = (slot_name == "A")? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX;
+    db_config.which_tx_clk = (slot_name == "A")? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX;
+    db_config.dboard_slot = (slot_name == "A")? 0 : 1;
     _dboard_ifaces[db_path] = x300_make_dboard_iface(db_config);
@@ -1038,4 +1040,4 @@ void x300_impl::setup_radio(const size_t
     _tree->access<std::string>(db_path / "rx_frontends" / fe_name / "antenna" / "value")
-        .subscribe(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[i].leds, _1));
-    this->update_atr_leds(mb.radio_perifs[i].leds, ""); //init anyway, even if never called
+        .subscribe(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[radio_index].leds, _1));
+    this->update_atr_leds(mb.radio_perifs[radio_index].leds, ""); //init anyway, even if never called
 
@@ -1046,3 +1048,3 @@ void x300_impl::setup_radio(const size_t
         _tree->access<double>(db_rx_fe_path / name / "freq" / "value")
-            .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, db_name, _1));
+            .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1));
     }
diff -p1 -u -r host/lib/usrp/x300/x300_impl.hpp uhd/host/lib/usrp/x300/x300_impl.hpp
--- host/lib/usrp/x300/x300_impl.hpp	2014-03-29 21:18:43.000000000 -0400
+++ uhd/host/lib/usrp/x300/x300_impl.hpp	2014-03-29 19:49:15.000000000 -0400
@@ -84,4 +84,4 @@ static const double X300_DEFAULT_SYSREF_
 #define X300_XB_DST_E1 1
-#define X300_XB_DST_R0 2
-#define X300_XB_DST_R1 3
+#define X300_XB_DST_R0 2 // Radio 0 -> Slot A
+#define X300_XB_DST_R1 3 // Radio 1 -> Slot B
 #define X300_XB_DST_CE0 4
@@ -193,4 +193,9 @@ private:
         //perifs in each radio
-        radio_perifs_t radio_perifs[2];
+        radio_perifs_t radio_perifs[2]; //!< This is hardcoded s.t. radio_perifs[0] points to slot A and [1] to B
         uhd::usrp::dboard_eeprom_t db_eeproms[8];
+	//! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs
+        size_t get_radio_index(const std::string &slot_name) {
+             UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B");
+             return slot_name == "A" ? 0 : 1;
+        }
 
@@ -222,3 +227,16 @@ private:
 
-    void setup_radio(const size_t, const size_t which_radio, const std::string &db_name);
+     /*! \brief Initialize the radio component on a given slot.
+      *
+      * Call this function once per slot (A and B) and motherboard to initialize all the radio components.
+      * This will:
+      * - Reset and init DACs and ADCs
+      * - Setup controls for DAC, ADC, SPI and LEDs
+      * - Self test ADC
+      * - Sync DACs (for MIMO)
+      * - Initialize the property tree for control objects etc. (gain, rate...)
+      *
+      * \param mb_i Motherboard index
+      * \param slot_name Slot name (A or B).
+      */
+    void setup_radio(const size_t, const std::string &slot_name);
 
@@ -288,3 +306,5 @@ private:
 
-    /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec
+    /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec.
+     *
+     * Also checks if the given subdev is valid for this device and updates the channel to DSP mapping.
      *
diff -p1 -u -r host/lib/usrp/x300/x300_io_impl.cpp uhd/host/lib/usrp/x300/x300_io_impl.cpp
--- host/lib/usrp/x300/x300_io_impl.cpp	2014-03-29 21:18:43.000000000 -0400
+++ uhd/host/lib/usrp/x300/x300_io_impl.cpp	2014-03-29 19:49:15.000000000 -0400
@@ -82,4 +82,5 @@ void x300_impl::update_subdev_spec(const
     UHD_ASSERT_THROW(tx_rx == "tx" or tx_rx == "rx");
+    UHD_ASSERT_THROW(mb_i < _mb.size());
     const std::string mb_name = boost::lexical_cast<std::string>(mb_i);
-    fs_path root = "/mboards/" + mb_name + "/dboards";
+    fs_path mb_root = "/mboards/" + mb_name;
 
@@ -88,31 +89,35 @@ void x300_impl::update_subdev_spec(const
     UHD_ASSERT_THROW(spec.size() <= 2);
-    if (spec.size() > 0) UHD_ASSERT_THROW(spec[0].db_name == "A");
-    if (spec.size() > 1) UHD_ASSERT_THROW(spec[1].db_name == "B");
+    if (spec.size() == 1) {
+        UHD_ASSERT_THROW(spec[0].db_name == "A" || spec[0].db_name == "B");
+    }
+    else if (spec.size() == 2) {
+        UHD_ASSERT_THROW(
+            (spec[0].db_name == "A" && spec[1].db_name == "B") ||
+            (spec[0].db_name == "B" && spec[1].db_name == "A")
+        );
+    }
 
-    //setup mux for this spec
-    for (size_t i = 0; i < 2; i++)
+    std::vector<size_t> chan_to_dsp_map(spec.size(), 0);
+    // setup mux for this spec
+    for (size_t i = 0; i < spec.size(); i++)
     {
-        //extract db name
-        const std::string db_name = (i == 0)? "A" : "B";
-        if (i < spec.size()) UHD_ASSERT_THROW(spec[i].db_name == db_name);
-
-        //extract fe name
-        std::string fe_name;
-        if (i < spec.size()) fe_name = spec[i].sd_name;
-        else fe_name = _tree->list(root / db_name / (tx_rx + "_frontends")).front();
+        const int radio_idx = _mb[mb_i].get_radio_index(spec[i].db_name);
+        chan_to_dsp_map[i] = radio_idx;
 
         //extract connection
-        const std::string conn = _tree->access<std::string>(root / db_name / (tx_rx + "_frontends") / fe_name / "connection").get();
+        const std::string conn = _tree->access<std::string>(mb_root / "dboards" / spec[i].db_name / (tx_rx + "_frontends") / spec[i].sd_name / "connection").get();
 
-	if (tx_rx == "tx") {
+        if (tx_rx == "tx") {
             //swap condition
-            _mb[mb_i].radio_perifs[i].tx_fe->set_mux(conn);
-	} else {
+            _mb[mb_i].radio_perifs[radio_idx].tx_fe->set_mux(conn);
+        } else {
             //swap condition
             const bool fe_swapped = (conn == "QI" or conn == "Q");
-            _mb[mb_i].radio_perifs[i].ddc->set_mux(conn, fe_swapped);
+            _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(conn, fe_swapped);
             //see usrp/io_impl.cpp if multiple DSPs share the frontend:
-            _mb[mb_i].radio_perifs[i].rx_fe->set_mux(fe_swapped);
-	}
+            _mb[mb_i].radio_perifs[radio_idx].rx_fe->set_mux(fe_swapped);
+        }
     }
+
+    _tree->access<std::vector<size_t> >(mb_root / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map);
 }
@@ -362,4 +367,10 @@ rx_streamer::sptr x300_impl::get_rx_stre
         // Find the DSP that corresponds to this mainboard and subdev
+        UHD_ASSERT_THROW(mb_index < _mb.size());
         mboard_members_t &mb = _mb[mb_index];
-        radio_perifs_t &perif = mb.radio_perifs[mb_chan];
+        const std::vector<size_t> dsp_map = _tree->access<std::vector<size_t> >("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "rx_chan_dsp_mapping")
+                                            .get(); //.at(mb_chan);
+        UHD_ASSERT_THROW(mb_chan < dsp_map.size());
+        const size_t radio_index = dsp_map[mb_chan];
+        UHD_ASSERT_THROW(radio_index < 2);
+        radio_perifs_t &perif = mb.radio_perifs[radio_index];
 
@@ -384,3 +395,3 @@ rx_streamer::sptr x300_impl::get_rx_stre
         //allocate sid and create transport
-        uint8_t dest = (mb_chan == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+        uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
         boost::uint32_t data_sid;
@@ -398,5 +409,5 @@ rx_streamer::sptr x300_impl::get_rx_stre
         ;
-        const size_t bpp = xport.recv->get_recv_frame_size() - hdr_size;
-        const size_t bpi = convert::get_bytes_per_item(args.otw_format);
-        const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));
+        const size_t bpp = xport.recv->get_recv_frame_size() - hdr_size; // bytes per packet
+        const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item
+        const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); // samples per packet
 
@@ -467,3 +478,3 @@ rx_streamer::sptr x300_impl::get_rx_stre
         //Store a weak pointer to prevent a streamer->x300_impl->streamer circular dependency
-        mb.rx_streamers[mb_chan] = boost::weak_ptr<sph::recv_packet_streamer>(my_streamer);
+        mb.rx_streamers[radio_index] = boost::weak_ptr<sph::recv_packet_streamer>(my_streamer);
 
@@ -472,3 +483,3 @@ rx_streamer::sptr x300_impl::get_rx_stre
         _tree->access<double>(mb_path / "tick_rate").update();
-        _tree->access<double>(mb_path / "rx_dsps" / boost::lexical_cast<std::string>(mb_chan) / "rate" / "value").update();
+        _tree->access<double>(mb_path / "rx_dsps" / boost::lexical_cast<std::string>(radio_index) / "rate" / "value").update();
     }
@@ -545,3 +556,5 @@ tx_streamer::sptr x300_impl::get_tx_stre
         mboard_members_t &mb = _mb[mb_index];
-        radio_perifs_t &perif = mb.radio_perifs[mb_chan];
+	const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "tx_chan_dsp_mapping")
+                                            .get().at(mb_chan);
+        radio_perifs_t &perif = mb.radio_perifs[radio_index];
 
@@ -551,3 +564,3 @@ tx_streamer::sptr x300_impl::get_tx_stre
         //allocate sid and create transport
-        uint8_t dest = (mb_chan == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+        uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
         boost::uint32_t data_sid;
@@ -624,3 +637,3 @@ tx_streamer::sptr x300_impl::get_tx_stre
         //Store a weak pointer to prevent a streamer->x300_impl->streamer circular dependency
-        mb.tx_streamers[mb_chan] = boost::weak_ptr<sph::send_packet_streamer>(my_streamer);
+        mb.tx_streamers[radio_index] = boost::weak_ptr<sph::send_packet_streamer>(my_streamer);
 
@@ -629,3 +642,3 @@ tx_streamer::sptr x300_impl::get_tx_stre
         _tree->access<double>(mb_path / "tick_rate").update();
-        _tree->access<double>(mb_path / "tx_dsps" / boost::lexical_cast<std::string>(mb_chan) / "rate" / "value").update();
+        _tree->access<double>(mb_path / "tx_dsps" / boost::lexical_cast<std::string>(radio_index) / "rate" / "value").update();
     }
