From 2f102fbff2b7245d3d038e7dfffaa2de856b61aa Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Fri, 8 Apr 2011 16:59:29 -0500
Subject: usrp2: support fw protos with older compats for various parts

i2c, spi, and uart are long time no changing

registers changed recently (think re-map)

also, perform the fpga compat check in the make

now we can find devices with out of date images
---
 host/lib/usrp/usrp2/mboard_impl.cpp | 10 ++++++++
 host/lib/usrp/usrp2/usrp2_iface.cpp | 48 +++++++++++++++++++++----------------
 2 files changed, 38 insertions(+), 20 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 40fc5098b..7a6c596bc 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -66,6 +66,16 @@ usrp2_mboard_impl::usrp2_mboard_impl(
         device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)
     )))
 {
+
+    //check the fpga compatibility number
+    const boost::uint32_t fpga_compat_num = _iface->peek32(_iface->regs.compat_num_rb);
+    if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){
+        throw uhd::runtime_error(str(boost::format(
+            "Expected fpga compatibility number %d, but got %d:\n"
+            "The fpga build is not compatible with the host code build."
+        ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
+    }
+
     //construct transports for dsp and async errors
     std::cout << "Making transport for DSP0..." << std::endl;
     device.dsp_xports.push_back(udp_zero_copy::make(
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index e3827233b..227233917 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -34,6 +34,13 @@ using namespace uhd::transport;
 
 static const double CTRL_RECV_TIMEOUT = 1.0;
 
+static const boost::uint32_t MIN_PROTO_COMPAT_SPI = 7;
+static const boost::uint32_t MIN_PROTO_COMPAT_I2C = 7;
+// The register compat number must reflect the protocol compatibility
+// and the compatibility of the register mapping (more likely to change).
+static const boost::uint32_t MIN_PROTO_COMPAT_REG = USRP2_FW_COMPAT_NUM;
+static const boost::uint32_t MIN_PROTO_COMPAT_UART = 7;
+
 class usrp2_iface_impl : public usrp2_iface{
 public:
 /***********************************************************************
@@ -59,15 +66,6 @@ public:
             regs = usrp2_get_regs(false);
             break;
         }
-
-        //check the fpga compatibility number
-        const boost::uint32_t fpga_compat_num = this->peek32(this->regs.compat_num_rb);
-        if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){
-            throw uhd::runtime_error(str(boost::format(
-                "Expected fpga compatibility number %d, but got %d:\n"
-                "The fpga build is not compatible with the host code build."
-            ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
-        }
     }
 
 /***********************************************************************
@@ -115,7 +113,7 @@ public:
         out_data.data.spi_args.data = htonl(data);
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_SPI);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
 
         return ntohl(in_data.data.spi_args.data);
@@ -138,7 +136,7 @@ public:
         std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data);
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_I2C);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE);
     }
 
@@ -153,7 +151,7 @@ public:
         UHD_ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data));
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_I2C);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE);
         UHD_ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes);
 
@@ -186,7 +184,7 @@ public:
         std::copy(item.begin(), item.end(), out_data.data.uart_args.data);
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_UART);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE);
       }
     }
@@ -205,7 +203,7 @@ public:
         //UHD_ASSERT_THROW(num_bytes <= sizeof(out_data.data.uart_args.data));
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_UART);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE);
         readlen = in_data.data.uart_args.bytes;
 
@@ -226,9 +224,18 @@ public:
 /***********************************************************************
  * Send/Recv over control
  **********************************************************************/
-    usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){
+    usrp2_ctrl_data_t ctrl_send_and_recv(
+        const usrp2_ctrl_data_t &out_data,
+        boost::uint32_t lo = USRP2_FW_COMPAT_NUM,
+        boost::uint32_t hi = USRP2_FW_COMPAT_NUM
+    ){
         boost::mutex::scoped_lock lock(_ctrl_mutex);
 
+        std::string range = (lo == hi)?
+            str(boost::format("%d") % hi) :
+            str(boost::format("[%d to %d]") % lo % hi)
+        ;
+
         //fill in the seq number and send
         usrp2_ctrl_data_t out_copy = out_data;
         out_copy.proto_ver = htonl(USRP2_FW_COMPAT_NUM);
@@ -240,11 +247,12 @@ public:
         const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem);
         while(true){
             size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CTRL_RECV_TIMEOUT);
-            if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){
+            boost::uint32_t compat = ntohl(ctrl_data_in->proto_ver);
+            if(len >= sizeof(boost::uint32_t) and hi >= compat and lo <= compat){
                 throw uhd::runtime_error(str(boost::format(
-                    "Expected protocol compatibility number %d, but got %d:\n"
+                    "Expected protocol compatibility number %s, but got %d:\n"
                     "The firmware build is not compatible with the host code build."
-                ) % int(USRP2_FW_COMPAT_NUM) % ntohl(ctrl_data_in->proto_ver)));
+                ) % range % compat));
             }
             if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(ctrl_data_in->seq) == _ctrl_seq_num){
                 return *ctrl_data_in;
@@ -297,7 +305,7 @@ private:
         out_data.data.poke_args.num_bytes = sizeof(T);
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE);
     }
 
@@ -309,7 +317,7 @@ private:
         out_data.data.poke_args.num_bytes = sizeof(T);
 
         //send and recv
-        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG);
         UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE);
         return T(ntohl(in_data.data.poke_args.data));
     }
-- 
cgit v1.2.3


From f9e1f06e81109573d2e600a18c288aafd1438f64 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 13 Apr 2011 10:04:42 -0700
Subject: usrp2: add check for holler protocol, we can support backwards

---
 host/lib/usrp/usrp2/usrp2_iface.cpp |  2 +-
 host/lib/usrp/usrp2/usrp2_impl.cpp  | 42 ++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 15 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 227233917..6e1d69044 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -248,7 +248,7 @@ public:
         while(true){
             size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CTRL_RECV_TIMEOUT);
             boost::uint32_t compat = ntohl(ctrl_data_in->proto_ver);
-            if(len >= sizeof(boost::uint32_t) and hi >= compat and lo <= compat){
+            if(len >= sizeof(boost::uint32_t) and (hi < compat or lo > compat)){
                 throw uhd::runtime_error(str(boost::format(
                     "Expected protocol compatibility number %s, but got %d:\n"
                     "The firmware build is not compatible with the host code build."
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index f42be321b..cb92b1921 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -171,6 +171,15 @@ static mtu_result_t determine_mtu(const std::string &addr){
     usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(buffer);
     static const double echo_timeout = 0.020; //20 ms
 
+    //test holler - check if its supported in this fw version
+    ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO);
+    ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM);
+    ctrl_data->data.echo_args.len = htonl(sizeof(usrp2_ctrl_data_t));
+    udp_sock->send(boost::asio::buffer(buffer, sizeof(usrp2_ctrl_data_t)));
+    udp_sock->recv(boost::asio::buffer(buffer), echo_timeout);
+    if (ntohl(ctrl_data->id) != USRP2_CTRL_ID_HOLLER_BACK_DUDE)
+        throw uhd::not_implemented_error("holler protocol not implemented");
+
     size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = sizeof(buffer);
     size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = sizeof(buffer);
 
@@ -233,23 +242,28 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
 
     device_addrs_t device_args = separate_device_addr(device_addr);
 
-    //calculate the minimum send and recv mtu of all devices
-    mtu_result_t mtu = determine_mtu(device_args[0]["addr"]);
-    for (size_t i = 1; i < device_args.size(); i++){
-        mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]);
-        mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu);
-        mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu);
-    }
+    try{
+        //calculate the minimum send and recv mtu of all devices
+        mtu_result_t mtu = determine_mtu(device_args[0]["addr"]);
+        for (size_t i = 1; i < device_args.size(); i++){
+            mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]);
+            mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu);
+            mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu);
+        }
 
-    //use the discovered mtu or clip the users requested mtu
-    mtu.recv_mtu = std::min(size_t(device_addr.cast<double>("recv_frame_size", 9000)), mtu.recv_mtu);
-    mtu.send_mtu = std::min(size_t(device_addr.cast<double>("send_frame_size", 9000)), mtu.send_mtu);
+        //use the discovered mtu or clip the users requested mtu
+        mtu.recv_mtu = std::min(size_t(device_addr.cast<double>("recv_frame_size", 9000)), mtu.recv_mtu);
+        mtu.send_mtu = std::min(size_t(device_addr.cast<double>("send_frame_size", 9000)), mtu.send_mtu);
 
-    device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu);
-    device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu);
+        device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu);
+        device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu);
 
-    std::cout << boost::format("Current recv frame size: %d bytes") % mtu.recv_mtu << std::endl;
-    std::cout << boost::format("Current send frame size: %d bytes") % mtu.send_mtu << std::endl;
+        std::cout << boost::format("Current recv frame size: %d bytes") % mtu.recv_mtu << std::endl;
+        std::cout << boost::format("Current send frame size: %d bytes") % mtu.send_mtu << std::endl;
+    }
+    catch(const uhd::not_implemented_error &){
+        //just ignore this error, makes older fw work...
+    }
 
     device_args = separate_device_addr(device_addr); //update args for new frame sizes
 
-- 
cgit v1.2.3


From 668402f27e34422a9afdc4d12f0f5575228f815b Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 13 Apr 2011 10:59:18 -0700
Subject: usrp2: use the firmware's discovered compat number

---
 host/lib/usrp/usrp2/usrp2_iface.cpp | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 6e1d69044..6b3409ecc 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -46,9 +46,20 @@ public:
 /***********************************************************************
  * Structors
  **********************************************************************/
-    usrp2_iface_impl(udp_simple::sptr ctrl_transport){
-        _ctrl_transport = ctrl_transport;
-        _ctrl_seq_num = 0;
+    usrp2_iface_impl(udp_simple::sptr ctrl_transport):
+        _ctrl_transport(ctrl_transport),
+        _ctrl_seq_num(0),
+        _protocol_compat(0) //initialized below...
+    {
+        //Obtain the firmware's compat number.
+        //Save the response compat number for communication.
+        //TODO can choose to reject certain older compat numbers
+        usrp2_ctrl_data_t ctrl_data;
+        ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
+        ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);
+        if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE)
+            throw uhd::runtime_error("firmware not responding");
+        _protocol_compat = ntohl(ctrl_data.proto_ver);
 
         mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_N100);
         switch(this->get_rev()){
@@ -238,7 +249,7 @@ public:
 
         //fill in the seq number and send
         usrp2_ctrl_data_t out_copy = out_data;
-        out_copy.proto_ver = htonl(USRP2_FW_COMPAT_NUM);
+        out_copy.proto_ver = htonl(_protocol_compat);
         out_copy.seq = htonl(++_ctrl_seq_num);
         _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t)));
 
@@ -292,6 +303,7 @@ private:
     //used in send/recv
     boost::mutex _ctrl_mutex;
     boost::uint32_t _ctrl_seq_num;
+    boost::uint32_t _protocol_compat;
 
 /***********************************************************************
  * Private Templated Peek and Poke
-- 
cgit v1.2.3


From a28099fe4abe10b11c9234d67b243adbd20ce1a1 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Tue, 19 Apr 2011 09:36:53 -0700
Subject: usrp2: improve the compatibility error messages

---
 host/lib/usrp/usrp2/mboard_impl.cpp | 6 ++++--
 host/lib/usrp/usrp2/usrp2_iface.cpp | 9 +++------
 2 files changed, 7 insertions(+), 8 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 7a6c596bc..29e0535f8 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -71,8 +71,10 @@ usrp2_mboard_impl::usrp2_mboard_impl(
     const boost::uint32_t fpga_compat_num = _iface->peek32(_iface->regs.compat_num_rb);
     if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){
         throw uhd::runtime_error(str(boost::format(
-            "Expected fpga compatibility number %d, but got %d:\n"
-            "The fpga build is not compatible with the host code build."
+            "\nPlease update the firmware and FPGA images for your device.\n"
+            "See the application notes for USRP2/N-Series for instructions.\n"
+            "Expected FPGA compatibility number %d, but got %d:\n"
+            "The FPGA build is not compatible with the host code build."
         ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
     }
 
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 6b3409ecc..d88d31765 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -242,11 +242,6 @@ public:
     ){
         boost::mutex::scoped_lock lock(_ctrl_mutex);
 
-        std::string range = (lo == hi)?
-            str(boost::format("%d") % hi) :
-            str(boost::format("[%d to %d]") % lo % hi)
-        ;
-
         //fill in the seq number and send
         usrp2_ctrl_data_t out_copy = out_data;
         out_copy.proto_ver = htonl(_protocol_compat);
@@ -261,9 +256,11 @@ public:
             boost::uint32_t compat = ntohl(ctrl_data_in->proto_ver);
             if(len >= sizeof(boost::uint32_t) and (hi < compat or lo > compat)){
                 throw uhd::runtime_error(str(boost::format(
+                    "\nPlease update the firmware and FPGA images for your device.\n"
+                    "See the application notes for USRP2/N-Series for instructions.\n"
                     "Expected protocol compatibility number %s, but got %d:\n"
                     "The firmware build is not compatible with the host code build."
-                ) % range % compat));
+                ) % ((lo == hi)? (boost::format("%d") % hi) : (boost::format("[%d to %d]") % lo % hi)) % compat));
             }
             if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(ctrl_data_in->seq) == _ctrl_seq_num){
                 return *ctrl_data_in;
-- 
cgit v1.2.3