From 23a0454998d8904d4e6f2f3f8bc0a79557043321 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Thu, 29 Jul 2010 16:00:39 -0700
Subject: usrp2: added tx policy register and changed fw to not handle error in
 buffer pool

---
 host/lib/usrp/usrp2/mboard_impl.cpp | 1 +
 host/lib/usrp/usrp2/usrp2_regs.hpp  | 5 +++++
 2 files changed, 6 insertions(+)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index b3b03c11c..0ac988361 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -85,6 +85,7 @@ usrp2_mboard_impl::usrp2_mboard_impl(
     _iface->poke32(U2_REG_TX_CTRL_NUM_CHAN, 0);    //1 channel
     _iface->poke32(U2_REG_TX_CTRL_CLEAR_STATE, 1); //reset
     _iface->poke32(U2_REG_TX_CTRL_REPORT_SID, 1);  //sid 1 (different from rx)
+    _iface->poke32(U2_REG_TX_CTRL_POLICY, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);
 
     //init the ddc
     init_ddc_config();
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index aa8bd860f..cc9094ae7 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -247,5 +247,10 @@
 #define U2_REG_TX_CTRL_NUM_CHAN          _SR_ADDR(SR_TX_CTRL + 0)
 #define U2_REG_TX_CTRL_CLEAR_STATE       _SR_ADDR(SR_TX_CTRL + 1)
 #define U2_REG_TX_CTRL_REPORT_SID        _SR_ADDR(SR_TX_CTRL + 2)
+#define U2_REG_TX_CTRL_POLICY            _SR_ADDR(SR_TX_CTRL + 3)
+
+#define U2_FLAG_TX_CTRL_POLICY_WAIT          (0x1 << 0)
+#define U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET   (0x1 << 1)
+#define U2_FLAG_TX_CTRL_POLICY_NEXT_BURST    (0x1 << 2)
 
 #endif /* INCLUDED_USRP2_REGS_HPP */
-- 
cgit v1.2.3


From 5dca9e6315c5f827d97351316e5bdd3a786dc4f1 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Fri, 30 Jul 2010 11:16:58 -0700
Subject: usrp2: stop streaming and drain buffer (if left running)

---
 host/lib/usrp/usrp2/io_impl.cpp     | 10 ++++++----
 host/lib/usrp/usrp2/mboard_impl.cpp |  5 +++++
 2 files changed, 11 insertions(+), 4 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index aa6d15783..9e29edd82 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -144,11 +144,13 @@ void usrp2_impl::io_impl::recv_pirate_loop(
  **********************************************************************/
 void usrp2_impl::io_init(void){
     //send a small data packet so the usrp2 knows the udp source port
-    for(size_t i = 0; i < _data_transports.size(); i++){
-        managed_send_buffer::sptr send_buff = _data_transports[i]->get_send_buff();
-        boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
-        memcpy(send_buff->cast<void*>(), &data, sizeof(data));
+    BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){
+        managed_send_buffer::sptr send_buff = data_transport->get_send_buff();
+        static const boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
+        std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
         send_buff->commit(sizeof(data));
+        //drain the recv buffers (may have junk)
+        while (data_transport->get_recv_buff().get());
     }
 
     //the number of recv frames is the number for the first transport
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 0ac988361..3d103c940 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -98,6 +98,11 @@ usrp2_mboard_impl::usrp2_mboard_impl(
 
     //init the tx and rx dboards (do last)
     dboard_init();
+
+    //Issue a stop streaming command (in case it was left running).
+    //Since this command is issued before the networking is setup,
+    //most if not all junk packets will never make it to the socket.
+    this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
 }
 
 usrp2_mboard_impl::~usrp2_mboard_impl(void){
-- 
cgit v1.2.3


From 4240d5a2a1b705fe8ed5c3a1d1deef24be00d444 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Fri, 30 Jul 2010 12:43:41 -0700
Subject: usrp2: reorganized firmware directory

---
 firmware/microblaze/.gitignore                     |   2 +
 firmware/microblaze/Makefile.am                    |   5 +-
 firmware/microblaze/Makefile.common                |  37 +-
 firmware/microblaze/apps/.gitignore                |   8 -
 firmware/microblaze/apps/Makefile.am               |  82 ---
 firmware/microblaze/apps/app_passthru_v2.c         | 251 -------
 firmware/microblaze/apps/app_passthru_v2.h         |  54 --
 firmware/microblaze/apps/blink_leds.c              |  40 --
 firmware/microblaze/apps/blink_leds2.c             |  53 --
 firmware/microblaze/apps/buf_ram_test.c            |  89 ---
 firmware/microblaze/apps/burn_dbsrx_eeprom.c       | 106 ---
 firmware/microblaze/apps/burnrev30.c               | 162 -----
 firmware/microblaze/apps/burnrev31.c               | 162 -----
 firmware/microblaze/apps/burnrev40.c               | 162 -----
 firmware/microblaze/apps/can_i_sub.c               |  25 -
 firmware/microblaze/apps/cruft/Makefile.am         |  82 +++
 firmware/microblaze/apps/cruft/app_passthru_v2.c   | 251 +++++++
 firmware/microblaze/apps/cruft/app_passthru_v2.h   |  54 ++
 firmware/microblaze/apps/cruft/blink_leds.c        |  40 ++
 firmware/microblaze/apps/cruft/blink_leds2.c       |  53 ++
 firmware/microblaze/apps/cruft/buf_ram_test.c      |  89 +++
 firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c | 106 +++
 firmware/microblaze/apps/cruft/burnrev30.c         | 162 +++++
 firmware/microblaze/apps/cruft/burnrev31.c         | 162 +++++
 firmware/microblaze/apps/cruft/can_i_sub.c         |  25 +
 .../microblaze/apps/cruft/double_buffer_fragment.c | 138 ++++
 firmware/microblaze/apps/cruft/echo.c              |  34 +
 firmware/microblaze/apps/cruft/eth_serdes.c        | 233 ++++++
 firmware/microblaze/apps/cruft/factory_test.c      | 438 +++++++++++
 firmware/microblaze/apps/cruft/gen_eth_packets.c   | 187 +++++
 firmware/microblaze/apps/cruft/gen_pause_frames.c  | 207 ++++++
 firmware/microblaze/apps/cruft/hello.c             |  30 +
 firmware/microblaze/apps/cruft/ibs_rx_test.c       |  82 +++
 firmware/microblaze/apps/cruft/ibs_tx_test.c       | 160 +++++
 .../microblaze/apps/cruft/mimo_app_common_v2.c     | 582 +++++++++++++++
 .../microblaze/apps/cruft/mimo_app_common_v2.h     |  63 ++
 firmware/microblaze/apps/cruft/mimo_tx.c           | 363 ++++++++++
 firmware/microblaze/apps/cruft/mimo_tx_slave.c     | 376 ++++++++++
 firmware/microblaze/apps/cruft/rcv_eth_packets.c   | 233 ++++++
 firmware/microblaze/apps/cruft/read_dbids.c        |  59 ++
 firmware/microblaze/apps/cruft/sd_bounce.c         | 153 ++++
 firmware/microblaze/apps/cruft/sd_gentest.c        | 269 +++++++
 firmware/microblaze/apps/cruft/serdes_to_dsp.c     | 179 +++++
 firmware/microblaze/apps/cruft/serdes_txrx.c       | 368 ++++++++++
 firmware/microblaze/apps/cruft/set_hw_rev.c        |  45 ++
 firmware/microblaze/apps/cruft/test1.c             | 282 ++++++++
 firmware/microblaze/apps/cruft/test_db_spi.c       |  35 +
 firmware/microblaze/apps/cruft/test_i2c.c          | 108 +++
 firmware/microblaze/apps/cruft/test_lsadc.c        |  57 ++
 firmware/microblaze/apps/cruft/test_lsdac.c        |  51 ++
 firmware/microblaze/apps/cruft/test_phy_comm.c     | 113 +++
 firmware/microblaze/apps/cruft/test_ram.c          | 105 +++
 firmware/microblaze/apps/cruft/test_sd.c           |  81 +++
 firmware/microblaze/apps/cruft/timer_test.c        |  57 ++
 firmware/microblaze/apps/cruft/tx_standalone.c     | 339 +++++++++
 firmware/microblaze/apps/double_buffer_fragment.c  | 138 ----
 firmware/microblaze/apps/echo.c                    |  34 -
 firmware/microblaze/apps/eth_serdes.c              | 233 ------
 firmware/microblaze/apps/factory_test.c            | 438 -----------
 firmware/microblaze/apps/gen_eth_packets.c         | 187 -----
 firmware/microblaze/apps/gen_pause_frames.c        | 207 ------
 firmware/microblaze/apps/hello.c                   |  30 -
 firmware/microblaze/apps/ibs_rx_test.c             |  82 ---
 firmware/microblaze/apps/ibs_tx_test.c             | 160 -----
 firmware/microblaze/apps/mimo_app_common_v2.c      | 582 ---------------
 firmware/microblaze/apps/mimo_app_common_v2.h      |  63 --
 firmware/microblaze/apps/mimo_tx.c                 | 363 ----------
 firmware/microblaze/apps/mimo_tx_slave.c           | 376 ----------
 firmware/microblaze/apps/rcv_eth_packets.c         | 233 ------
 firmware/microblaze/apps/read_dbids.c              |  59 --
 firmware/microblaze/apps/sd_bounce.c               | 153 ----
 firmware/microblaze/apps/sd_gentest.c              | 269 -------
 firmware/microblaze/apps/serdes_to_dsp.c           | 179 -----
 firmware/microblaze/apps/serdes_txrx.c             | 368 ----------
 firmware/microblaze/apps/set_hw_rev.c              |  45 --
 firmware/microblaze/apps/test1.c                   | 282 --------
 firmware/microblaze/apps/test_db_spi.c             |  35 -
 firmware/microblaze/apps/test_i2c.c                | 108 ---
 firmware/microblaze/apps/test_lsadc.c              |  57 --
 firmware/microblaze/apps/test_lsdac.c              |  51 --
 firmware/microblaze/apps/test_phy_comm.c           | 113 ---
 firmware/microblaze/apps/test_ram.c                | 105 ---
 firmware/microblaze/apps/test_sd.c                 |  81 ---
 firmware/microblaze/apps/timer_test.c              |  57 --
 firmware/microblaze/apps/tx_standalone.c           | 339 ---------
 firmware/microblaze/apps/txrx_uhd.c                |   3 +-
 firmware/microblaze/bootstrap                      |   1 +
 firmware/microblaze/config.guess                   |   1 -
 firmware/microblaze/config.sub                     |   1 -
 firmware/microblaze/configure.ac                   |   6 +-
 firmware/microblaze/include/.gitignore             |   2 -
 firmware/microblaze/include/Makefile.am            |  30 -
 firmware/microblaze/include/compiler.h             |  25 -
 firmware/microblaze/include/net/.gitignore         |   2 -
 firmware/microblaze/include/net/Makefile.am        |  23 -
 firmware/microblaze/include/net/eth_mac_addr.h     |  29 -
 firmware/microblaze/include/net/padded_eth_hdr.h   |  37 -
 firmware/microblaze/include/net/socket_address.h   |  41 --
 firmware/microblaze/include/usrp2_clock_bits.h     |  55 --
 firmware/microblaze/include/usrp2_fpga_regs.h      |  80 ---
 firmware/microblaze/include/usrp2_i2c_addr.h       |  78 --
 firmware/microblaze/include/usrp2_types.h          | 105 ---
 firmware/microblaze/include/vrt/bits.h             |  92 ---
 firmware/microblaze/include/vrt/types.h            | 138 ----
 firmware/microblaze/lib/.gitignore                 |  40 --
 firmware/microblaze/lib/Makefile.am                |  87 ---
 firmware/microblaze/lib/Makefile.inc               |  47 ++
 firmware/microblaze/lib/clock_bits.h               |  55 ++
 firmware/microblaze/lib/clocks.c                   |  81 ++-
 firmware/microblaze/lib/clocks.h                   |   8 +-
 firmware/microblaze/lib/compiler.h                 |  25 +
 firmware/microblaze/lib/eth_mac.c                  |  10 +-
 firmware/microblaze/lib/eth_phy.h                  | 219 ------
 firmware/microblaze/lib/ethernet.c                 | 390 ----------
 firmware/microblaze/lib/hal_io.c                   |  10 +
 firmware/microblaze/lib/hal_io.h                   |   1 +
 firmware/microblaze/lib/hal_uart.c                 |  13 +-
 firmware/microblaze/lib/hal_uart.h                 |  10 +
 firmware/microblaze/lib/memory_map.h               | 792 --------------------
 firmware/microblaze/lib/net/.gitignore             |   2 +
 firmware/microblaze/lib/net/eth_mac_addr.h         |  29 +
 firmware/microblaze/lib/net/padded_eth_hdr.h       |  37 +
 firmware/microblaze/lib/net/socket_address.h       |  41 ++
 firmware/microblaze/lib/nonstdio.c                 |  43 ++
 firmware/microblaze/lib/nonstdio.h                 |  10 +-
 firmware/microblaze/lib/pic.c                      |   2 +-
 firmware/microblaze/lib/sd.c                       | 197 -----
 firmware/microblaze/lib/sd.h                       | 122 ----
 firmware/microblaze/lib/spi.c                      |   2 +-
 firmware/microblaze/lib/spi.h                      |  18 +
 firmware/microblaze/lib/u2_init.c                  |  11 +-
 firmware/microblaze/usrp2/.gitignore               |   9 +
 firmware/microblaze/usrp2/Makefile.am              |  43 ++
 firmware/microblaze/usrp2/eth_phy.h                | 219 ++++++
 firmware/microblaze/usrp2/ethernet.c               | 389 ++++++++++
 firmware/microblaze/usrp2/memory_map.h             | 797 +++++++++++++++++++++
 firmware/microblaze/usrp2/sd.c                     | 197 +++++
 firmware/microblaze/usrp2/sd.h                     | 122 ++++
 host/docs/usrp2.rst                                |   2 +-
 host/lib/usrp/usrp2/dboard_impl.cpp                |   8 +-
 host/lib/usrp/usrp2/fw_common.h                    |  16 +
 host/lib/usrp/usrp2/mboard_impl.cpp                |  12 +-
 host/lib/usrp/usrp2/usrp2_iface.hpp                |  16 -
 143 files changed, 8682 insertions(+), 9315 deletions(-)
 delete mode 100644 firmware/microblaze/apps/.gitignore
 delete mode 100644 firmware/microblaze/apps/Makefile.am
 delete mode 100644 firmware/microblaze/apps/app_passthru_v2.c
 delete mode 100644 firmware/microblaze/apps/app_passthru_v2.h
 delete mode 100644 firmware/microblaze/apps/blink_leds.c
 delete mode 100644 firmware/microblaze/apps/blink_leds2.c
 delete mode 100644 firmware/microblaze/apps/buf_ram_test.c
 delete mode 100644 firmware/microblaze/apps/burn_dbsrx_eeprom.c
 delete mode 100644 firmware/microblaze/apps/burnrev30.c
 delete mode 100644 firmware/microblaze/apps/burnrev31.c
 delete mode 100644 firmware/microblaze/apps/burnrev40.c
 delete mode 100644 firmware/microblaze/apps/can_i_sub.c
 create mode 100644 firmware/microblaze/apps/cruft/Makefile.am
 create mode 100644 firmware/microblaze/apps/cruft/app_passthru_v2.c
 create mode 100644 firmware/microblaze/apps/cruft/app_passthru_v2.h
 create mode 100644 firmware/microblaze/apps/cruft/blink_leds.c
 create mode 100644 firmware/microblaze/apps/cruft/blink_leds2.c
 create mode 100644 firmware/microblaze/apps/cruft/buf_ram_test.c
 create mode 100644 firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c
 create mode 100644 firmware/microblaze/apps/cruft/burnrev30.c
 create mode 100644 firmware/microblaze/apps/cruft/burnrev31.c
 create mode 100644 firmware/microblaze/apps/cruft/can_i_sub.c
 create mode 100644 firmware/microblaze/apps/cruft/double_buffer_fragment.c
 create mode 100644 firmware/microblaze/apps/cruft/echo.c
 create mode 100644 firmware/microblaze/apps/cruft/eth_serdes.c
 create mode 100644 firmware/microblaze/apps/cruft/factory_test.c
 create mode 100644 firmware/microblaze/apps/cruft/gen_eth_packets.c
 create mode 100644 firmware/microblaze/apps/cruft/gen_pause_frames.c
 create mode 100644 firmware/microblaze/apps/cruft/hello.c
 create mode 100644 firmware/microblaze/apps/cruft/ibs_rx_test.c
 create mode 100644 firmware/microblaze/apps/cruft/ibs_tx_test.c
 create mode 100644 firmware/microblaze/apps/cruft/mimo_app_common_v2.c
 create mode 100644 firmware/microblaze/apps/cruft/mimo_app_common_v2.h
 create mode 100644 firmware/microblaze/apps/cruft/mimo_tx.c
 create mode 100644 firmware/microblaze/apps/cruft/mimo_tx_slave.c
 create mode 100644 firmware/microblaze/apps/cruft/rcv_eth_packets.c
 create mode 100644 firmware/microblaze/apps/cruft/read_dbids.c
 create mode 100644 firmware/microblaze/apps/cruft/sd_bounce.c
 create mode 100644 firmware/microblaze/apps/cruft/sd_gentest.c
 create mode 100644 firmware/microblaze/apps/cruft/serdes_to_dsp.c
 create mode 100644 firmware/microblaze/apps/cruft/serdes_txrx.c
 create mode 100644 firmware/microblaze/apps/cruft/set_hw_rev.c
 create mode 100644 firmware/microblaze/apps/cruft/test1.c
 create mode 100644 firmware/microblaze/apps/cruft/test_db_spi.c
 create mode 100644 firmware/microblaze/apps/cruft/test_i2c.c
 create mode 100644 firmware/microblaze/apps/cruft/test_lsadc.c
 create mode 100644 firmware/microblaze/apps/cruft/test_lsdac.c
 create mode 100644 firmware/microblaze/apps/cruft/test_phy_comm.c
 create mode 100644 firmware/microblaze/apps/cruft/test_ram.c
 create mode 100644 firmware/microblaze/apps/cruft/test_sd.c
 create mode 100644 firmware/microblaze/apps/cruft/timer_test.c
 create mode 100644 firmware/microblaze/apps/cruft/tx_standalone.c
 delete mode 100644 firmware/microblaze/apps/double_buffer_fragment.c
 delete mode 100644 firmware/microblaze/apps/echo.c
 delete mode 100644 firmware/microblaze/apps/eth_serdes.c
 delete mode 100644 firmware/microblaze/apps/factory_test.c
 delete mode 100644 firmware/microblaze/apps/gen_eth_packets.c
 delete mode 100644 firmware/microblaze/apps/gen_pause_frames.c
 delete mode 100644 firmware/microblaze/apps/hello.c
 delete mode 100644 firmware/microblaze/apps/ibs_rx_test.c
 delete mode 100644 firmware/microblaze/apps/ibs_tx_test.c
 delete mode 100644 firmware/microblaze/apps/mimo_app_common_v2.c
 delete mode 100644 firmware/microblaze/apps/mimo_app_common_v2.h
 delete mode 100644 firmware/microblaze/apps/mimo_tx.c
 delete mode 100644 firmware/microblaze/apps/mimo_tx_slave.c
 delete mode 100644 firmware/microblaze/apps/rcv_eth_packets.c
 delete mode 100644 firmware/microblaze/apps/read_dbids.c
 delete mode 100644 firmware/microblaze/apps/sd_bounce.c
 delete mode 100644 firmware/microblaze/apps/sd_gentest.c
 delete mode 100644 firmware/microblaze/apps/serdes_to_dsp.c
 delete mode 100644 firmware/microblaze/apps/serdes_txrx.c
 delete mode 100644 firmware/microblaze/apps/set_hw_rev.c
 delete mode 100644 firmware/microblaze/apps/test1.c
 delete mode 100644 firmware/microblaze/apps/test_db_spi.c
 delete mode 100644 firmware/microblaze/apps/test_i2c.c
 delete mode 100644 firmware/microblaze/apps/test_lsadc.c
 delete mode 100644 firmware/microblaze/apps/test_lsdac.c
 delete mode 100644 firmware/microblaze/apps/test_phy_comm.c
 delete mode 100644 firmware/microblaze/apps/test_ram.c
 delete mode 100644 firmware/microblaze/apps/test_sd.c
 delete mode 100644 firmware/microblaze/apps/timer_test.c
 delete mode 100644 firmware/microblaze/apps/tx_standalone.c
 delete mode 120000 firmware/microblaze/config.guess
 delete mode 120000 firmware/microblaze/config.sub
 delete mode 100644 firmware/microblaze/include/.gitignore
 delete mode 100644 firmware/microblaze/include/Makefile.am
 delete mode 100644 firmware/microblaze/include/compiler.h
 delete mode 100644 firmware/microblaze/include/net/.gitignore
 delete mode 100644 firmware/microblaze/include/net/Makefile.am
 delete mode 100644 firmware/microblaze/include/net/eth_mac_addr.h
 delete mode 100644 firmware/microblaze/include/net/padded_eth_hdr.h
 delete mode 100644 firmware/microblaze/include/net/socket_address.h
 delete mode 100644 firmware/microblaze/include/usrp2_clock_bits.h
 delete mode 100644 firmware/microblaze/include/usrp2_fpga_regs.h
 delete mode 100644 firmware/microblaze/include/usrp2_i2c_addr.h
 delete mode 100644 firmware/microblaze/include/usrp2_types.h
 delete mode 100644 firmware/microblaze/include/vrt/bits.h
 delete mode 100644 firmware/microblaze/include/vrt/types.h
 delete mode 100644 firmware/microblaze/lib/.gitignore
 delete mode 100644 firmware/microblaze/lib/Makefile.am
 create mode 100644 firmware/microblaze/lib/Makefile.inc
 create mode 100644 firmware/microblaze/lib/clock_bits.h
 create mode 100644 firmware/microblaze/lib/compiler.h
 delete mode 100644 firmware/microblaze/lib/eth_phy.h
 delete mode 100644 firmware/microblaze/lib/ethernet.c
 delete mode 100644 firmware/microblaze/lib/memory_map.h
 create mode 100644 firmware/microblaze/lib/net/.gitignore
 create mode 100644 firmware/microblaze/lib/net/eth_mac_addr.h
 create mode 100644 firmware/microblaze/lib/net/padded_eth_hdr.h
 create mode 100644 firmware/microblaze/lib/net/socket_address.h
 delete mode 100644 firmware/microblaze/lib/sd.c
 delete mode 100644 firmware/microblaze/lib/sd.h
 create mode 100644 firmware/microblaze/usrp2/.gitignore
 create mode 100644 firmware/microblaze/usrp2/Makefile.am
 create mode 100644 firmware/microblaze/usrp2/eth_phy.h
 create mode 100644 firmware/microblaze/usrp2/ethernet.c
 create mode 100644 firmware/microblaze/usrp2/memory_map.h
 create mode 100644 firmware/microblaze/usrp2/sd.c
 create mode 100644 firmware/microblaze/usrp2/sd.h

(limited to 'host/lib')

diff --git a/firmware/microblaze/.gitignore b/firmware/microblaze/.gitignore
index 068f01838..e867fe87c 100644
--- a/firmware/microblaze/.gitignore
+++ b/firmware/microblaze/.gitignore
@@ -5,6 +5,8 @@
 /*.log
 /*.rom
 /.deps
+/*.guess
+/*.sub
 /Makefile
 /Makefile.in
 /aclocal.m4
diff --git a/firmware/microblaze/Makefile.am b/firmware/microblaze/Makefile.am
index 676c4fe42..6316b31a2 100644
--- a/firmware/microblaze/Makefile.am
+++ b/firmware/microblaze/Makefile.am
@@ -22,6 +22,5 @@ include $(top_srcdir)/Makefile.common
 EXTRA_DIST = \
 	u2_flash_tool
 
-SUBDIRS = include lib apps
-
-
+SUBDIRS = \
+	usrp2
diff --git a/firmware/microblaze/Makefile.common b/firmware/microblaze/Makefile.common
index 3d0f540d8..ceb6a553a 100644
--- a/firmware/microblaze/Makefile.common
+++ b/firmware/microblaze/Makefile.common
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+include $(top_srcdir)/lib/Makefile.inc
+
 ########################################################################
 # lwIP header include dirs
 ########################################################################
@@ -28,13 +30,6 @@ LWIP_INCLUDES = \
 	-I$(LWIPDIR)/src/include \
 	-I$(LWIPDIR)/src/include/ipv4
 
-########################################################################
-# local include dirs
-########################################################################
-LOCAL_INCLUDES = \
-	-I$(top_srcdir)/include \
-	-I$(top_srcdir)/lib
-
 ########################################################################
 # misc flags for the mb-gcc compiler
 ########################################################################
@@ -42,8 +37,6 @@ MBGCC_CFLAGS = \
 	--std=gnu99 -Wall -Werror-implicit-function-declaration \
 	-mxl-soft-div -msoft-float -mxl-soft-mul -mxl-barrel-shift
 
-MBGCC_LFLAGS = -Wl,-defsym -Wl,_STACK_SIZE=3072
-
 ########################################################################
 # define for the hal io (FIXME move?)
 ########################################################################
@@ -51,31 +44,39 @@ MBGCC_LFLAGS = -Wl,-defsym -Wl,_STACK_SIZE=3072
 HAL_IO = -DHAL_IO_USES_UART 
 
 ########################################################################
-# set the cflags and ldflags
+# common cflags and ldflags
 ########################################################################
-AM_CFLAGS = $(MBGCC_CFLAGS) $(LOCAL_INCLUDES) $(LWIP_INCLUDES) $(HAL_IO)
+COMMON_CFLAGS = \
+	-I$(top_srcdir)/../../host/lib/usrp \
+	-I$(top_srcdir)/lib \
+	$(MBGCC_CFLAGS) \
+	$(LWIP_INCLUDES) \
+	$(HAL_IO)
 
-AM_LDFLAGS = $(MBGCC_LFLAGS)
+COMMON_LFLAGS = \
+	-Wl,-Map -Wl,$(@:.elf=.map)
 
 ########################################################################
 # Common stuff for building top level microblaze images
 ########################################################################
-AM_LDFLAGS += -Wl,-Map -Wl,$(@:.elf=.map)
-
-%.bin : %.elf
+.elf.bin:
 	$(MB_OBJCOPY) -O binary $< $@
 
-%.dump : %.elf
+.elf.dump:
 	$(MB_OBJDUMP) -DSC $< > $@
 
-%.rom : %.bin
+.bin.rom:
 	$(HEXDUMP) -v -e'1/1 "%.2X\n"' $< > $@
 
+.elf.ihx:
+	$(MB_OBJCOPY) -O ihex $(COMMON_IHX_ARGS) $< $@
+
 _generated_from_elf = \
 	$(noinst_PROGRAMS:.elf=.map) \
 	$(noinst_PROGRAMS:.elf=.bin) \
 	$(noinst_PROGRAMS:.elf=.dump) \
-	$(noinst_PROGRAMS:.elf=.rom)
+	$(noinst_PROGRAMS:.elf=.rom) \
+	$(noinst_PROGRAMS:.elf=.ihx)
 
 noinst_DATA = $(_generated_from_elf)
 
diff --git a/firmware/microblaze/apps/.gitignore b/firmware/microblaze/apps/.gitignore
deleted file mode 100644
index 968b04cd7..000000000
--- a/firmware/microblaze/apps/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/*.elf
-/*.bin
-/*.dump
-/*.log
-/*.rom
-/*.map
-/Makefile
-/Makefile.in
diff --git a/firmware/microblaze/apps/Makefile.am b/firmware/microblaze/apps/Makefile.am
deleted file mode 100644
index a4f79935b..000000000
--- a/firmware/microblaze/apps/Makefile.am
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# Copyright 2010 Ettus Research LLC
-#
-# Copyright 2007,2008 Free Software Foundation, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-include $(top_srcdir)/Makefile.common
-
-LDADD = $(top_srcdir)/lib/libu2fw.a
-
-AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp
-
-noinst_PROGRAMS = txrx_uhd.elf
-
-#	blink_leds \
-#	blink_leds2 \
-#	buf_ram_test \
-#	burn_dbsrx_eeprom \
-#	can_i_sub \
-#	echo \
-#	hello \
-#	read_dbids \
-#	set_hw_rev \
-#	test1 \
-#	test_db_spi \
-#	test_i2c \
-#	test_sd \
-#	test_ram \
-#	test_phy_comm \
-#	test_lsadc \
-#	test_lsdac \
-#	timer_test \
-#	txrx \
-#	burnrev30 \
-#	burnrev31 \
-#	burnrev40 \
-#	sd_gentest \
-#	sd_bounce
-#
-
-#nononono =  \
-#	eth_serdes \
-#	gen_eth_packets \
-#	rcv_eth_packets \
-#	tx_standalone \
-#	factory_test \
-#	serdes_txrx \
-#	mimo_tx \
-#	mimo_tx_slave \
-#	ibs_rx_test \
-#	ibs_tx_test
-
-# tx_drop_SOURCES = tx_drop.c app_common.c
-# tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c
-# tx_drop2_SOURCES = tx_drop2.c app_common.c
-txrx_uhd_elf_SOURCES = txrx_uhd.c
-# app_common_v2.c
-#factory_test_SOURCES = factory_test.c app_common_v2.c
-#eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c
-#serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c
-#mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c
-#mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c
-
-#noinst_HEADERS = \
-#        app_common_v2.h \
-#        app_passthru_v2.h \
-#        mimo_app_common_v2.h
-#
-
diff --git a/firmware/microblaze/apps/app_passthru_v2.c b/firmware/microblaze/apps/app_passthru_v2.c
deleted file mode 100644
index 406c56b3b..000000000
--- a/firmware/microblaze/apps/app_passthru_v2.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "app_passthru_v2.h"
-#include "buffer_pool.h"
-#include "memcpy_wa.h"
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "print_rmon_regs.h"
-#include "db.h"
-#include "clocks.h"
-#include <string.h>
-
-volatile bool link_is_up = false;	// eth handler sets this
-
-
-// If this is non-zero, this dbsm could be writing to the ethernet
-dbsm_t *ac_could_be_sending_to_eth;
-
-//static unsigned char exp_seqno = 0;
-
-void
-set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
-{
-  reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
-  reply_pkt->ehdr.src = *ethernet_mac_addr();
-  reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
-  reply_pkt->thdr.flags = 0;
-  reply_pkt->thdr.fifo_status = 0;	// written by protocol engine
-  reply_pkt->thdr.seqno = 0;		// written by protocol engine
-  reply_pkt->thdr.ack = 0;		// written by protocol engine
-  u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
-  reply_pkt->fixed.timestamp = timer_regs->time;
-}
-
-static void
-send_reply(unsigned char *reply, size_t reply_len)
-{
-  if (reply_len < 64)
-    reply_len = 64;
-
-  // wait for buffer to become idle
-  hal_set_leds(0x4, 0x4);
-  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
-    ;
-  hal_set_leds(0x0, 0x4);
-
-  // copy reply into CPU_TX_BUF
-  memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
-
-  // wait until nobody else is sending to the ethernet
-  if (ac_could_be_sending_to_eth){
-    hal_set_leds(0x8, 0x8);
-    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
-    hal_set_leds(0x0, 0x8);
-  }
-
-  // fire it off
-  bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4);
-
-  // wait for it to complete (not long, it's a small pkt)
-  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
-    ;
-
-  bp_clear_buf(CPU_TX_BUF);
-}
-
-
-static size_t
-op_id_cmd(const op_generic_t *p,
-	  void *reply_payload, size_t reply_payload_space)
-{
-  op_id_reply_t *r = (op_id_reply_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))	// no room
-    return 0;
-
-  // Build reply subpacket
-
-  r->opcode = OP_ID_REPLY;
-  r->len = sizeof(op_id_reply_t);
-  r->rid = p->rid;
-  r->addr = *ethernet_mac_addr();
-  r->hw_rev = 0x0000;	// FIXME
-  // r->fpga_md5sum = ;	// FIXME
-  // r->sw_md5sum = ;	// FIXME
-
-  // FIXME Add d'board info, including dbid, min/max gain, min/max freq
-
-  return r->len;
-}
-
-static size_t
-add_eop(void *reply_payload, size_t reply_payload_space)
-{
-  op_generic_t *r = (op_generic_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))		
-    return 0;					// no room
-
-  r->opcode = OP_EOP;
-  r->len = sizeof(*r);
-  r->rid = 0;
-  r->ok =  0;
-
-  return r->len;
-}
-
-bool
-handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
-{
-  unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
-  unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
-  int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
-
-  bool handled_it = false;
-
-  // initialize reply
-  memset(reply, 0, sizeof(reply));
-  set_reply_hdr((u2_eth_packet_t *) reply, pkt);
-
-  // point to beginning of payload (subpackets)
-  unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
-  int payload_len = len - sizeof(u2_eth_packet_t);
-
-  size_t subpktlen = 0;
-
-  while (payload_len >= sizeof(op_generic_t)){
-    const op_generic_t *gp = (const op_generic_t *) payload;
-    subpktlen = 0;
-
-    switch(gp->opcode){
-    case OP_EOP:		// end of subpackets
-      goto end_of_subpackets;
-
-    case OP_ID:
-      subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
-      handled_it = true;
-      break;
-
-    default:
-      if (0){
-	printf("\npassing on %d\n", gp->opcode);
-      }
-      break;
-    }
-
-    int t = (gp->len + 3) & ~3;		// bump to a multiple of 4
-    payload += t;
-    payload_len -= t;
-
-    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
-    reply_payload += subpktlen;
-    reply_payload_space -= subpktlen;
-  }
-
- end_of_subpackets:
-
-  if (handled_it){
-    // add the EOP marker
-    subpktlen = add_eop(reply_payload, reply_payload_space);
-    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
-    reply_payload += subpktlen;
-    reply_payload_space -= subpktlen;
-
-    send_reply(reply, reply_payload - reply);
-  }
-
-  return handled_it;
-}
-
-
-/*
- * Called when an ethernet packet is received.
- * Return true if we handled it here, otherwise
- * it'll be passed on to the DSP Tx pipe
- */
-bool
-eth_pkt_inspector(dbsm_t *sm, int bufno)
-{
-  u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
-  size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
-
-  //static size_t last_len = 0;
-
-  // hal_toggle_leds(0x1);
-
-  // inspect rcvd frame and figure out what do do.
-
-  if (pkt->ehdr.ethertype != U2_ETHERTYPE)
-    return true;	// ignore, probably bogus PAUSE frame from MAC
-
-  int chan = u2p_chan(&pkt->fixed);
-
-  switch (chan){
-  case CONTROL_CHAN:
-    return handle_control_chan_frame(pkt, byte_len);
-    break;
-
-  case 0:
-  default:
-#if 0
-    if (last_len != 0){
-      if (byte_len != last_len){
-	printf("Len: %d last: %d\n", byte_len, last_len);
-      }
-    }
-    last_len = byte_len;
-
-    if((pkt->thdr.seqno) == exp_seqno){
-      exp_seqno++;
-      //putchar('.');
-    }
-    else {
-      // putchar('S');
-      //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
-      exp_seqno = pkt->thdr.seqno + 1;
-    }
-#endif
-    return false;	// pass it on to Tx DSP
-    break;
-  }
-}
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  link_is_up = speed != 0;
-  hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45);
-  printf("\neth link changed: speed = %d\n", speed);
-}
diff --git a/firmware/microblaze/apps/app_passthru_v2.h b/firmware/microblaze/apps/app_passthru_v2.h
deleted file mode 100644
index 3904c670f..000000000
--- a/firmware/microblaze/apps/app_passthru_v2.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_APP_COMMON_H
-#define INCLUDED_APP_COMMON_H
-
-#include <stdbool.h>
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include <stddef.h>
-#include <db.h>
-
-#define CPU_TX_BUF 	7	// cpu -> eth
-
-#define	_AL4 __attribute__((aligned (4)))
-
-extern volatile bool link_is_up;	// eth handler sets this
-
-
-// If there's a dbsm that sends to the ethernet, put it's address here
-extern dbsm_t *ac_could_be_sending_to_eth;
-
-
-void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
-
-/*
- * Called when an ethernet packet is received.
- * Return true if we handled it here, otherwise
- * it'll be passed on to the DSP Tx pipe
- */
-bool eth_pkt_inspector(dbsm_t *sm, int bufno);
-
-void link_changed_callback(int speed);
-
-bool handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
-
-#endif /* INCLUDED_APP_COMMON_H */
diff --git a/firmware/microblaze/apps/blink_leds.c b/firmware/microblaze/apps/blink_leds.c
deleted file mode 100644
index 682ca8db2..000000000
--- a/firmware/microblaze/apps/blink_leds.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include "nonstdio.h"
-
-int
-main(void)
-{
-  int	counter = 0;
-
-  u2_init();
-  
-  putstr("blink_leds\n");
-  while(1){
-    output_regs->leds = (counter++ & 0x3);
-  }
-  
-  return 0;
-}
diff --git a/firmware/microblaze/apps/blink_leds2.c b/firmware/microblaze/apps/blink_leds2.c
deleted file mode 100644
index 13e78afb3..000000000
--- a/firmware/microblaze/apps/blink_leds2.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include "pic.h"
-#include "nonstdio.h"
-
-//#define DELTA_T  (MASTER_CLK_RATE/2)	// 0.5s (10ns per tick)
-#define DELTA_T  5000  		// 5 us (10ns per tick)
-
-
-void
-timer_handler(unsigned irq)
-{
-  hal_set_timeout(DELTA_T);	// schedule next timeout
-  hal_toggle_leds(0x2);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("blink_leds2\n");
-  pic_register_handler(IRQ_ONETIME, timer_handler);
-  hal_set_timeout(DELTA_T);	// schedule next timeout
-
-  while(1){
-    hal_toggle_leds(0x1);
-  }
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/buf_ram_test.c b/firmware/microblaze/apps/buf_ram_test.c
deleted file mode 100644
index 1aca2aec5..000000000
--- a/firmware/microblaze/apps/buf_ram_test.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include <stdbool.h>
-#include "nonstdio.h"
-#include "hal_io.h"
-#include "mdelay.h"
-
-
-static void
-write_bufs(void)
-{
-  int	i, n;
-  int	counter = 0;
-
-  for (n = 0; n < NBUFFERS; n++){
-    volatile int *p = buffer_ram(n);
-    for (i = 0; i < BP_NLINES; i++)
-      p[i] = counter++;
-  }
-}
-
-// return number of errors detected
-static int
-check_bufs(void)
-{
-  int	i, n;
-  int	counter = 0;
-  int	nerrors = 0;
-
-  for (n = 0; n < NBUFFERS; n++){
-    volatile int *p = buffer_ram(n);
-    for (i = 0; i < BP_NLINES; i++, counter++){
-      int rd = p[i];
-      if (rd != counter){
-	putchar('b');
-	putchar(n + '0');
-	putchar('[');
-	puthex16(i);
-	putstr("] exp: ");
-	puthex32(counter);
-	putstr(" got: ");
-	puthex32_nl(rd);
-	nerrors++;
-      }
-    }
-  }
-  return nerrors;
-}
-
-
-int
-main(void)
-{
-  u2_init();
-
-  output_regs->leds = 0;
-
-  write_bufs();
-  int nerrors = check_bufs();
-
-  if (nerrors == 0){
-    output_regs->leds = 0x3;		// leds on  -> PASS
-    putstr("PASS\n");
-  }
-  else {
-    output_regs->leds = 0x0;		// leds off -> FAIL
-    putstr("FAIL\n");
-  }
-
-  hal_finish();
-  return 0;
-}
diff --git a/firmware/microblaze/apps/burn_dbsrx_eeprom.c b/firmware/microblaze/apps/burn_dbsrx_eeprom.c
deleted file mode 100644
index 116d4d8d0..000000000
--- a/firmware/microblaze/apps/burn_dbsrx_eeprom.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "i2c.h"
-#include "usrp2_i2c_addr.h"
-#include "mdelay.h"
-#include "hal_io.h"
-#include "nonstdio.h"
-#include <stdbool.h>
-
-
-
-int read_dboard_eeprom(int i2c_addr);
-
-
-#define USRP_DBID_DBS_RX          	 0x0002
-#define USRP_DBID_DBS_RX_WITH_CLOCK_MOD  0x000d
-
-const char dbs_rx_rev2_eeprom[] = {
-  0xdb, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18
-};
-
-#define	LED_VALS   (LED_A | LED_B | LED_C | LED_D)
-#define	LED_MASK   (LED_A | LED_B | LED_C | LED_D)
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("\nburn_dbsrx_eeprom\n");
-
-  hal_set_leds(0, ~0);	// all off
-
-  int i2c_addr = I2C_ADDR_RX_A;
-  int dbid = read_dboard_eeprom(i2c_addr);
-  bool ok;
-  const char *msg = 0;
-
-  switch (dbid){
-  case -1:
-    msg = "No RX daughterboard found";
-    goto bad;
-
-  case -2:
-    msg = "Invalid RX EEPROM contents";
-    goto bad;
-
-  case USRP_DBID_DBS_RX_WITH_CLOCK_MOD:
-    msg = "RX Daughterboard already reports being a DBS RX w/ CLOCK_MOD";
-    goto good;
-
-  case USRP_DBID_DBS_RX:
-    // Says it's a DBS_RX, attempt to burn the EEPROM
-    ok = eeprom_write(i2c_addr, 0,
-		      dbs_rx_rev2_eeprom, sizeof(dbs_rx_rev2_eeprom));
-    if (ok){
-      msg = "Successfully programmed db as DBS RX Rev 2.1";
-      goto good;
-    }
-    else {
-      msg = "Failed to write daugherboard eeprom";
-      goto bad;
-    }
-
-  default:
-    msg = "Daughterboard is not a DBS RX; ignored";
-    goto bad;
-  }
-  
- good:
-  puts(msg);
-  hal_set_leds(LED_VALS, LED_MASK);
-  while (1)
-    ;
-
- bad:
-  puts(msg);
-  while(1){
-    hal_toggle_leds(LED_VALS);
-    mdelay(50);
-  }
-}
diff --git a/firmware/microblaze/apps/burnrev30.c b/firmware/microblaze/apps/burnrev30.c
deleted file mode 100644
index 40fa53e34..000000000
--- a/firmware/microblaze/apps/burnrev30.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-#include <clocks.h>
-#include "sd.h"
-#include "mdelay.h"
-
-#define HW_REV_MAJOR 3
-#define HW_REV_MINOR 0
-
-int test_ram()
-{
-  int i,j,k;
-  output_regs->ram_page = 1<<10;
-  
-  extram[0] = 0xDEADBEEF;
-  extram[1] = 0xF00D1234;
-  extram[7] = 0x76543210;
-  
-  output_regs->ram_page = 2<<10;
-  extram[7] = 0x55555555;
-  extram[1] = 0xaaaaaaaa;
-  extram[0] = 0xeeeeeeee;
-  
-  output_regs->ram_page = 1<<10;
-  
-  i = extram[0];
-  k = extram[1];
-  j = extram[7];
-  
-  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
-    puts("RAM FAIL1!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  
-  output_regs->ram_page = 2<<10;
-
-  j = extram[7];
-  k = extram[1];
-  i = extram[0];
-
-  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
-    puts("RAM FAIL2!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  return 1;
-}
-
-int test_sd()
-{
-  int i = sd_init();
-  if(i==0) {
-    puts("FAILED INIT of Card\n");
-    return 0;
-  }
-  
-  unsigned char buf[512];
-  i = sd_read_block(2048,buf);
-  if(i == 0) {
-    puts("READ Command Rejected\n");
-    return 0;
-  }
-  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
-    ;
-  else {
-    puts("Read bad data from SD Card\n");
-    return 0;
-  }
-  return 1;
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nFactory Test, Board Rev 3.0\n");
-
-  bool ok = true;
-  unsigned char maj = HW_REV_MAJOR;
-  unsigned char min = HW_REV_MINOR;
-  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
-  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
-
-  putstr("\nset_hw_rev\n");
-  if (ok)
-    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-  else {
-    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-    hal_finish();
-    return 0;
-  }
-
-  if(test_sd())
-    puts("SD OK\n");
-  else {
-    puts("SD FAIL\n");
-    //hal_finish();
-    //return 0;
-  }
-  if(test_ram())
-    puts("RAM OK\n");
-  else {
-    puts("RAM FAIL\n");
-    hal_finish();
-    return 0;
-  }
-
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
-
-  while (!clocks_lock_detect()) {
-    puts("No Lock");
-    mdelay(1000);
-  }
-  puts("Clock Locked\n");
-
-}
diff --git a/firmware/microblaze/apps/burnrev31.c b/firmware/microblaze/apps/burnrev31.c
deleted file mode 100644
index f6b08d187..000000000
--- a/firmware/microblaze/apps/burnrev31.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-#include <clocks.h>
-#include "sd.h"
-#include "mdelay.h"
-
-#define HW_REV_MAJOR 3
-#define HW_REV_MINOR 1
-
-int test_ram()
-{
-  int i,j,k;
-  output_regs->ram_page = 1<<10;
-  
-  extram[0] = 0xDEADBEEF;
-  extram[1] = 0xF00D1234;
-  extram[7] = 0x76543210;
-  
-  output_regs->ram_page = 2<<10;
-  extram[7] = 0x55555555;
-  extram[1] = 0xaaaaaaaa;
-  extram[0] = 0xeeeeeeee;
-  
-  output_regs->ram_page = 1<<10;
-  
-  i = extram[0];
-  k = extram[1];
-  j = extram[7];
-  
-  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
-    puts("RAM FAIL1!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  
-  output_regs->ram_page = 2<<10;
-
-  j = extram[7];
-  k = extram[1];
-  i = extram[0];
-
-  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
-    puts("RAM FAIL2!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  return 1;
-}
-
-int test_sd()
-{
-  int i = sd_init();
-  if(i==0) {
-    puts("FAILED INIT of Card\n");
-    return 0;
-  }
-  
-  unsigned char buf[512];
-  i = sd_read_block(2048,buf);
-  if(i == 0) {
-    puts("READ Command Rejected\n");
-    return 0;
-  }
-  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
-    ;
-  else {
-    puts("Read bad data from SD Card\n");
-    return 0;
-  }
-  return 1;
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nFactory Test, Board Rev 3.1\n");
-
-  bool ok = true;
-  unsigned char maj = HW_REV_MAJOR;
-  unsigned char min = HW_REV_MINOR;
-  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
-  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
-
-  putstr("\nset_hw_rev\n");
-  if (ok)
-    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-  else {
-    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-    hal_finish();
-    return 0;
-  }
-
-  if(test_sd())
-    puts("SD OK\n");
-  else {
-    puts("SD FAIL\n");
-    //hal_finish();
-    //return 0;
-  }
-  if(test_ram())
-    puts("RAM OK\n");
-  else {
-    puts("RAM FAIL\n");
-    hal_finish();
-    return 0;
-  }
-
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
-
-  while (!clocks_lock_detect()) {
-    puts("No Lock");
-    mdelay(1000);
-  }
-  puts("Clock Locked\n");
-
-}
diff --git a/firmware/microblaze/apps/burnrev40.c b/firmware/microblaze/apps/burnrev40.c
deleted file mode 100644
index 362270961..000000000
--- a/firmware/microblaze/apps/burnrev40.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-#include <clocks.h>
-#include "sd.h"
-#include "mdelay.h"
-
-#define HW_REV_MAJOR 4
-#define HW_REV_MINOR 0
-
-int test_ram()
-{
-  int i,j,k;
-  output_regs->ram_page = 1<<10;
-  
-  extram[0] = 0xDEADBEEF;
-  extram[1] = 0xF00D1234;
-  extram[7] = 0x76543210;
-  
-  output_regs->ram_page = 2<<10;
-  extram[7] = 0x55555555;
-  extram[1] = 0xaaaaaaaa;
-  extram[0] = 0xeeeeeeee;
-  
-  output_regs->ram_page = 1<<10;
-  
-  i = extram[0];
-  k = extram[1];
-  j = extram[7];
-  
-  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
-    puts("RAM FAIL1!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  
-  output_regs->ram_page = 2<<10;
-
-  j = extram[7];
-  k = extram[1];
-  i = extram[0];
-
-  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
-    puts("RAM FAIL2!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  return 1;
-}
-
-int test_sd()
-{
-  int i = sd_init();
-  if(i==0) {
-    puts("FAILED INIT of Card\n");
-    return 0;
-  }
-  
-  unsigned char buf[512];
-  i = sd_read_block(2048,buf);
-  if(i == 0) {
-    puts("READ Command Rejected\n");
-    return 0;
-  }
-  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
-    ;
-  else {
-    puts("Read bad data from SD Card\n");
-    return 0;
-  }
-  return 1;
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nFactory Test, Board Rev 4.0\n");
-
-  bool ok = true;
-  unsigned char maj = HW_REV_MAJOR;
-  unsigned char min = HW_REV_MINOR;
-  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
-  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
-
-  putstr("\nset_hw_rev\n");
-  if (ok)
-    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-  else {
-    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-    hal_finish();
-    return 0;
-  }
-
-  if(test_sd())
-    puts("SD OK\n");
-  else {
-    puts("SD FAIL\n");
-    //hal_finish();
-    //return 0;
-  }
-  if(test_ram())
-    puts("RAM OK\n");
-  else {
-    puts("RAM FAIL\n");
-    hal_finish();
-    return 0;
-  }
-
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
-
-  while (!clocks_lock_detect()) {
-    puts("No Lock");
-    mdelay(1000);
-  }
-  puts("Clock Locked\n");
-
-}
diff --git a/firmware/microblaze/apps/can_i_sub.c b/firmware/microblaze/apps/can_i_sub.c
deleted file mode 100644
index ed49791f0..000000000
--- a/firmware/microblaze/apps/can_i_sub.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <u2_init.h>
-#include <nonstdio.h>
-
-//typedef long long int64_t;
-
-
-int64_t sub(int64_t a, int64_t b);
-void print(int64_t d);
-
-int main(void)
-{
-  u2_init();
-
-  int64_t d = sub(462550990848000LL, 462028800000000LL);
-  print_uint64(d);
-  newline();
-  return 0;
-}
-
-int64_t sub(int64_t a, int64_t b)
-{
-  return a - b;
-}
-
-
diff --git a/firmware/microblaze/apps/cruft/Makefile.am b/firmware/microblaze/apps/cruft/Makefile.am
new file mode 100644
index 000000000..a4f79935b
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/Makefile.am
@@ -0,0 +1,82 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# Copyright 2007,2008 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+LDADD = $(top_srcdir)/lib/libu2fw.a
+
+AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp
+
+noinst_PROGRAMS = txrx_uhd.elf
+
+#	blink_leds \
+#	blink_leds2 \
+#	buf_ram_test \
+#	burn_dbsrx_eeprom \
+#	can_i_sub \
+#	echo \
+#	hello \
+#	read_dbids \
+#	set_hw_rev \
+#	test1 \
+#	test_db_spi \
+#	test_i2c \
+#	test_sd \
+#	test_ram \
+#	test_phy_comm \
+#	test_lsadc \
+#	test_lsdac \
+#	timer_test \
+#	txrx \
+#	burnrev30 \
+#	burnrev31 \
+#	burnrev40 \
+#	sd_gentest \
+#	sd_bounce
+#
+
+#nononono =  \
+#	eth_serdes \
+#	gen_eth_packets \
+#	rcv_eth_packets \
+#	tx_standalone \
+#	factory_test \
+#	serdes_txrx \
+#	mimo_tx \
+#	mimo_tx_slave \
+#	ibs_rx_test \
+#	ibs_tx_test
+
+# tx_drop_SOURCES = tx_drop.c app_common.c
+# tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c
+# tx_drop2_SOURCES = tx_drop2.c app_common.c
+txrx_uhd_elf_SOURCES = txrx_uhd.c
+# app_common_v2.c
+#factory_test_SOURCES = factory_test.c app_common_v2.c
+#eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c
+#serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c
+#mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c
+#mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c
+
+#noinst_HEADERS = \
+#        app_common_v2.h \
+#        app_passthru_v2.h \
+#        mimo_app_common_v2.h
+#
+
diff --git a/firmware/microblaze/apps/cruft/app_passthru_v2.c b/firmware/microblaze/apps/cruft/app_passthru_v2.c
new file mode 100644
index 000000000..406c56b3b
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/app_passthru_v2.c
@@ -0,0 +1,251 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app_passthru_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include "db.h"
+#include "clocks.h"
+#include <string.h>
+
+volatile bool link_is_up = false;	// eth handler sets this
+
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+//static unsigned char exp_seqno = 0;
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+  reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+  reply_pkt->ehdr.src = *ethernet_mac_addr();
+  reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+  reply_pkt->thdr.flags = 0;
+  reply_pkt->thdr.fifo_status = 0;	// written by protocol engine
+  reply_pkt->thdr.seqno = 0;		// written by protocol engine
+  reply_pkt->thdr.ack = 0;		// written by protocol engine
+  u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+  reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+  if (reply_len < 64)
+    reply_len = 64;
+
+  // wait for buffer to become idle
+  hal_set_leds(0x4, 0x4);
+  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+    ;
+  hal_set_leds(0x0, 0x4);
+
+  // copy reply into CPU_TX_BUF
+  memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+  // wait until nobody else is sending to the ethernet
+  if (ac_could_be_sending_to_eth){
+    hal_set_leds(0x8, 0x8);
+    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+    hal_set_leds(0x0, 0x8);
+  }
+
+  // fire it off
+  bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4);
+
+  // wait for it to complete (not long, it's a small pkt)
+  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
+    ;
+
+  bp_clear_buf(CPU_TX_BUF);
+}
+
+
+static size_t
+op_id_cmd(const op_generic_t *p,
+	  void *reply_payload, size_t reply_payload_space)
+{
+  op_id_reply_t *r = (op_id_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))	// no room
+    return 0;
+
+  // Build reply subpacket
+
+  r->opcode = OP_ID_REPLY;
+  r->len = sizeof(op_id_reply_t);
+  r->rid = p->rid;
+  r->addr = *ethernet_mac_addr();
+  r->hw_rev = 0x0000;	// FIXME
+  // r->fpga_md5sum = ;	// FIXME
+  // r->sw_md5sum = ;	// FIXME
+
+  // FIXME Add d'board info, including dbid, min/max gain, min/max freq
+
+  return r->len;
+}
+
+static size_t
+add_eop(void *reply_payload, size_t reply_payload_space)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))		
+    return 0;					// no room
+
+  r->opcode = OP_EOP;
+  r->len = sizeof(*r);
+  r->rid = 0;
+  r->ok =  0;
+
+  return r->len;
+}
+
+bool
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+  unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
+  unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
+  int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
+
+  bool handled_it = false;
+
+  // initialize reply
+  memset(reply, 0, sizeof(reply));
+  set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+
+  // point to beginning of payload (subpackets)
+  unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+  int payload_len = len - sizeof(u2_eth_packet_t);
+
+  size_t subpktlen = 0;
+
+  while (payload_len >= sizeof(op_generic_t)){
+    const op_generic_t *gp = (const op_generic_t *) payload;
+    subpktlen = 0;
+
+    switch(gp->opcode){
+    case OP_EOP:		// end of subpackets
+      goto end_of_subpackets;
+
+    case OP_ID:
+      subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
+      handled_it = true;
+      break;
+
+    default:
+      if (0){
+	printf("\npassing on %d\n", gp->opcode);
+      }
+      break;
+    }
+
+    int t = (gp->len + 3) & ~3;		// bump to a multiple of 4
+    payload += t;
+    payload_len -= t;
+
+    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
+    reply_payload += subpktlen;
+    reply_payload_space -= subpktlen;
+  }
+
+ end_of_subpackets:
+
+  if (handled_it){
+    // add the EOP marker
+    subpktlen = add_eop(reply_payload, reply_payload_space);
+    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
+    reply_payload += subpktlen;
+    reply_payload_space -= subpktlen;
+
+    send_reply(reply, reply_payload - reply);
+  }
+
+  return handled_it;
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool
+eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+  u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+  size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+  //static size_t last_len = 0;
+
+  // hal_toggle_leds(0x1);
+
+  // inspect rcvd frame and figure out what do do.
+
+  if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+    return true;	// ignore, probably bogus PAUSE frame from MAC
+
+  int chan = u2p_chan(&pkt->fixed);
+
+  switch (chan){
+  case CONTROL_CHAN:
+    return handle_control_chan_frame(pkt, byte_len);
+    break;
+
+  case 0:
+  default:
+#if 0
+    if (last_len != 0){
+      if (byte_len != last_len){
+	printf("Len: %d last: %d\n", byte_len, last_len);
+      }
+    }
+    last_len = byte_len;
+
+    if((pkt->thdr.seqno) == exp_seqno){
+      exp_seqno++;
+      //putchar('.');
+    }
+    else {
+      // putchar('S');
+      //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
+      exp_seqno = pkt->thdr.seqno + 1;
+    }
+#endif
+    return false;	// pass it on to Tx DSP
+    break;
+  }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  link_is_up = speed != 0;
+  hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45);
+  printf("\neth link changed: speed = %d\n", speed);
+}
diff --git a/firmware/microblaze/apps/cruft/app_passthru_v2.h b/firmware/microblaze/apps/cruft/app_passthru_v2.h
new file mode 100644
index 000000000..3904c670f
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/app_passthru_v2.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include <stdbool.h>
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF 	7	// cpu -> eth
+
+#define	_AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up;	// eth handler sets this
+
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool eth_pkt_inspector(dbsm_t *sm, int bufno);
+
+void link_changed_callback(int speed);
+
+bool handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */
diff --git a/firmware/microblaze/apps/cruft/blink_leds.c b/firmware/microblaze/apps/cruft/blink_leds.c
new file mode 100644
index 000000000..682ca8db2
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/blink_leds.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "nonstdio.h"
+
+int
+main(void)
+{
+  int	counter = 0;
+
+  u2_init();
+  
+  putstr("blink_leds\n");
+  while(1){
+    output_regs->leds = (counter++ & 0x3);
+  }
+  
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/blink_leds2.c b/firmware/microblaze/apps/cruft/blink_leds2.c
new file mode 100644
index 000000000..13e78afb3
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/blink_leds2.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+//#define DELTA_T  (MASTER_CLK_RATE/2)	// 0.5s (10ns per tick)
+#define DELTA_T  5000  		// 5 us (10ns per tick)
+
+
+void
+timer_handler(unsigned irq)
+{
+  hal_set_timeout(DELTA_T);	// schedule next timeout
+  hal_toggle_leds(0x2);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("blink_leds2\n");
+  pic_register_handler(IRQ_ONETIME, timer_handler);
+  hal_set_timeout(DELTA_T);	// schedule next timeout
+
+  while(1){
+    hal_toggle_leds(0x1);
+  }
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/buf_ram_test.c b/firmware/microblaze/apps/cruft/buf_ram_test.c
new file mode 100644
index 000000000..1aca2aec5
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/buf_ram_test.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include <stdbool.h>
+#include "nonstdio.h"
+#include "hal_io.h"
+#include "mdelay.h"
+
+
+static void
+write_bufs(void)
+{
+  int	i, n;
+  int	counter = 0;
+
+  for (n = 0; n < NBUFFERS; n++){
+    volatile int *p = buffer_ram(n);
+    for (i = 0; i < BP_NLINES; i++)
+      p[i] = counter++;
+  }
+}
+
+// return number of errors detected
+static int
+check_bufs(void)
+{
+  int	i, n;
+  int	counter = 0;
+  int	nerrors = 0;
+
+  for (n = 0; n < NBUFFERS; n++){
+    volatile int *p = buffer_ram(n);
+    for (i = 0; i < BP_NLINES; i++, counter++){
+      int rd = p[i];
+      if (rd != counter){
+	putchar('b');
+	putchar(n + '0');
+	putchar('[');
+	puthex16(i);
+	putstr("] exp: ");
+	puthex32(counter);
+	putstr(" got: ");
+	puthex32_nl(rd);
+	nerrors++;
+      }
+    }
+  }
+  return nerrors;
+}
+
+
+int
+main(void)
+{
+  u2_init();
+
+  output_regs->leds = 0;
+
+  write_bufs();
+  int nerrors = check_bufs();
+
+  if (nerrors == 0){
+    output_regs->leds = 0x3;		// leds on  -> PASS
+    putstr("PASS\n");
+  }
+  else {
+    output_regs->leds = 0x0;		// leds off -> FAIL
+    putstr("FAIL\n");
+  }
+
+  hal_finish();
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c b/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c
new file mode 100644
index 000000000..116d4d8d0
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "i2c.h"
+#include "usrp2_i2c_addr.h"
+#include "mdelay.h"
+#include "hal_io.h"
+#include "nonstdio.h"
+#include <stdbool.h>
+
+
+
+int read_dboard_eeprom(int i2c_addr);
+
+
+#define USRP_DBID_DBS_RX          	 0x0002
+#define USRP_DBID_DBS_RX_WITH_CLOCK_MOD  0x000d
+
+const char dbs_rx_rev2_eeprom[] = {
+  0xdb, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18
+};
+
+#define	LED_VALS   (LED_A | LED_B | LED_C | LED_D)
+#define	LED_MASK   (LED_A | LED_B | LED_C | LED_D)
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("\nburn_dbsrx_eeprom\n");
+
+  hal_set_leds(0, ~0);	// all off
+
+  int i2c_addr = I2C_ADDR_RX_A;
+  int dbid = read_dboard_eeprom(i2c_addr);
+  bool ok;
+  const char *msg = 0;
+
+  switch (dbid){
+  case -1:
+    msg = "No RX daughterboard found";
+    goto bad;
+
+  case -2:
+    msg = "Invalid RX EEPROM contents";
+    goto bad;
+
+  case USRP_DBID_DBS_RX_WITH_CLOCK_MOD:
+    msg = "RX Daughterboard already reports being a DBS RX w/ CLOCK_MOD";
+    goto good;
+
+  case USRP_DBID_DBS_RX:
+    // Says it's a DBS_RX, attempt to burn the EEPROM
+    ok = eeprom_write(i2c_addr, 0,
+		      dbs_rx_rev2_eeprom, sizeof(dbs_rx_rev2_eeprom));
+    if (ok){
+      msg = "Successfully programmed db as DBS RX Rev 2.1";
+      goto good;
+    }
+    else {
+      msg = "Failed to write daugherboard eeprom";
+      goto bad;
+    }
+
+  default:
+    msg = "Daughterboard is not a DBS RX; ignored";
+    goto bad;
+  }
+  
+ good:
+  puts(msg);
+  hal_set_leds(LED_VALS, LED_MASK);
+  while (1)
+    ;
+
+ bad:
+  puts(msg);
+  while(1){
+    hal_toggle_leds(LED_VALS);
+    mdelay(50);
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/burnrev30.c b/firmware/microblaze/apps/cruft/burnrev30.c
new file mode 100644
index 000000000..40fa53e34
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/burnrev30.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <clocks.h>
+#include "sd.h"
+#include "mdelay.h"
+
+#define HW_REV_MAJOR 3
+#define HW_REV_MINOR 0
+
+int test_ram()
+{
+  int i,j,k;
+  output_regs->ram_page = 1<<10;
+  
+  extram[0] = 0xDEADBEEF;
+  extram[1] = 0xF00D1234;
+  extram[7] = 0x76543210;
+  
+  output_regs->ram_page = 2<<10;
+  extram[7] = 0x55555555;
+  extram[1] = 0xaaaaaaaa;
+  extram[0] = 0xeeeeeeee;
+  
+  output_regs->ram_page = 1<<10;
+  
+  i = extram[0];
+  k = extram[1];
+  j = extram[7];
+  
+  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
+    puts("RAM FAIL1!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  
+  output_regs->ram_page = 2<<10;
+
+  j = extram[7];
+  k = extram[1];
+  i = extram[0];
+
+  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
+    puts("RAM FAIL2!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  return 1;
+}
+
+int test_sd()
+{
+  int i = sd_init();
+  if(i==0) {
+    puts("FAILED INIT of Card\n");
+    return 0;
+  }
+  
+  unsigned char buf[512];
+  i = sd_read_block(2048,buf);
+  if(i == 0) {
+    puts("READ Command Rejected\n");
+    return 0;
+  }
+  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
+    ;
+  else {
+    puts("Read bad data from SD Card\n");
+    return 0;
+  }
+  return 1;
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nFactory Test, Board Rev 3.0\n");
+
+  bool ok = true;
+  unsigned char maj = HW_REV_MAJOR;
+  unsigned char min = HW_REV_MINOR;
+  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
+  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
+
+  putstr("\nset_hw_rev\n");
+  if (ok)
+    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+  else {
+    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+    hal_finish();
+    return 0;
+  }
+
+  if(test_sd())
+    puts("SD OK\n");
+  else {
+    puts("SD FAIL\n");
+    //hal_finish();
+    //return 0;
+  }
+  if(test_ram())
+    puts("RAM OK\n");
+  else {
+    puts("RAM FAIL\n");
+    hal_finish();
+    return 0;
+  }
+
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
+
+  while (!clocks_lock_detect()) {
+    puts("No Lock");
+    mdelay(1000);
+  }
+  puts("Clock Locked\n");
+
+}
diff --git a/firmware/microblaze/apps/cruft/burnrev31.c b/firmware/microblaze/apps/cruft/burnrev31.c
new file mode 100644
index 000000000..f6b08d187
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/burnrev31.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <clocks.h>
+#include "sd.h"
+#include "mdelay.h"
+
+#define HW_REV_MAJOR 3
+#define HW_REV_MINOR 1
+
+int test_ram()
+{
+  int i,j,k;
+  output_regs->ram_page = 1<<10;
+  
+  extram[0] = 0xDEADBEEF;
+  extram[1] = 0xF00D1234;
+  extram[7] = 0x76543210;
+  
+  output_regs->ram_page = 2<<10;
+  extram[7] = 0x55555555;
+  extram[1] = 0xaaaaaaaa;
+  extram[0] = 0xeeeeeeee;
+  
+  output_regs->ram_page = 1<<10;
+  
+  i = extram[0];
+  k = extram[1];
+  j = extram[7];
+  
+  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
+    puts("RAM FAIL1!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  
+  output_regs->ram_page = 2<<10;
+
+  j = extram[7];
+  k = extram[1];
+  i = extram[0];
+
+  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
+    puts("RAM FAIL2!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  return 1;
+}
+
+int test_sd()
+{
+  int i = sd_init();
+  if(i==0) {
+    puts("FAILED INIT of Card\n");
+    return 0;
+  }
+  
+  unsigned char buf[512];
+  i = sd_read_block(2048,buf);
+  if(i == 0) {
+    puts("READ Command Rejected\n");
+    return 0;
+  }
+  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
+    ;
+  else {
+    puts("Read bad data from SD Card\n");
+    return 0;
+  }
+  return 1;
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nFactory Test, Board Rev 3.1\n");
+
+  bool ok = true;
+  unsigned char maj = HW_REV_MAJOR;
+  unsigned char min = HW_REV_MINOR;
+  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
+  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
+
+  putstr("\nset_hw_rev\n");
+  if (ok)
+    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+  else {
+    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+    hal_finish();
+    return 0;
+  }
+
+  if(test_sd())
+    puts("SD OK\n");
+  else {
+    puts("SD FAIL\n");
+    //hal_finish();
+    //return 0;
+  }
+  if(test_ram())
+    puts("RAM OK\n");
+  else {
+    puts("RAM FAIL\n");
+    hal_finish();
+    return 0;
+  }
+
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
+
+  while (!clocks_lock_detect()) {
+    puts("No Lock");
+    mdelay(1000);
+  }
+  puts("Clock Locked\n");
+
+}
diff --git a/firmware/microblaze/apps/cruft/can_i_sub.c b/firmware/microblaze/apps/cruft/can_i_sub.c
new file mode 100644
index 000000000..ed49791f0
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/can_i_sub.c
@@ -0,0 +1,25 @@
+#include <u2_init.h>
+#include <nonstdio.h>
+
+//typedef long long int64_t;
+
+
+int64_t sub(int64_t a, int64_t b);
+void print(int64_t d);
+
+int main(void)
+{
+  u2_init();
+
+  int64_t d = sub(462550990848000LL, 462028800000000LL);
+  print_uint64(d);
+  newline();
+  return 0;
+}
+
+int64_t sub(int64_t a, int64_t b)
+{
+  return a - b;
+}
+
+
diff --git a/firmware/microblaze/apps/cruft/double_buffer_fragment.c b/firmware/microblaze/apps/cruft/double_buffer_fragment.c
new file mode 100644
index 000000000..cfc061247
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/double_buffer_fragment.c
@@ -0,0 +1,138 @@
+#if 0
+void 
+double_buffering(int port) {
+  unsigned int localstatus = buffer_pool_status->status;
+
+  if(localstatus & BPS_DONE_0) {
+    bp_clear_buf(0);
+    if(buffer_state[0] == FILLING) {
+      buffer_state[0] = FULL;
+      if(buffer_state[1] == EMPTY) {
+	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[1] = FILLING;
+      }
+      else
+	dsp_rx_idle = 1;
+      if(serdes_tx_idle) {
+	serdes_tx_idle = 0;
+	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
+	buffer_state[0] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[0] = EMPTY;
+      if(dsp_rx_idle) {
+	dsp_rx_idle = 0;
+	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
+	buffer_state[0] = FILLING;
+      }
+      if(buffer_state[1] == FULL) {
+	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
+	buffer_state[1] = EMPTYING;
+      }
+      else
+	serdes_tx_idle = 1;
+    }
+    putstr("Int Proc'ed 0\n");
+  }
+
+  if(localstatus & BPS_DONE_1) {
+    bp_clear_buf(1);
+    if(buffer_state[1] == FILLING) {
+      buffer_state[1] = FULL;
+      if(buffer_state[0] == EMPTY) {
+	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[0] = FILLING;
+      }
+      else
+	dsp_rx_idle = 1;
+      if(serdes_tx_idle) {
+	serdes_tx_idle = 0;
+	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
+	buffer_state[1] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[1] = EMPTY;
+      if(dsp_rx_idle) {
+	dsp_rx_idle = 0;
+	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[1] = FILLING;
+      }
+      if(buffer_state[0] == FULL) {
+	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
+	buffer_state[0] = EMPTYING;
+      }
+      else
+	serdes_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 1\n");
+  }
+
+  if(localstatus & BPS_DONE_2) {
+    bp_clear_buf(2);
+    if(buffer_state[2] == FILLING) {
+      buffer_state[2] = FULL;
+      if(buffer_state[3] == EMPTY) {
+	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3, use 500 lines
+	buffer_state[3] = FILLING;
+      }
+      else
+	serdes_rx_idle = 1;
+      if(dsp_tx_idle) {
+	dsp_tx_idle = 0;
+	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
+	buffer_state[2] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[2] = EMPTY;
+      if(serdes_rx_idle) {
+	serdes_rx_idle = 0;
+	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2
+	buffer_state[2] = FILLING;
+      }
+      if(buffer_state[3] == FULL) {
+	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
+	buffer_state[3] = EMPTYING;
+      }
+      else
+	dsp_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 2\n");
+  }
+
+  if(localstatus & BPS_DONE_3) {
+    bp_clear_buf(3);
+    if(buffer_state[3] == FILLING) {
+      buffer_state[3] = FULL;
+      if(buffer_state[2] == EMPTY) {
+	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2, use 500 lines
+	buffer_state[2] = FILLING;
+      }
+      else
+	serdes_rx_idle = 1;
+      if(dsp_tx_idle) {
+	dsp_tx_idle = 0;
+	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
+	buffer_state[3] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[3] = EMPTY;
+      if(serdes_rx_idle) {
+	serdes_rx_idle = 0;
+	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3
+	buffer_state[3] = FILLING;
+      }
+      if(buffer_state[2] == FULL) {
+	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
+	buffer_state[2] = EMPTYING;
+      }
+      else
+	dsp_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 3\n");
+  }
+}
+#endif
diff --git a/firmware/microblaze/apps/cruft/echo.c b/firmware/microblaze/apps/cruft/echo.c
new file mode 100644
index 000000000..89108ee80
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/echo.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "stdio.h"
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("\n>>> echo <<<");
+
+  while (1){
+    int ch = getchar();
+    putchar(ch);
+  }
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/eth_serdes.c b/firmware/microblaze/apps/cruft/eth_serdes.c
new file mode 100644
index 000000000..2d2ddc1ca
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/eth_serdes.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_passthru_v2.h"
+#include "memcpy_wa.h"
+#include "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno __attribute__((unused));	// used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and serdes
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+
+#define	DSP_RX_BUF_0	2	// serdes -> eth (double buffer)
+#define	DSP_RX_BUF_1	3	// serdes -> eth
+#define	DSP_TX_BUF_0	4	// eth -> serdes (double buffer)
+#define	DSP_TX_BUF_1	5	// eth -> serdes
+
+/*
+ * ================================================================
+ *   configure serdes double buffering state machine (eth -> serdes)
+ * ================================================================
+ */
+
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to serdes
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_SERDES,
+  0,
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+/*
+ * ====================================================================
+ *   configure serdes RX double buffering state machine (serdes -> eth)
+ * ====================================================================
+ */
+
+// receive from serdes
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_SERDES,
+  0,
+  BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+// ----------------------------------------------------------------
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
+{
+#if 0
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t last_line = buffer_pool_status->last_line[buf_this] - sm->last_line_adj;
+  printf("fw_sets_seqno_inspector: buf_this = %d, last_line = %d\n",
+	 buf_this, last_line);
+
+  print_buffer(p, (last_line + 1));
+#endif
+
+#if 0
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+#endif
+
+  return false;		// we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  if (0 && (status & ~BPS_IDLE_ALL)){
+    putstr("status = ");
+    puthex32_nl(status);
+  }
+    
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  output_regs->led_src = 0x3;		// h/w controls bottom two bits
+  clocks_enable_test_clk(true, 1);
+
+  putstr("\neth <-> serdes\n");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  // clocks_mimo_config(MC_WE_LOCK_TO_SMA | MC_PROVIDE_CLK_TO_MIMO);
+  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 1
+  output_regs->debug_mux_ctrl = 1;
+  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> serdes
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+	    &dsp_tx_recv_args, &dsp_tx_send_args,
+	    eth_pkt_inspector);
+
+
+  // initialize double buffering state machine for serdes -> ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      dbsm_nop_inspector);
+  }
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+  // kick off the state machines
+  dbsm_start(&dsp_tx_sm);
+  dbsm_start(&dsp_rx_sm);
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    buffer_irq_handler(0);
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/factory_test.c b/firmware/microblaze/apps/cruft/factory_test.c
new file mode 100644
index 000000000..e1fbb0e40
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/factory_test.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <clocks.h>
+#include "sd.h"
+
+#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;	// used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+
+#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
+#define	DSP_RX_BUF_1	3	// dsp rx -> eth
+#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
+#define	DSP_TX_BUF_1	5	// eth -> dsp tx
+
+/*
+ * ================================================================
+ *   configure DSP TX double buffering state machine (eth -> dsp)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past transport header
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+/*
+ * ================================================================
+ *   configure DSP RX double buffering state machine (dsp -> eth)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool         streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD	1000
+
+bool is_streaming(void){ return streaming_p; }
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;			// reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);			// set "chain" bit
+
+  // kick off the state machine
+  dbsm_start(&dsp_rx_sm);
+
+  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
+
+  // make sure this one and the rest have the "now" and "chain" bits set.
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);				
+
+  dsp_rx_regs->rx_time = 0;		// enqueue second command
+}
+
+void
+start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  host_mac_addr = *host;	// remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t	pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;	// flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 256;
+  int interp = 32;
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = interp;
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;		// we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int test_ram()
+{
+  int i,j,k;
+  output_regs->ram_page = 1<<10;
+  
+  extram[0] = 0xDEADBEEF;
+  extram[1] = 0xF00D1234;
+  extram[7] = 0x76543210;
+  
+  output_regs->ram_page = 2<<10;
+  extram[7] = 0x55555555;
+  extram[1] = 0xaaaaaaaa;
+  extram[0] = 0xeeeeeeee;
+  
+  output_regs->ram_page = 1<<10;
+  
+  i = extram[0];
+  k = extram[1];
+  j = extram[7];
+  
+  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
+    puts("RAM FAIL1!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  
+  output_regs->ram_page = 2<<10;
+
+  j = extram[7];
+  k = extram[1];
+  i = extram[0];
+
+  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
+    puts("RAM FAIL2!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  return 1;
+}
+
+int test_sd()
+{
+  int i = sd_init();
+  if(i==0) {
+    puts("FAILED INIT of Card\n");
+    return 0;
+  }
+  
+  unsigned char buf[512];
+  i = sd_read_block(2048,buf);
+  if(i == 0) {
+    puts("READ Command Rejected\n");
+    return 0;
+  }
+  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
+    ;
+  else {
+    puts("Read bad data from SD Card\n");
+    return 0;
+  }
+  return 1;
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nFactory Test\n");
+
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  if(test_sd())
+    puts("SD OK\n");
+  else {
+    puts("SD FAIL\n");
+    //    hal_finish();
+    //return 0;
+  }
+  if(test_ram())
+    puts("RAM OK\n");
+  else {
+    puts("RAM FAIL\n");
+    hal_finish();
+    return 0;
+  }
+
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  output_regs->led_src = 0x7;  // make bottom 3 controlled by HW
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  clocks_enable_tx_dboard(true,1);
+  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+  output_regs->debug_mux_ctrl = 1;
+#if 0
+  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+	    &dsp_tx_recv_args, &dsp_tx_send_args,
+	    eth_pkt_inspector);
+
+
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      dbsm_nop_inspector);
+  }
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;		// poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
+      putchar('U');
+    }
+
+    if (pending & PIC_OVERRUN_INT){
+      dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+	// restart_streaming();
+	// FIXME report error
+      }
+      else {
+	// FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/gen_eth_packets.c b/firmware/microblaze/apps/cruft/gen_eth_packets.c
new file mode 100644
index 000000000..4d521f6bf
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/gen_eth_packets.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "print_rmon_regs.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// ----------------------------------------------------------------
+
+static eth_mac_addr_t dst_mac_addr =
+  {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+// ----------------------------------------------------------------
+
+// #define	PACKET_SIZE 1500		// bytes
+// #define ETH_DATA_RATE 1000000		// 1MB/s
+// #define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
+
+// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE;	// ticks between interrupts
+
+static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3);		// tick at 1 kHz
+static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6);	// tick at 10 kHz
+
+static volatile bool send_packet_now = false;   // timer handler sets this
+static volatile bool link_is_up = false;	// eth handler sets this
+
+int packet_number = 0;
+
+
+#define CPU_TX_BUF	0	// cpu xmits ethernet frames from here
+#define CPU_RX_BUF	1	// receive ethernet frames here
+
+// ----------------------------------------------------------------
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  link_is_up = speed == 0 ? false : true;
+  hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
+  printf("\neth link changed: speed = %d\n", speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+  hal_set_timeout(timer_delta);	// schedule next timeout
+  send_packet_now = 1;
+}
+
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+  int i = 0;
+  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+  for (i = 0; i < BP_NLINES; i++){
+    buf[i] = mark | i;
+    mark ^= 0x00FF0000;
+  }
+
+  // copy header into buffer
+  memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+  u2_eth_packet_t	pkt __attribute__((aligned (4)));
+
+  memset(&pkt, 0, sizeof(pkt));
+
+  pkt.ehdr.dst = dst_mac_addr;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  pkt.fixed.word0 = 0x01234567;
+  pkt.fixed.timestamp = 0xffffffff;
+
+  // init just the one we're using
+  init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF);
+}
+
+int
+main(void)
+{
+  int npackets_sent = 0;
+
+  u2_init();
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\ngen_eth_packets\n");
+  
+  hal_set_leds(0x0, 0x3);
+
+  init_packets();
+
+  pic_register_handler(IRQ_TIMER, timer_irq_handler);
+
+  if (hwconfig_simulation_p())
+    timer_delta = sim_timer_delta;
+
+  hal_set_timeout(timer_delta);
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  /*
+  if (hwconfig_simulation_p()){
+    eth_mac->speed = 4;	// hardcode mac speed to 1000
+    link_is_up = true;
+  }
+  */
+
+  // fire off a receive from the ethernet
+  bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+  while(1){
+    uint32_t status = buffer_pool_status->status;
+
+    if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){
+      bp_clear_buf(CPU_RX_BUF);
+      // ignore incoming ethernet packets; they were looped back in sim
+      bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+    }
+
+    if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){
+      if (status & BPS_ERROR(CPU_TX_BUF)){
+	putchar('E');
+      }
+      bp_clear_buf(CPU_TX_BUF);
+      npackets_sent++;
+      if ((npackets_sent & 0xF) == 0){	// print after every 16 packets
+	//print_rmon_regs();
+	putchar('.');
+      }
+    }
+
+    if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){
+      send_packet_now = false;
+
+      // kick off the next packet
+      // FIXME set packet number in packet
+
+      bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255);	// 1KB total
+      hal_toggle_leds(0x1);
+    }
+  }
+
+  hal_finish();
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/gen_pause_frames.c b/firmware/microblaze/apps/cruft/gen_pause_frames.c
new file mode 100644
index 000000000..0f81dafff
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/gen_pause_frames.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "u2_eth_packet.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+
+// ----------------------------------------------------------------
+
+unsigned char dst_mac_addr[6] = {
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+// ----------------------------------------------------------------
+
+// #define	PACKET_SIZE 1500		// bytes
+// #define ETH_DATA_RATE 1000000		// 1MB/s
+// #define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
+
+// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE;	// ticks between interrupts
+
+static int timer_delta = MASTER_CLK_RATE/1000;	// tick at 1kHz
+
+static volatile bool send_packet_now = false;   // timer handler sets this
+static volatile bool link_is_up = false;	// eth handler sets this
+
+int packet_number = 0;
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK  0xE0000
+#define LS_1000  0x80000
+#define LS_100   0x40000
+#define LS_10    0x20000
+
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  int v = 0;
+  switch(speed){
+  case 10:
+    v = LS_10;
+    link_is_up = true;
+    break;
+    
+  case 100:
+    v = LS_100;
+    link_is_up = true;
+    break;
+    
+  case 1000:
+    v = LS_100;
+    link_is_up = true;
+    break;
+
+  default:
+    v = 0;
+    link_is_up = false;
+    break;
+  }
+
+  hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
+
+  putstr("\neth link changed: speed = ");
+  puthex16_nl(speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+  hal_set_timeout(timer_delta);	// schedule next timeout
+  send_packet_now = 1;
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+  // FIXME
+}
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+  int i = 0;
+  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+  for (i = 0; i < BP_NLINES; i++){
+    buf[i] = mark | i;
+    mark ^= 0x00FF0000;
+  }
+
+  // copy header into buffer
+  memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+  int	i;
+  
+  u2_eth_packet_t	pkt __attribute__((aligned (4)));
+
+  for (i = 0; i < 6; i++){
+    pkt.ehdr.dst.addr[i] = dst_mac_addr[i];
+  }
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+
+  // fill ALL buffers for debugging
+  for (i = 0; i < 8; i++)
+    init_packet((void *)buffer_ram(i), &pkt, i);
+}
+
+static int led_counter = 0;
+
+int
+main(void)
+{
+  int send_pause = 1;
+  
+  u2_init();
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\ngen_eth_packets\n");
+  
+  // Control LEDs
+  output_regs->leds = 0x00;
+
+  init_packets();
+
+  // pic_register_handler(IRQ_BUFFER, buffer_irq_handler);  // poll for now
+  pic_register_handler(IRQ_TIMER, timer_irq_handler);
+  hal_set_timeout(timer_delta);
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+
+  ethernet_init();
+
+  eth_mac->pause_frame_send_en = 1;
+  eth_mac->pause_quanta_set = 16384 / 512;
+
+  // eth_mac->speed = 4;	// FIXME hardcode mac speed to 1000
+
+  while(1){
+    if (link_is_up && send_packet_now){
+      send_packet_now = false;
+
+
+      if (send_pause)
+	eth_mac->xon_cpu = 1;
+      else
+	eth_mac->xon_cpu = 0;
+
+      send_pause ^= 1;
+
+      // kick off the next packet
+      // FIXME set packet number in packet
+
+#if 0
+      bp_send_from_buf(0, PORT_ETH, 1, 0, 255);	// 1KB total
+
+      while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0)
+	;
+      bp_clear_buf(0);
+#endif
+
+      output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0);
+    }
+  }
+
+  hal_finish();
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/hello.c b/firmware/microblaze/apps/cruft/hello.c
new file mode 100644
index 000000000..bce843093
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/hello.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "stdio.h"
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("Hello World");
+  puts("Goodbye World");
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/ibs_rx_test.c b/firmware/microblaze/apps/cruft/ibs_rx_test.c
new file mode 100644
index 000000000..bdc04747e
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/ibs_rx_test.c
@@ -0,0 +1,82 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "nonstdio.h"
+
+#define PORT 2    // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+static void __attribute__((unused))
+wait_until_status_nonzero(void) 
+{
+  while (buffer_pool_status->status == 0)
+    ;
+}
+
+int
+main(void)
+{
+  int i;
+  
+  u2_init();
+
+  output_regs->adc_ctrl = 0x0A;
+
+  dsp_rx_regs->freq = 0;
+  dsp_rx_regs->scale_iq = (1 << 16) | 1;
+  dsp_rx_regs->decim_rate = 8;
+
+  volatile unsigned int *buffer0 = buffer_ram(0);
+  volatile unsigned int *buffer1 = buffer_ram(1);
+  volatile unsigned int *buffer2 = buffer_ram(2);
+  
+  putstr("Starting RX\n");
+  bp_clear_buf(0);
+  bp_receive_to_buf(0, 1, 1, 0, 99);
+
+  dsp_rx_regs->rx_command = (50 << 9) | 100;   // Numlines, lines per frame
+  dsp_rx_regs->rx_time = 0x2000;
+
+  dsp_rx_regs->rx_command = (137 << 9) | 50;   // Numlines, lines per frame
+  dsp_rx_regs->rx_time = 0x2200;
+
+  while (buffer_pool_status->status == 0)
+    ;
+  bp_clear_buf(0);
+  bp_clear_buf(1);
+  bp_receive_to_buf(1, 1, 1, 0, 99);
+  while (buffer_pool_status->status == 0)
+    ;
+  bp_clear_buf(2);
+  bp_receive_to_buf(2, 1, 1, 0, 99);
+  while (buffer_pool_status->status == 0)
+    ;
+  
+  for(i=0;i<100;i++) {
+    puthex(i);
+    putstr("   ");
+    puthex_nl(buffer0[i]);
+  }
+  for(i=0;i<60;i++) {
+    puthex(i);
+    putstr("   ");
+    puthex_nl(buffer1[i]);
+  }
+  for(i=0;i<60;i++) {
+    puthex(i);
+    putstr("   ");
+    puthex_nl(buffer2[i]);
+  }
+  //while(timer_regs -> time < 0x6000)
+  //  {}
+
+  putstr("Done\n");
+  hal_finish();
+  
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/ibs_tx_test.c b/firmware/microblaze/apps/cruft/ibs_tx_test.c
new file mode 100644
index 000000000..ff9446d92
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/ibs_tx_test.c
@@ -0,0 +1,160 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "nonstdio.h"
+
+// Globals
+#define EMPTY 0
+#define FILLING 1
+#define FULL 2
+#define EMPTYING 3
+
+#define PORT 2    // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+static void
+wait_until_status_nonzero(void)
+{
+  while (buffer_pool_status->status == 0)
+    ;
+}
+
+int
+main(void)
+{
+  int i;
+  
+  u2_init();
+  
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (1 << 16) | 1;
+  dsp_tx_regs->interp_rate = 8;
+
+  // Write data to be sent into the first buffer
+  volatile unsigned int *buffer0 = buffer_ram(0);
+  volatile unsigned int *buffer1 = buffer_ram(1);
+  
+
+  putstr("Starting to fill in RAM\n");
+  for(i=0;i<512;i++) 
+    buffer0[i] = i;
+  putstr("Filled in RAM\n");
+  
+  buffer0[0] = 7; // start and end of buffer, send immediately
+  buffer0[1] = 0x0000;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+  while(timer_regs -> time < 0x6000)
+    {}
+
+  buffer0[0] = 3; // start and end of buffer
+  buffer0[1] = 0x8000;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+  while(timer_regs -> time < 0x8400)
+    {}
+
+  buffer0[0] = 3; // start and end of buffer
+  buffer0[1] = 0x8800;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+  while(timer_regs -> time < 0x9000)
+    {}
+
+  buffer0[0] = 0x2;  // not last
+  buffer0[1] = 0x9100;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+  buffer0[0] = 0x1;  // last
+  buffer0[1] = 0x0000;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+
+  
+  buffer0[0] = 0x3;  // first and last
+  buffer0[1] = 0x8000;  // Time in the past
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+
+  /*
+  buffer0[0] = 0x2; // not last
+  buffer0[1] = 0x9600;  // start time
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 1, 1, 0, 9);
+  while (buffer_pool_status->status == 0)
+    ;
+  */
+
+  while(timer_regs -> time < 0xa000)
+    {}
+
+  putstr("Done\n");
+
+  while(1)
+    {}
+  hal_finish();
+  
+  // Send a bunch, let them pile up in FIFO
+  bp_send_from_buf(0, 2, 1, 21, 80);    wait_until_status_nonzero();
+  bp_clear_buf(0);
+  putstr("First add'l TX done\n");
+  bp_send_from_buf(0, 2, 1, 81, 288);   wait_until_status_nonzero();
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 2, 1, 289, 292);  wait_until_status_nonzero();
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 2, 1, 293, 326);  wait_until_status_nonzero();
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 2, 1, 327, 399);  wait_until_status_nonzero();
+  bp_clear_buf(0);
+  bp_send_from_buf(0, 2, 1, 400, 511);  wait_until_status_nonzero();
+  bp_clear_buf(0);
+  putstr("All add'l TX done\n");
+  
+  bp_receive_to_buf(1, 2, 1, 21, 80);   wait_until_status_nonzero();
+  bp_clear_buf(1);
+  putstr("First add'l RX done\n");
+  bp_receive_to_buf(1, 2, 1, 81, 288);  wait_until_status_nonzero();
+  bp_clear_buf(1);
+  bp_receive_to_buf(1, 2, 1, 289, 292); wait_until_status_nonzero();
+  bp_clear_buf(1);
+  bp_receive_to_buf(1, 2, 1, 293, 326); wait_until_status_nonzero();
+  bp_clear_buf(1);
+  bp_receive_to_buf(1, 2, 1, 327, 399); wait_until_status_nonzero();
+  bp_clear_buf(1);
+  bp_receive_to_buf(1, 2, 1, 400, 511); wait_until_status_nonzero();
+  bp_clear_buf(1);
+  putstr("All add'l RX done\n");
+
+  for(i=0;i<512;i++)
+    if(buffer0[i] != buffer1[i]) {
+      putstr("ERROR at location: ");
+      puthex_nl(i);
+      putstr("Value sent: ");
+      puthex_nl(buffer0[i]);
+      putstr("Value rcvd: ");
+      puthex_nl(buffer1[i]);
+      //break;
+    }
+  
+  putstr("Done Testing\n");
+  
+  hal_finish();
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/mimo_app_common_v2.c b/firmware/microblaze/apps/cruft/mimo_app_common_v2.c
new file mode 100644
index 000000000..5dbecb0d0
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/mimo_app_common_v2.c
@@ -0,0 +1,582 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mimo_app_common_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include "db.h"
+#include "db_base.h"
+#include "clocks.h"
+#include "u2_init.h"
+#include <string.h>
+
+volatile bool link_is_up = false;	// eth handler sets this
+int cpu_tx_buf_dest_port = PORT_ETH;
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+static unsigned char exp_seqno __attribute__((unused)) = 0;
+
+void abort(void);
+
+static bool
+burn_mac_addr(const op_burn_mac_addr_t *p)
+{
+  return ethernet_set_mac_addr(&p->addr);
+}
+
+static bool
+sync_to_pps(const op_generic_t *p)
+{
+  timesync_regs->sync_on_next_pps = 1;
+  putstr("SYNC to PPS\n");
+  return true;
+}
+
+static bool
+config_mimo_cmd(const op_config_mimo_t *p)
+{
+  clocks_mimo_config(p->flags);
+  return true;
+}
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+  reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+  reply_pkt->ehdr.src = *ethernet_mac_addr();
+  reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+  reply_pkt->thdr.flags = 0;
+  reply_pkt->thdr.fifo_status = 0;	// written by protocol engine
+  reply_pkt->thdr.seqno = 0;		// written by protocol engine
+  reply_pkt->thdr.ack = 0;		// written by protocol engine
+  u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+  reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+  if (reply_len < 64)
+    reply_len = 64;
+
+  // wait for buffer to become idle
+  hal_set_leds(0x4, 0x4);
+  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+    ;
+  hal_set_leds(0x0, 0x4);
+
+  // copy reply into CPU_TX_BUF
+  memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+  // wait until nobody else is sending to the ethernet
+  if (ac_could_be_sending_to_eth){
+    hal_set_leds(0x8, 0x8);
+    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+    hal_set_leds(0x0, 0x8);
+  }
+
+  if (0){
+    printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, (int)reply_len);
+    print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4);
+  }
+
+  // fire it off
+  bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4);
+
+  // wait for it to complete (not long, it's a small pkt)
+  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
+    ;
+
+  bp_clear_buf(CPU_TX_BUF);
+}
+
+
+static size_t
+op_id_cmd(const op_generic_t *p,
+	  void *reply_payload, size_t reply_payload_space)
+{
+  op_id_reply_t *r = (op_id_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))	// no room
+    return 0;
+
+  // Build reply subpacket
+
+  r->opcode = OP_ID_REPLY;
+  r->len = sizeof(op_id_reply_t);
+  r->rid = p->rid;
+  r->addr = *ethernet_mac_addr();
+  r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor;
+  // r->fpga_md5sum = ;	// FIXME
+  // r->sw_md5sum = ;	// FIXME
+
+  return r->len;
+}
+
+
+static size_t
+config_tx_v2_cmd(const op_config_tx_v2_t *p,
+		 void *reply_payload, size_t reply_payload_space)
+{
+  op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))
+    return 0;					// no room
+
+  struct tune_result	tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+#if 0
+  if (p->valid & CFGV_GAIN){
+    ok &= db_set_gain(tx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    bool was_streaming = is_streaming();
+    if (was_streaming)
+      stop_rx_cmd();
+    
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Tx", tune_ok, f, &tune_result);
+
+    if (was_streaming)
+      restart_streaming();
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    int interp = p->interp;
+    int hb1 = 0;
+    int hb2 = 0;
+
+    if (!(interp & 1)){
+      hb2 = 1;
+      interp = interp >> 1;
+    }
+
+    if (!(interp & 1)){
+      hb1 = 1;
+      interp = interp >> 1;
+    }
+    
+    if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP)
+      ok = false;
+    else {
+      dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp;
+      // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp);
+    }
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_tx_regs->scale_iq = p->scale_iq;
+  }
+#endif
+
+  // Build reply subpacket
+
+  r->opcode = OP_CONFIG_TX_REPLY_V2;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+  r->inverted = tune_result.inverted;
+  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+  r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+  r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+  return r->len;
+}
+
+static size_t
+config_rx_v2_cmd(const op_config_rx_v2_t *p, 
+		 void *reply_payload, size_t reply_payload_space)
+{
+  op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))
+    return 0;				// no room
+
+  struct tune_result	tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= db_set_gain(rx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    bool was_streaming = is_streaming();
+    if (was_streaming)
+      stop_rx_cmd();
+    
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Rx", tune_ok, f, &tune_result);
+
+    if (was_streaming)
+      restart_streaming();
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    int decim = p->decim;
+    int hb1 = 0;
+    int hb2 = 0;
+    
+    if(!(decim & 1)) {
+      hb2 = 1;
+      decim = decim >> 1;
+    }
+    
+    if(!(decim & 1)) {
+      hb1 = 1;
+      decim = decim >> 1;
+    }
+    
+    if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM)
+      ok = false;
+    else {
+      dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim;
+      // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim);
+    }
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_rx_regs->scale_iq = p->scale_iq;
+  }
+
+  // Build reply subpacket
+
+  r->opcode = OP_CONFIG_RX_REPLY_V2;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+  r->inverted = tune_result.inverted;
+  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+  r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+  r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+
+  return r->len;
+}
+
+static size_t
+read_time_cmd(const op_generic_t *p,
+	      void *reply_payload, size_t reply_payload_space)
+{
+  op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))		
+    return 0;					// no room
+
+  r->opcode = OP_READ_TIME_REPLY;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->time = timer_regs->time;
+
+  return r->len;
+}
+
+static void
+fill_db_info(u2_db_info_t *p, const struct db_base *db)
+{
+  p->dbid = db->dbid;
+  p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min);
+  p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min);
+  p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max);
+  p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max);
+  p->gain_min = db->gain_min;
+  p->gain_max = db->gain_max;
+  p->gain_step_size = db->gain_step_size;
+}
+
+static size_t
+dboard_info_cmd(const op_generic_t *p,
+		void *reply_payload, size_t reply_payload_space)
+{
+  op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))		
+    return 0;					// no room
+
+  r->opcode = OP_DBOARD_INFO_REPLY;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = true;
+
+  fill_db_info(&r->tx_db_info, tx_dboard);
+  fill_db_info(&r->rx_db_info, rx_dboard);
+
+  return r->len;
+}
+
+static size_t
+peek_cmd(const op_peek_t *p,
+	 void *reply_payload, size_t reply_payload_space)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+
+  putstr("peek: addr="); puthex32(p->addr);
+  printf(" bytes=%u\n", p->bytes);
+
+  if ((reply_payload_space < (sizeof(*r) + p->bytes)) ||
+      p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) {
+    putstr("peek: insufficient reply packet space\n");
+    return 0;			// FIXME do partial read?
+  }
+
+  r->opcode = OP_PEEK_REPLY;
+  r->len = sizeof(*r)+p->bytes;
+  r->rid = p->rid;
+  r->ok = true;
+
+  memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes);
+
+  return r->len;
+}
+
+static bool
+poke_cmd(const op_poke_t *p)
+{
+  int bytes = p->len - sizeof(*p);
+  putstr("poke: addr="); puthex32(p->addr);
+  printf(" bytes=%u\n", bytes);
+
+  uint8_t *src = (uint8_t *)p + sizeof(*p);
+  memcpy_wa((void *)p->addr, src, bytes);
+
+  return true;
+}
+
+static size_t
+generic_reply(const op_generic_t *p,
+	      void *reply_payload, size_t reply_payload_space,
+	      bool ok)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))		
+    return 0;					// no room
+
+  r->opcode = p->opcode | OP_REPLY_BIT;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+
+  return r->len;
+}
+
+static size_t
+add_eop(void *reply_payload, size_t reply_payload_space)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))		
+    return 0;					// no room
+
+  r->opcode = OP_EOP;
+  r->len = sizeof(*r);
+  r->rid = 0;
+  r->ok =  0;
+
+  return r->len;
+}
+
+void
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+  unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
+  unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
+  int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
+
+  // initialize reply
+  memset(reply, 0, sizeof(reply));
+  set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+
+  // point to beginning of payload (subpackets)
+  unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+  int payload_len = len - sizeof(u2_eth_packet_t);
+
+  size_t subpktlen = 0;
+
+  while (payload_len >= sizeof(op_generic_t)){
+    const op_generic_t *gp = (const op_generic_t *) payload;
+    subpktlen = 0;
+
+    // printf("\nopcode = %d\n", gp->opcode);
+
+    switch(gp->opcode){
+    case OP_EOP:		// end of subpackets
+      goto end_of_subpackets;
+
+    case OP_ID:
+      subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
+      break;
+    
+    case OP_CONFIG_TX_V2:
+      subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload,
+				   reply_payload, reply_payload_space);
+      break;
+
+    case OP_CONFIG_RX_V2:
+      subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload,
+				   reply_payload, reply_payload_space);
+      break;
+
+    case OP_START_RX_STREAMING:
+      start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+      break;
+    
+    case OP_STOP_RX:
+      stop_rx_cmd();
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+      break;
+    
+    case OP_BURN_MAC_ADDR:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+				burn_mac_addr((op_burn_mac_addr_t *) payload));
+      break;
+
+    case OP_CONFIG_MIMO:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+				config_mimo_cmd((op_config_mimo_t *) payload));
+      break;
+
+    case OP_READ_TIME:
+      subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space);
+      break;
+
+    case OP_DBOARD_INFO:
+      subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space);
+      break;
+
+    case OP_SYNC_TO_PPS:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+				sync_to_pps((op_generic_t *) payload));
+      break;
+
+    case OP_PEEK:
+      subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space);
+      break;
+
+    case OP_POKE:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+				poke_cmd((op_poke_t *)payload));
+      break;
+
+    default:
+      printf("app_common_v2: unhandled opcode = %d\n", gp->opcode);
+      break;
+    }
+
+    int t = (gp->len + 3) & ~3;		// bump to a multiple of 4
+    payload += t;
+    payload_len -= t;
+
+    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
+    reply_payload += subpktlen;
+    reply_payload_space -= subpktlen;
+  }
+
+ end_of_subpackets:
+
+  // add the EOP marker
+  subpktlen = add_eop(reply_payload, reply_payload_space);
+  subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
+  reply_payload += subpktlen;
+  reply_payload_space -= subpktlen;
+
+  send_reply(reply, reply_payload - reply);
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+int
+eth_pkt_inspector(bsm12_t *sm, int bufno)
+{
+  u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+  size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+  //static size_t last_len = 0;
+
+  // hal_toggle_leds(0x1);
+
+  // inspect rcvd frame and figure out what do do.
+
+  if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+    return true;	// ignore, probably bogus PAUSE frame from MAC
+
+  int chan = u2p_chan(&pkt->fixed);
+
+  switch (chan){
+  case CONTROL_CHAN:
+    handle_control_chan_frame(pkt, byte_len);
+    return -1;
+    break;
+
+  case 0:
+    return 0;	// pass it off to DSP TX
+
+  case 1:
+    return 1;	// pass it off to SERDES TX
+
+  default:
+    abort();
+    break;
+  }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  link_is_up = speed != 0;
+  hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45);
+  printf("\neth link changed: speed = %d\n", speed);
+}
+
+
+void
+print_tune_result(char *msg, bool tune_ok,
+		  u2_fxpt_freq_t target_freq, struct tune_result *r)
+{
+#if 0
+  printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
+  putstr("  target_freq   "); print_fxpt_freq(target_freq); newline();
+  putstr("  baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
+  putstr("  dxc_freq      "); print_fxpt_freq(r->dxc_freq); newline();
+  putstr("  residual_freq "); print_fxpt_freq(r->residual_freq); newline();
+  printf("  inverted      %s\n", r->inverted ? "true" : "false");
+#endif
+}
diff --git a/firmware/microblaze/apps/cruft/mimo_app_common_v2.h b/firmware/microblaze/apps/cruft/mimo_app_common_v2.h
new file mode 100644
index 000000000..1e62ced37
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/mimo_app_common_v2.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include <stdbool.h>
+#include "usrp2_eth_packet.h"
+#include "bsm12.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF 	7	// cpu -> eth
+
+#define	_AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up;	// eth handler sets this
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+extern int cpu_tx_buf_dest_port;
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ */
+int eth_pkt_inspector(bsm12_t *sm, int bufno);
+
+
+void link_changed_callback(int speed);
+
+void
+print_tune_result(char *msg, bool tune_ok,
+		  u2_fxpt_freq_t target_freq, struct tune_result *r);
+
+
+void start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p);
+void stop_rx_cmd(void);
+void restart_streaming(void);
+bool is_streaming(void);
+
+void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */
diff --git a/firmware/microblaze/apps/cruft/mimo_tx.c b/firmware/microblaze/apps/cruft/mimo_tx.c
new file mode 100644
index 000000000..e0f8aa6fa
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/mimo_tx.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This is a down and dirty test program that confirms that the we can
+ * coherently transmit different signals to two USRP2s connected via a
+ * mimo cable.  This code runs in the USRP2 connected to the ethernet.
+ * The other USRP runs mimo_tx_slave.  The host runs test_mimo_tx.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "bsm12.h"
+#include "mimo_app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "clocks.h"
+
+#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;	// used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Experimental code to transmit packets to DSP Tx and SERDES
+ *
+ * Hard wire the Tx config so we don't have to deal with control stuff yet.
+ */
+
+#define	BUF_BSM12_0	4
+#define	BUF_BSM12_1	5
+#define	BUF_BSM12_2	6
+
+//#define CPU_TX_BUF	7	// cpu -> eth
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t bsm12_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t bsm12_send0_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past transport header
+  0			// filled in from last_line register
+};
+
+// send to SERDES
+buf_cmd_args_t bsm12_send1_args = {
+  PORT_SERDES,
+  0,			// starts just past transport header
+  0			// filled in from last_line register
+};
+
+bsm12_t bsm12_sm;	// the state machine
+
+#if 0
+/*
+ * ================================================================
+ *   configure DSP RX double buffering state machine (dsp -> eth)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+#endif
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool         streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD	1000
+
+bool is_streaming(void){ return streaming_p; }
+
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+#if 0
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;			// reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);			// set "chain" bit
+
+  // kick off the state machine
+  dbsm_start(&dsp_rx_sm);
+
+  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
+
+  // make sure this one and the rest have the "now" and "chain" bits set.
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);				
+
+  dsp_rx_regs->rx_time = 0;		// enqueue second command
+#endif
+}
+
+void
+start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+#if 0
+  host_mac_addr = *host;	// remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t	pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+#if 0
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;	// flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+#endif
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+
+  int tx_scale = 2500;
+  int interp = 8;		// * 4
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 429496730;	// 10MHz
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
+}
+
+
+#if 0
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+int
+fw_sets_seqno_inspector(bsm12_t *sm, int buf_this)
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;		// we didn't handle the packet
+}
+#endif
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  bsm12_process_status(&bsm12_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nMIMO Tx\n");
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+  output_regs->debug_mux_ctrl = 1;
+#if 0
+  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  bsm12_init(&bsm12_sm, BUF_BSM12_0,
+	     &bsm12_recv_args, &bsm12_send0_args, &bsm12_send1_args,
+	     eth_pkt_inspector);
+
+
+#if 0
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      dbsm_nop_inspector);
+  }
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+#endif
+
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  bsm12_start(&bsm12_sm);
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;		// poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      // dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
+      putchar('U');
+    }
+
+    if (pending & PIC_OVERRUN_INT){
+      // dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+	// restart_streaming();
+	// FIXME report error
+      }
+      else {
+	// FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/mimo_tx_slave.c b/firmware/microblaze/apps/cruft/mimo_tx_slave.c
new file mode 100644
index 000000000..cdf9c03c2
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/mimo_tx_slave.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This is a down and dirty test program that confirms that the we can
+ * coherently transmit different signals to two USRP2s connected via a
+ * mimo cable.  This code runs in the USRP2 NOT connected to the
+ * ethernet.  The USRP connected to the ethernet runs mimo_tx.  The
+ * host runs test_mimo_tx.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;	// used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between serdes and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow
+ * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+
+#define	DSP_RX_BUF_0	2	// dsp rx -> serdes (double buffer)
+#define	DSP_RX_BUF_1	3	// dsp rx -> serdes
+#define	DSP_TX_BUF_0	4	// serdes -> dsp tx (double buffer)
+#define	DSP_TX_BUF_1	5	// serdes -> dsp tx
+
+/*
+ * ==================================================================
+ *   configure DSP TX double buffering state machine (serdes -> dsp)
+ * ==================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from serdes
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_SERDES,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past transport header
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+/*
+ * =================================================================
+ *   configure DSP RX double buffering state machine (dsp -> serdes)
+ * =================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to serdes
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_SERDES,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool         streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD	1000
+
+bool is_streaming(void){ return streaming_p; }
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;			// reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);			// set "chain" bit
+
+  // kick off the state machine
+  dbsm_start(&dsp_rx_sm);
+
+  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
+
+  // make sure this one and the rest have the "now" and "chain" bits set.
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);				
+
+  dsp_rx_regs->rx_time = 0;		// enqueue second command
+}
+
+void
+start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  host_mac_addr = *host;	// remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t	pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;	// flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 2500;
+  int interp = 8;		// * 4
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 429496730;	// 10MHz
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;		// we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  // hal_toggle_leds(LED_A);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  if (0 && (status & ~BPS_IDLE_ALL)){
+    putstr("status = ");
+    puthex32_nl(status);
+  }
+
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  output_regs->led_src = 0x3;		// h/w controls bottom two bits
+  clocks_enable_test_clk(true, 1);
+
+  putstr("\nMIMO Tx Slave\n");
+
+  cpu_tx_buf_dest_port = PORT_SERDES;
+
+  // ethernet_register_link_changed_callback(link_changed_callback);
+  // ethernet_init();
+
+  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+  // puts("post clocks_mimo_config");
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 0
+  output_regs->debug_mux_ctrl = 1;
+  hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
+  hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+	    &dsp_tx_recv_args, &dsp_tx_send_args,
+	    eth_pkt_inspector);
+
+
+  //output_regs->flush_icache = 1;
+ 
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      dbsm_nop_inspector);
+  }
+
+  // puts("post dbsm_init's");
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+  // program tx registers
+  setup_tx();
+
+  // puts("post setup_tx");
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  // puts("post dbsm_start");
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;		// poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
+      putchar('U');
+    }
+
+    if (pending & PIC_OVERRUN_INT){
+      dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+	// restart_streaming();
+	// FIXME report error
+      }
+      else {
+	// FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/rcv_eth_packets.c b/firmware/microblaze/apps/cruft/rcv_eth_packets.c
new file mode 100644
index 000000000..03fc94354
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/rcv_eth_packets.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+
+// ----------------------------------------------------------------
+
+static eth_mac_addr_t dst_mac_addr =
+  {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
+
+
+// ----------------------------------------------------------------
+
+#define	PACKET_SIZE 1500		// bytes
+#define ETH_DATA_RATE 1000000		// 1MB/s
+#define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
+
+#define TIMER_RATE 100000000		// 100 MHz clock
+
+static int timer_delta = TIMER_RATE/ETH_PACKET_RATE;	// ticks between interrupts
+
+static volatile bool send_packet_now = false;   // timer handler sets this
+static volatile bool link_is_up = false;	// eth handler sets this
+
+int packet_number = 0;
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK  0xE0000
+#define LS_1000  0x80000
+#define LS_100   0x40000
+#define LS_10    0x20000
+
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  int v = 0;
+  switch(speed){
+  case 10:
+    v = LS_10;
+    link_is_up = true;
+    break;
+    
+  case 100:
+    v = LS_100;
+    link_is_up = true;
+    break;
+    
+  case 1000:
+    v = LS_100;
+    link_is_up = true;
+    break;
+
+  default:
+    v = 0;
+    link_is_up = false;
+    break;
+  }
+
+  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
+
+  putstr("\neth link changed: speed = ");
+  puthex16_nl(speed);
+}
+
+void
+timer_irq_handler(unsigned irq)
+{
+  hal_set_timeout(timer_delta);	// schedule next timeout
+  send_packet_now = 1;
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+  // FIXME
+}
+
+static void
+init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
+{
+  int i = 0;
+  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
+
+  for (i = 0; i < BP_NLINES; i++){
+    buf[i] = mark | i;
+    mark ^= 0x00FF0000;
+  }
+
+  // copy header into buffer
+  memcpy_wa(buf, pkt, sizeof(*pkt));
+}
+
+static void
+init_packets(void)
+{
+  int	i;
+  
+  u2_eth_packet_t	pkt __attribute__((aligned (4)));
+
+  pkt.ehdr.dst = dst_mac_addr;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+
+  // fill ALL buffers for debugging
+  for (i = 0; i < 8; i++)
+    init_packet((void *)buffer_ram(i), &pkt, i);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  int	prev_leds = -1;
+  int	new_leds  = 0x00;
+  output_regs->leds = 0x00;
+
+  int peak_hold_count = 0;
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\nrcv_eth_packets\n");
+  
+  init_packets();
+
+  // pic_register_handler(IRQ_BUFFER, buffer_irq_handler);  // poll for now
+
+  // FIXME turn off timer since I don't think MTS and MFS instructions are implemented
+  // pic_register_handler(IRQ_TIMER, timer_irq_handler);
+  // hal_set_timeout(timer_delta);
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+
+  ethernet_init();
+
+  //eth_mac->speed = 4;	// FIXME hardcode mac speed to 1000
+
+  // kick off a receive
+  bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
+
+  while(1){
+    // u2_eth_packet_t	pkt;
+
+    new_leds = 0;
+    if (link_is_up)
+      new_leds = 0x2;
+
+    if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){
+      // we've got a packet!
+
+#if 0
+      // copy to stack buffer so we can byte address it
+      memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt));
+      
+      putstr("Rx: src: ");
+      print_mac_addr(pkt.ehdr.dst_addr);
+      putstr(" dst: ");
+      print_mac_addr(pkt.ehdr.src_addr);
+      putstr(" ethtype: ");
+      puthex16(pkt.ehdr.ethertype);
+      putstr(" len: ");
+      int len = (buffer_pool_status->last_line[2] + 1) * 4;
+      puthex16_nl(len);
+#else
+      volatile int *bp = buffer_ram(2);
+      int	i;
+      for (i = 0; i < 16; i++){
+	puthex8(i);
+	putchar(':');
+	puthex32_nl(bp[i]);
+      }
+#endif
+      
+      // kick off next receive
+      bp_clear_buf(2);
+      bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
+
+      peak_hold_count = 2048 * 10;
+    }
+
+    if (peak_hold_count > 0){
+      peak_hold_count--;
+      new_leds |= 0x1;
+    }
+
+    if (new_leds != prev_leds){
+      prev_leds = new_leds;
+      output_regs->leds = new_leds;
+    }
+  }
+
+  hal_finish();
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/read_dbids.c b/firmware/microblaze/apps/cruft/read_dbids.c
new file mode 100644
index 000000000..24c6d9ab4
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/read_dbids.c
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nonstdio.h>
+#include <u2_init.h>
+#include <stdbool.h>
+#include <usrp2_i2c_addr.h>
+#include <i2c.h>
+
+
+int main(void)
+{
+  u2_init();
+
+  puts("\nread_dbids");
+
+  unsigned char dbid_tx[2];
+  unsigned char dbid_rx[2];
+  bool ok;
+
+  ok = eeprom_read(I2C_ADDR_TX_A, 1, dbid_tx, 2);
+  if (!ok){
+    puts("failed to read Tx Daugherboard EEPROM");
+  }
+  else {
+    putstr("Tx Daugherboard ID: ");
+    puthex8(dbid_tx[1]);    // MSB
+    puthex8(dbid_tx[0]);    // LSB
+    newline();
+  }
+
+  ok = eeprom_read(I2C_ADDR_RX_A, 1, dbid_rx, 2);
+  if (!ok){
+    puts("failed to read Rx Daugherboard EEPROM");
+  }
+  else {
+    putstr("Rx Daugherboard ID: ");
+    puthex8(dbid_rx[1]);    // MSB
+    puthex8(dbid_rx[0]);    // LSB
+    newline();
+  }
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/sd_bounce.c b/firmware/microblaze/apps/cruft/sd_bounce.c
new file mode 100644
index 000000000..c1b48f170
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/sd_bounce.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* 
+ * Loopback SERDES to SERDES
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "nonstdio.h"
+#include "memset_wa.h"
+#include <dbsm.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <clocks.h>
+
+
+
+// ----------------------------------------------------------------
+
+#define SERDES_RX_BUF_0		0
+#define	SERDES_RX_BUF_1		1
+
+/*
+ * ================================================================
+ *      configure SD RX double buffering state machine
+ * ================================================================
+ */
+
+// receive from SERDES
+buf_cmd_args_t sd_recv_args = {
+  PORT_SERDES,
+  0,
+  BP_LAST_LINE
+};
+
+// send to SERDES
+buf_cmd_args_t sd_send_args = {
+  PORT_SERDES,
+  0,		// starts with packet in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t sd_sm;	// the state machine
+
+
+
+
+// ----------------------------------------------------------------
+
+#if 0
+static bool
+check_packet(int *buf, int nlines)
+{
+  bool ok = true;
+  int i = 0;
+  for (i = 0; i < nlines; i++){
+    int expected = ((2*i + 0) << 16) | (2*i+1);
+    if (buf[i] != expected){
+      ok = false;
+      printf("buf[%d] = 0x%x  expected = 0x%x\n", i, buf[i], expected);
+    }
+  }
+  return ok;
+}
+
+static void
+zero_buffer(int bufno)
+{
+  memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
+}
+#endif
+
+
+bool
+sd_rx_inspector(dbsm_t *sm, int buf_this)
+{
+  hal_toggle_leds(0x2);
+
+#if 0
+  int last_line = buffer_pool_status->last_line[buf_this];
+  bool ok = check_packet(buffer_ram(buf_this), last_line);
+  static int good = 0;
+  static int bad = 0;
+
+  if (ok)
+    good++;
+  else
+    bad++;
+
+  if(good+bad == 10000) {
+    printf("Good %d\tBad %d\n",good,bad);
+    good = 0;
+    bad = 0;
+  }
+#endif
+
+  return false;
+}
+
+
+inline static void
+buffer_irq_handler(void)
+{
+  uint32_t  status = buffer_pool_status->status;
+  dbsm_process_status(&sd_sm, status);
+}
+
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nsd_bounce\n");
+
+  // Get our clock from the mimo interface
+  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+  dbsm_init(&sd_sm, SERDES_RX_BUF_0,
+	    &sd_recv_args, &sd_send_args,
+	    sd_rx_inspector);
+
+  // kick off the state machine
+  dbsm_start(&sd_sm);
+
+  while(1){
+    buffer_irq_handler();
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/sd_gentest.c b/firmware/microblaze/apps/cruft/sd_gentest.c
new file mode 100644
index 000000000..35e912615
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/sd_gentest.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "nonstdio.h"
+#include "memset_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <clocks.h>
+#include <mdelay.h>
+
+// ----------------------------------------------------------------
+
+int packet_number = 0;
+volatile bool send_packet_now = 0;
+
+#define SERDES_TX_BUF	0
+#define	SERDES_RX_BUF 	1
+
+
+#define NLINES_PER_PKT	380
+
+
+// ----------------------------------------------------------------
+
+//static int timer_delta = (int)(MASTER_CLK_RATE * 100e-6);
+static int timer_delta = 1000000; // .01 second
+
+void
+timer_irq_handler(unsigned irq)
+{
+  hal_set_timeout(timer_delta);	// schedule next timeout
+  send_packet_now = true;
+}
+
+
+static void
+init_packet(int *buf)
+{
+  int i = 0;
+  for (i = 0; i < BP_NLINES; i++){
+    buf[i] = ((2*i + 0) << 16) | (2*i+1);
+  }
+}
+
+static bool
+check_packet(int *buf, int nlines)
+{
+  bool ok = true;
+  int i = 0;
+  for (i = 0; i < nlines; i++){
+    int expected = ((2*i + 0) << 16) | (2*i+1);
+    if (buf[i] != expected){
+      ok = false;
+      printf("buf[%d] = 0x%x  expected = 0x%x\n", i, buf[i], expected);
+    }
+  }
+  return ok;
+}
+
+static void
+zero_buffer(int bufno)
+{
+  memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
+}
+
+static void
+init_packets(void)
+{
+  // init just the one we're using
+  init_packet(buffer_ram(SERDES_TX_BUF));
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  // We're free running and provide clock to the MIMO interface
+  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  // output_regs->debug_mux_ctrl = 1;
+  // hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  // hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\nsd_gentest\n");
+  
+  // Set up serdes (already enabled)
+  //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN | SERDES_LOOPEN);
+  //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN);
+
+  init_packets();
+
+  // pic_register_handler(IRQ_TIMER, timer_irq_handler);
+
+  //if (hwconfig_simulation_p())
+  //  timer_delta = sim_timer_delta;
+
+  // start a receive from sd
+  zero_buffer(SERDES_RX_BUF);
+  bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+
+  // fire off the first packet
+  bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+  hal_set_timeout(timer_delta);
+  int ready_to_send = 0;
+
+  int counter __attribute__((unused)) = 0;
+  int sent = 1;
+  int txerr = 0;
+  int rxerr = 0;
+  int rcvd = 0;
+  int rxcrc = 0;
+  int sent_acc = 0;
+  int txerr_acc = 0;
+  int rxerr_acc = 0;
+  int rcvd_acc = 0;
+  int rxcrc_acc = 0;
+
+#define EXPECTING_PKT() ((counter & 0x1) == 0)
+#define	SEND_PKT()      ((counter & 0x1) != 0)
+
+  bool got_packet = false;
+
+  while(1){
+    uint32_t status = buffer_pool_status->status;
+
+    if (status & (BPS_DONE(SERDES_RX_BUF))){
+      bp_clear_buf(SERDES_RX_BUF);
+      got_packet = true;
+
+      //hal_toggle_leds(0x2);
+
+      // check packet
+      int last_line = buffer_pool_status->last_line[SERDES_RX_BUF]-1;
+      bool ok = check_packet(buffer_ram(SERDES_RX_BUF), last_line);
+      
+      if (ok) {
+	rcvd++;
+	//putchar('r');
+      }
+      else {
+	rcvd++;
+	rxcrc++;
+	//putchar('P');
+      }
+      // start a receive from sd
+      zero_buffer(SERDES_RX_BUF);
+      bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+    }
+
+    if (status & (BPS_ERROR(SERDES_RX_BUF))){
+      bp_clear_buf(SERDES_RX_BUF);
+      got_packet = true;
+      rcvd++;
+      rxerr++;
+      //putchar('E');
+
+      // start a receive from sd
+      zero_buffer(SERDES_RX_BUF);
+      bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
+    }
+
+    if (status & (BPS_DONE(SERDES_TX_BUF))){
+      bp_clear_buf(SERDES_TX_BUF);
+      //putchar('t');
+      bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+      //mdelay(1);
+      int	i;
+      for (i = 0; i < 50; i++){
+	asm volatile ("or  r0, r0, r0\n\
+		   or  r0, r0, r0\n    \
+		   or  r0, r0, r0\n    \
+		   or  r0, r0, r0\n    \
+		   or  r0, r0, r0\n    \
+		   or  r0, r0, r0\n    \
+		   or  r0, r0, r0\n");
+      }
+      sent ++;
+      ready_to_send = 1;
+      //hal_toggle_leds(0x1);
+    }
+
+    if (status & BPS_ERROR(SERDES_TX_BUF)){
+      bp_clear_buf(SERDES_TX_BUF);
+      sent++;
+      txerr++;
+      ready_to_send = 1;
+      //putchar('X');
+    }
+
+    if(sent >=1000) {
+      printf("Status\tSENT %d\tTXERR %d\t",sent,txerr);
+      printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n",rcvd, rxerr, rxcrc, sent-rcvd);
+      sent_acc += sent; sent = 0;
+      txerr_acc += txerr; txerr = 0;
+      rcvd_acc += rcvd; rcvd = 0;
+      rxerr_acc += rxerr; rxerr = 0;
+      rxcrc_acc += rxcrc; rxcrc = 0;
+    }
+
+    if(sent_acc >=10000) {
+      printf("\nOverall\tSENT %d\tTXERR %d\t",sent_acc,txerr_acc);
+      printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n\n",rcvd_acc, rxerr_acc, rxcrc_acc, sent_acc-rcvd_acc);
+      sent_acc = 0;
+      txerr_acc = 0;
+      rcvd_acc = 0;
+      rxerr_acc = 0;
+      rxcrc_acc = 0;
+    }
+#if 0
+    int pending = pic_regs->pending;
+    if (pending & PIC_TIMER_INT){
+      hal_set_timeout(timer_delta);
+      
+      /*
+	if (EXPECTING_PKT()){
+	if (!got_packet)
+	  putchar('T');
+	got_packet = false;
+      }
+
+      if (SEND_PKT()){
+	if (status & BPS_IDLE(SERDES_TX_BUF))
+	  bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+      }
+      counter++;
+      */
+
+      putchar('T');
+      if(ready_to_send) {
+	bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
+	counter++;
+	ready_to_send = 0;
+      }
+      
+      pic_regs->pending = PIC_TIMER_INT;	// clear pending interrupt
+    }
+#endif
+  }
+  
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/serdes_to_dsp.c b/firmware/microblaze/apps/cruft/serdes_to_dsp.c
new file mode 100644
index 000000000..4994e0a69
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/serdes_to_dsp.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+//#define CPU_TX_BUF 	1	// cpu -> eth
+
+#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
+#define	DSP_RX_BUF_1	3	// dsp rx -> eth
+#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
+#define	DSP_TX_BUF_1	5	// eth -> dsp tx
+
+/*
+ * ================================================================
+ *      configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_SERDES,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past transport header
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+void
+start_rx_cmd(const eth_mac_addr_t *host, op_start_rx_t *p)
+{
+}
+
+void
+stop_rx_cmd(void)
+{
+}
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 256;
+  int interp = 32;
+
+  op_config_tx_t def_config;
+  memset(&def_config, 0, sizeof(def_config));
+  def_config.phase_inc  = 408021893;			// 9.5 MHz [2**32 * fc/fsample]
+  def_config.scale_iq = (tx_scale << 16) | tx_scale;
+  def_config.interp = interp;
+
+  // setup Tx DSP regs
+  config_tx_cmd(&def_config);
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  //hal_toggle_leds(0x2);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  dbsm_process_status(&dsp_tx_sm, status);
+
+  if (status & BPS_DONE(CPU_TX_BUF)){
+    bp_clear_buf(CPU_TX_BUF);
+  }
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  // Get our clock from the mimo interface
+
+  clocks_enable_test_clk(true,1);
+  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+  
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\nserdes_to_dsp\n");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+	    &dsp_tx_recv_args, &dsp_tx_send_args,
+	    eth_pkt_inspector);
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  while(1){
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;	// poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
+      putchar('U');
+    }
+  }
+}
+
diff --git a/firmware/microblaze/apps/cruft/serdes_txrx.c b/firmware/microblaze/apps/cruft/serdes_txrx.c
new file mode 100644
index 000000000..2c47c9628
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/serdes_txrx.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;	// used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between serdes and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow
+ * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+
+#define	DSP_RX_BUF_0	2	// dsp rx -> serdes (double buffer)
+#define	DSP_RX_BUF_1	3	// dsp rx -> serdes
+#define	DSP_TX_BUF_0	4	// serdes -> dsp tx (double buffer)
+#define	DSP_TX_BUF_1	5	// serdes -> dsp tx
+
+/*
+ * ==================================================================
+ *   configure DSP TX double buffering state machine (serdes -> dsp)
+ * ==================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
+
+// Receive from serdes
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_SERDES,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past transport header
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+/*
+ * =================================================================
+ *   configure DSP RX double buffering state machine (dsp -> serdes)
+ * =================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to serdes
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_SERDES,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool         streaming_p = false;
+static unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD	1000
+
+bool is_streaming(void){ return streaming_p; }
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;			// reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);			// set "chain" bit
+
+  // kick off the state machine
+  dbsm_start(&dsp_rx_sm);
+
+  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
+
+  // make sure this one and the rest have the "now" and "chain" bits set.
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+	      streaming_items_per_frame,
+	      1, 1);				
+
+  dsp_rx_regs->rx_time = 0;		// enqueue second command
+}
+
+void
+start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  host_mac_addr = *host;	// remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t	pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;	// flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 256;
+  int interp = 32;
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = interp;
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;		// we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  // hal_toggle_leds(LED_A);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  if (0 && (status & ~BPS_IDLE_ALL)){
+    putstr("status = ");
+    puthex32_nl(status);
+  }
+
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  output_regs->led_src = 0x3;		// h/w controls bottom two bits
+  clocks_enable_test_clk(true, 1);
+
+  putstr("\nSERDES TxRx\n");
+
+  cpu_tx_buf_dest_port = PORT_SERDES;
+
+  // ethernet_register_link_changed_callback(link_changed_callback);
+  // ethernet_init();
+
+  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+  // puts("post clocks_mimo_config");
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 0
+  output_regs->debug_mux_ctrl = 1;
+  hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
+  hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+	    &dsp_tx_recv_args, &dsp_tx_send_args,
+	    eth_pkt_inspector);
+
+
+  //output_regs->flush_icache = 1;
+ 
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	      &dsp_rx_recv_args, &dsp_rx_send_args,
+	      dbsm_nop_inspector);
+  }
+
+  // puts("post dbsm_init's");
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+  // program tx registers
+  setup_tx();
+
+  // puts("post setup_tx");
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  // puts("post dbsm_start");
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;		// poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
+      putchar('U');
+    }
+
+    if (pending & PIC_OVERRUN_INT){
+      dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+	// restart_streaming();
+	// FIXME report error
+      }
+      else {
+	// FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/set_hw_rev.c b/firmware/microblaze/apps/cruft/set_hw_rev.c
new file mode 100644
index 000000000..d4ac8ff81
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/set_hw_rev.c
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+
+#define HW_REV_MAJOR 0
+#define HW_REV_MINOR 3
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nset_hw_rev\n");
+
+  bool ok = true;
+  unsigned char maj = HW_REV_MAJOR;
+  unsigned char min = HW_REV_MINOR;
+  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
+  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
+
+  if (ok)
+    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+  else
+    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/test1.c b/firmware/microblaze/apps/cruft/test1.c
new file mode 100644
index 000000000..c3cc3be56
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test1.c
@@ -0,0 +1,282 @@
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+// Globals
+#define EMPTY 0
+#define FILLING 1
+#define FULL 2
+#define EMPTYING 3
+
+#define PORT 2    // ethernet = 2, serdes = 0
+int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
+int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
+
+int buffer_state[4];
+
+
+void double_buffering(int port);
+
+//
+// We register this in the secondary interrupt vector.
+// It's called on buffer manager interrupts
+//
+void
+buffer_irq_handler(unsigned irq)
+{
+  double_buffering(PORT);
+}
+
+int
+main(void)
+{
+  int i;
+
+  u2_init();
+
+  // Control LEDs
+  output_regs->leds = 0x02;
+
+  // Turn on ADCs
+  output_regs->adc_ctrl = 0x0A;
+
+  // Set up TX Chain
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (1 << 16) | 1;
+  dsp_tx_regs->interp_rate = 8;
+
+  // Set up RX Chain
+  dsp_rx_regs->freq = 0;
+  dsp_rx_regs->scale_iq = (1 << 16) | 1;
+  dsp_rx_regs->decim_rate = 8;
+
+  // Set up buffer control, using only 4 for now
+  for(i=0;i<4;i++) 
+    buffer_state[i] = EMPTY;
+
+  // Set up DSP RX
+  buffer_state[0] = FILLING;
+  serdes_tx_idle = 1;
+  bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
+
+  //dsp_rx_regs->run_rx = 1;           // Start DSP_RX
+  putstr("Done DSP RX setup\n");
+
+  // Set up serdes RX
+  buffer_state[2] = FILLING;
+  dsp_tx_idle = 1;
+  bp_receive_to_buf(2, PORT, 1, 5, 504);
+
+  while (buffer_pool_status->status == 0)  // wait for completion of DSP RX
+    ;
+
+  putstr("Done DSP TX setup\n");
+  //dsp_tx_regs->run_tx = 1;
+
+  // register interrupt handler
+  pic_register_handler(IRQ_BUFFER, buffer_irq_handler);
+
+  while (1)
+    ;
+
+  hal_finish();
+  return 1;
+}
+
+void 
+double_buffering(int port) {
+  unsigned int localstatus = buffer_pool_status->status;
+
+  if(localstatus & BPS_DONE_0) {
+    bp_clear_buf(0);
+    if(buffer_state[0] == FILLING) {
+      buffer_state[0] = FULL;
+      if(buffer_state[1] == EMPTY) {
+	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[1] = FILLING;
+      }
+      else
+	dsp_rx_idle = 1;
+      if(serdes_tx_idle) {
+	serdes_tx_idle = 0;
+	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
+	buffer_state[0] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[0] = EMPTY;
+      if(dsp_rx_idle) {
+	dsp_rx_idle = 0;
+	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
+	buffer_state[0] = FILLING;
+      }
+      if(buffer_state[1] == FULL) {
+	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
+	buffer_state[1] = EMPTYING;
+      }
+      else
+	serdes_tx_idle = 1;
+    }
+    putstr("Int Proc'ed 0\n");
+  }
+  if(localstatus & BPS_DONE_1) {
+    bp_clear_buf(1);
+    if(buffer_state[1] == FILLING) {
+      buffer_state[1] = FULL;
+      if(buffer_state[0] == EMPTY) {
+	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[0] = FILLING;
+      }
+      else
+	dsp_rx_idle = 1;
+      if(serdes_tx_idle) {
+	serdes_tx_idle = 0;
+	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
+	buffer_state[1] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[1] = EMPTY;
+      if(dsp_rx_idle) {
+	dsp_rx_idle = 0;
+	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
+	buffer_state[1] = FILLING;
+      }
+      if(buffer_state[0] == FULL) {
+	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
+	buffer_state[0] = EMPTYING;
+      }
+      else
+	serdes_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 1\n");
+  }
+  if(localstatus & BPS_DONE_2) {
+    bp_clear_buf(2);
+    if(buffer_state[2] == FILLING) {
+      buffer_state[2] = FULL;
+      if(buffer_state[3] == EMPTY) {
+	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3, use 500 lines
+	buffer_state[3] = FILLING;
+      }
+      else
+	serdes_rx_idle = 1;
+      if(dsp_tx_idle) {
+	dsp_tx_idle = 0;
+	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
+	buffer_state[2] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[2] = EMPTY;
+      if(serdes_rx_idle) {
+	serdes_rx_idle = 0;
+	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2
+	buffer_state[2] = FILLING;
+      }
+      if(buffer_state[3] == FULL) {
+	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
+	buffer_state[3] = EMPTYING;
+      }
+      else
+	dsp_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 2\n");
+  }
+  if(localstatus & BPS_DONE_3) {
+    bp_clear_buf(3);
+    if(buffer_state[3] == FILLING) {
+      buffer_state[3] = FULL;
+      if(buffer_state[2] == EMPTY) {
+	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2, use 500 lines
+	buffer_state[2] = FILLING;
+      }
+      else
+	serdes_rx_idle = 1;
+      if(dsp_tx_idle) {
+	dsp_tx_idle = 0;
+	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
+	buffer_state[3] = EMPTYING;
+      }
+    }
+    else {  // buffer was emptying
+      buffer_state[3] = EMPTY;
+      if(serdes_rx_idle) {
+	serdes_rx_idle = 0;
+	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3
+	buffer_state[3] = FILLING;
+      }
+      if(buffer_state[2] == FULL) {
+	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
+	buffer_state[2] = EMPTYING;
+      }
+      else
+	dsp_tx_idle = 1;
+    }
+  putstr("Int Proc'ed 3\n");
+  }
+}
+
+// Spare Code
+
+#if 0  
+  // Set up LSDAC
+  int i = 0;
+  while(1) {
+    int command = (3 << 19) | (0 << 16) |  (i & 0xffff);
+    spi_transact(SPI_TXONLY, SPI_SS_TX_DAC, command, 24, 1); // negate TX phase
+    i++;
+  }
+#endif
+
+#if 0  
+  // Write to buffer 0
+  int *buf = (int *)(BUFFER_BASE + BUFFER_0);
+  puthex_nl((int)buf);
+
+  for(i=0;i<BUFFER_SIZE;i++)
+    buf[i] = i;
+
+  putstr("Filled buffer 0\n");
+
+  // Write to buffer 1
+  buf = (int *)(BUFFER_BASE + BUFFER_1);
+  puthex_nl((int)buf);
+  for(i=0;i<BUFFER_SIZE;i++)
+    buf[i] =  i + ((i^0xFFFF) << 16);
+
+  putstr("Filled buffer 1\n");
+
+#endif
+
+#if 0
+  // rx SERDES into buffer #2  (buf,port,step,fl,ll)
+  bp_receive_to_buf(2, 0, 1, 10, 300);
+  putstr("SERDES RX buffer setup\n");
+
+  // send SERDES from buffer #0 (buf,port,step,fl,ll)
+  bp_send_from_buf(0, 0, 1, 20, 200);
+  putstr("SERDES TX buffer setup\n");
+
+#endif
+
+#if 0
+  // send to DACs from buffer #1
+  bp_send_from_buf(1 /*buf#*/, 1 /*port*/, 1 /*step*/, 20 /*fl*/, 250 /*ll*/);
+  putstr("DAC Buffer setup\n");
+#endif
+
+#if 0
+  //putstr("ENTER INT\n");
+  for(i=0;i<8;i++)
+    if(*status & (1<<i)) {
+      //putstr("Clearing buf ");
+      puthex_nl(i);
+      bp_clear_buf(i);
+    }
+  //putstr("EXIT INT\n");
+#endif
diff --git a/firmware/microblaze/apps/cruft/test_db_spi.c b/firmware/microblaze/apps/cruft/test_db_spi.c
new file mode 100644
index 000000000..f4fa98ef1
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_db_spi.c
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+#include <spi.h>
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("\ntest_db_spi");
+
+  while(1){
+    spi_transact(SPI_TXONLY, SPI_SS_RX_DB, 0xCC33, 16, SPIF_PUSH_FALL);
+    spi_transact(SPI_TXONLY, SPI_SS_TX_DB, 0x33CC, 16, SPIF_PUSH_FALL);
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/test_i2c.c b/firmware/microblaze/apps/cruft/test_i2c.c
new file mode 100644
index 000000000..f349ead88
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_i2c.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <u2_init.h>		/* FIXME */
+#include <i2c.h>
+#include <usrp2_i2c_addr.h>
+#include <string.h>
+#include <hal_io.h>
+
+
+
+#define ASSERT_TRUE(x) \
+  do { \
+    if (!(x)){ \
+      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+#define ASSERT_FALSE(x) \
+  do { \
+    if (x){ \
+      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+
+#define BUFSIZE 128
+
+int
+main(void)
+{
+  int i;
+  bool ok;
+  int  nerrors = 0;
+  uint8_t buf[BUFSIZE];
+  int not_dev_addr = 0x35;	// no device with this address on the i2c bus.
+  int offset;
+  int len;
+  
+  u2_init();
+
+  puts("test_i2c\n");
+
+  // try writing a non-existent device
+  buf[0] = 0xA5;
+  ok = i2c_write(not_dev_addr, buf, 1);
+  ASSERT_FALSE(ok);
+
+  // try read from non-existent device
+  buf[0] = 0;
+  ok = i2c_read(not_dev_addr, buf, 1);
+  ASSERT_FALSE(ok);
+
+  // try writing eeprom
+  offset = 31;
+  len = 8;
+  memset(buf, 0, sizeof(buf));
+  for (i = 0; i < len; i++)
+    buf[i] = i;
+  ok = eeprom_write(I2C_ADDR_MBOARD, offset, buf, len);
+  ASSERT_TRUE(ok);
+
+  // now try to read it back
+  offset = 31;
+  len = 8;
+  memset(buf, 0, sizeof(buf));
+  ok = eeprom_read(I2C_ADDR_MBOARD, offset, buf, len);
+  ASSERT_TRUE(ok);
+
+  // check result
+  for (i = 0; i < len; i++){
+    if (buf[i] != i){
+      printf("buf[%d] = %d, should be %d\n", i, buf[i], i);
+      nerrors++;
+    }
+  }
+  
+  if (nerrors == 0){
+    output_regs->leds = 0x3;
+    puts("PASSED\n");
+  }
+  else {
+    output_regs->leds = 0x0;
+    puts("FAILED\n");
+  }
+
+  hal_finish();
+  return 0;
+}
+
diff --git a/firmware/microblaze/apps/cruft/test_lsadc.c b/firmware/microblaze/apps/cruft/test_lsadc.c
new file mode 100644
index 000000000..5fda29cd7
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_lsadc.c
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <lsadc.h>
+#include <lsdac.h>
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("\ntest_lsadc");
+
+  uint32_t r;
+
+  unsigned int up_counter = 0;
+  
+  while (1){
+    unsigned int v;
+    v = up_counter;
+
+    lsdac_write_rx(0, v << 0);
+    lsdac_write_rx(2, v << 1);
+
+#if 1
+    r = lsadc_read_rx(0);
+    lsdac_write_rx(1, r & 0x0fff);
+    //puthex32_nl(r);
+#endif
+
+#if 1
+    r = lsadc_read_rx(1);
+    lsdac_write_rx(3, r & 0x0fff);
+    //puthex32_nl(r);
+#endif
+
+    up_counter++;
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/test_lsdac.c b/firmware/microblaze/apps/cruft/test_lsdac.c
new file mode 100644
index 000000000..8c1bf333b
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_lsdac.c
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <lsdac.h>
+#include <u2_init.h>
+#include <nonstdio.h>
+#include <hal_io.h>
+
+int
+main(void)
+{
+  u2_init();
+
+  puts("\ntest_lsdac");
+
+  unsigned int up_counter = 0;
+  unsigned int dn_counter = 0;
+
+  while(1){
+    unsigned int v;
+    v = up_counter;
+    lsdac_write_rx(0, v << 0);
+    lsdac_write_rx(1, v << 1);
+    lsdac_write_rx(2, v << 2);
+    lsdac_write_rx(3, v << 3);
+
+    v = up_counter;
+    lsdac_write_tx(0, v << 0);
+    lsdac_write_tx(1, v << 1);
+    lsdac_write_tx(2, v << 2);
+    lsdac_write_tx(3, v << 3);
+
+    up_counter++;
+    dn_counter--;
+  }
+}
diff --git a/firmware/microblaze/apps/cruft/test_phy_comm.c b/firmware/microblaze/apps/cruft/test_phy_comm.c
new file mode 100644
index 000000000..d312ca4cc
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_phy_comm.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// check communication with ethernet PHY chip
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "ethernet.h"
+#include "pic.h"
+#include "nonstdio.h"
+
+
+#define DELTA_T     12500000  		// .125s (10ns per tick)
+//#define DELTA_T      10000
+
+// debugging output on tx pins
+#define LS_MASK  0xE0000
+#define LS_1000  0x80000
+#define LS_100   0x40000
+#define LS_10    0x20000
+
+
+
+#define U2_ETHERTYPE 0xBEEF
+
+
+static volatile int led_link_up_flag = 0;
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  int v = 0;
+  switch(speed){
+  case 10:
+    v = LS_10;
+    led_link_up_flag = 0x2;
+    break;
+    
+  case 100:
+    v = LS_100;
+    led_link_up_flag = 0x2;
+    break;
+    
+  case 1000:
+    v = LS_100;
+    led_link_up_flag = 0x2;
+    break;
+
+  default:
+    v = 0;
+    led_link_up_flag = 0;
+    break;
+  }
+
+  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
+
+  putstr("\neth link changed: speed = ");
+  puthex_nl(speed);
+}
+
+void
+timer_handler(unsigned irq)
+{
+  static int led_counter = 0;
+
+  hal_set_timeout(DELTA_T);	// schedule next timeout
+  output_regs->leds = (led_counter++ & 0x1) | led_link_up_flag;
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\n test_phy_comm\n");
+
+  pic_register_handler(IRQ_ONETIME, timer_handler);
+  hal_set_timeout(DELTA_T);	// schedule timeout
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+
+  output_regs->phy_ctrl = 1;	/* reset the eth PHY */
+  output_regs->phy_ctrl = 0;
+
+  ethernet_init();
+
+  while(1)
+    ;
+
+  return 0;
+}
diff --git a/firmware/microblaze/apps/cruft/test_ram.c b/firmware/microblaze/apps/cruft/test_ram.c
new file mode 100644
index 000000000..77ee693f6
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_ram.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <u2_init.h>		/* FIXME */
+#include <sd.h>
+#include <string.h>
+#include <hal_io.h>
+#include <nonstdio.h>
+#include <hal_uart.h>
+
+#define ASSERT_TRUE(x) \
+  do { \
+    if (!(x)){ \
+      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+#define ASSERT_FALSE(x) \
+  do { \
+    if (x){ \
+      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+
+#define BUFSIZE 128
+
+int test_ram()
+{
+  int i,j,k;
+  output_regs->ram_page = 1<<10;
+  
+  extram[0] = 0xDEADBEEF;
+  extram[1] = 0xF00D1234;
+  extram[7] = 0x76543210;
+  
+  output_regs->ram_page = 2<<10;
+  extram[7] = 0x55555555;
+  extram[1] = 0xaaaaaaaa;
+  extram[0] = 0xeeeeeeee;
+  
+  output_regs->ram_page = 1<<10;
+  
+  i = extram[0];
+  k = extram[1];
+  j = extram[7];
+  
+  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
+    puts("RAM FAIL1!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  
+  output_regs->ram_page = 2<<10;
+
+  j = extram[7];
+  k = extram[1];
+  i = extram[0];
+
+  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
+    puts("RAM FAIL2!\n");
+    puthex32_nl(i);
+    puthex32_nl(j);
+    puthex32_nl(k);
+    return 0;
+  }
+  return 1;
+}
+
+int
+main(void)
+{
+
+  u2_init();
+  puts("\ntest_ram\n");
+  int success = test_ram();
+  if(success)
+    puts("RAM Passed Tests\n");
+  else
+    puts("RAM Failed\n");
+
+  hal_finish();
+  return 0;
+}
+
diff --git a/firmware/microblaze/apps/cruft/test_sd.c b/firmware/microblaze/apps/cruft/test_sd.c
new file mode 100644
index 000000000..494432d7f
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/test_sd.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <u2_init.h>		/* FIXME */
+#include <sd.h>
+#include <string.h>
+#include <hal_io.h>
+#include <nonstdio.h>
+
+
+#define ASSERT_TRUE(x) \
+  do { \
+    if (!(x)){ \
+      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+#define ASSERT_FALSE(x) \
+  do { \
+    if (x){ \
+      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
+      nerrors++; \
+    } \
+  } while(0)
+
+
+#define BUFSIZE 128
+
+int
+main(void)
+{
+  int i;
+  unsigned char buf[512];
+
+  u2_init();
+
+  puts("\ntest_sd\n");
+  
+
+  i = sd_init();
+  if(i)
+    puts("Successfully Init'ed Card\n");
+  else
+    puts("FAILED INIT of Card\n");
+
+  i = sd_read_block(2048,buf);
+  if(i) {
+    puts("READ Command accepted\n");
+    for(i=0;i<512;i++)
+      if((i&15) == 15)
+	puthex8_nl(buf[i]);
+      else {
+	puthex8(buf[i]);
+	putchar(' ');
+      }
+  }
+  else
+    puts("READ Command Rejected\n");
+  
+  puts("Done");
+  hal_finish();
+  return 0;
+}
+
diff --git a/firmware/microblaze/apps/cruft/timer_test.c b/firmware/microblaze/apps/cruft/timer_test.c
new file mode 100644
index 000000000..44e80b5f1
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/timer_test.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "nonstdio.h"
+#include "hal_io.h"
+
+#define DELTA_T  500  		// 5 us (10ns per tick)
+
+
+void 
+timer_handler(unsigned irq)
+{
+  hal_set_timeout(DELTA_T);
+
+  putstr("Tick: ");
+  puthex_nl(0);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  // setup timer
+
+  putstr("Setting up timer\n");
+  pic_register_handler(IRQ_ONETIME, timer_handler);
+
+  hal_set_timeout(DELTA_T);
+
+  while (1)
+    ;
+
+  putstr("Done Testing\n");
+  
+  hal_finish();
+  return 1;
+}
diff --git a/firmware/microblaze/apps/cruft/tx_standalone.c b/firmware/microblaze/apps/cruft/tx_standalone.c
new file mode 100644
index 000000000..1645fa8ba
--- /dev/null
+++ b/firmware/microblaze/apps/cruft/tx_standalone.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include <stdbool.h>
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "dbsm.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define	_AL4 __attribute__((aligned (4)))
+
+#define USE_BUFFER_INTERRUPT	0	// 0 or 1
+
+
+static int timer_delta = MASTER_CLK_RATE/1000;	// tick at 1kHz
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF	0	// eth -> cpu
+#define CPU_TX_BUF 	1	// cpu -> eth
+
+#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
+#define	DSP_RX_BUF_1	3	// dsp rx -> eth
+#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
+#define	DSP_TX_BUF_1	5	// eth -> dsp tx
+
+
+/*
+ * ================================================================
+ *      configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+
+// 4 lines of ethernet hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE		  5
+#define DSP_RX_SAMPLES_PER_FRAME	128
+#define	DSP_RX_EXTRA_LINES		  1	// writes timestamp
+
+// Receive from DSP Rx
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to ethernet
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,		// starts with ethernet header in line 0
+  0,		// filled in from last_line register
+};
+
+dbsm_t dsp_rx_sm;	// the state machine
+
+/*
+ * ================================================================
+ *      configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE		  4
+#define DSP_TX_SAMPLES_PER_FRAME	250	// not used except w/ debugging
+#define	DSP_TX_EXTRA_LINES		  2	// reads word0 + timestamp
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,	// starts just past ethernet header
+  0			// filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;	// the state machine
+
+/*
+ * send constant buffer to DSP TX
+ */
+static inline void 
+SEND_CONST_TO_DSP_TX(void)
+{
+  bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1,
+		   DSP_TX_FIRST_LINE,
+		   DSP_TX_FIRST_LINE + DSP_TX_EXTRA_LINES + DSP_TX_SAMPLES_PER_FRAME - 1);
+}
+
+// ----------------------------------------------------------------
+
+
+
+// The mac address of the host we're sending to.
+eth_mac_addr_t host_mac_addr;
+
+
+void link_changed_callback(int speed);
+static volatile bool link_is_up = false;	// eth handler sets this
+
+
+void
+timer_irq_handler(unsigned irq)
+{
+  hal_set_timeout(timer_delta);	// schedule next timeout
+}
+
+// Tx DSP underrun
+void
+underrun_irq_handler(unsigned irq)
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+  dbsm_stop(&dsp_tx_sm);
+
+  // FIXME anything else?
+
+  putstr("\nirq: underrun\n");
+}
+
+// Rx DSP overrun
+void
+overrun_irq_handler(unsigned irq)
+{
+  dsp_rx_regs->clear_state = 1;
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+  dbsm_stop(&dsp_rx_sm);
+
+  // FIXME anything else?
+
+  putstr("\nirq: overrun\n");
+}
+
+static void
+start_tx_transfers(void)
+{
+  bp_clear_buf(DSP_TX_BUF_0);	// FIXME, really goes in state machine
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  // fill everything with a constant 32k + 0j
+
+  uint32_t const_sample = (32000 << 16) | 0;
+  int i;
+  for (i = 0; i < BP_NLINES; i++){
+    buffer_ram(DSP_TX_BUF_0)[i] = const_sample;
+    buffer_ram(DSP_TX_BUF_1)[i] = const_sample;
+  }
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t	pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  //pkt.ehdr.dst = *host;
+  pkt.ehdr.src = *ethernet_mac_addr();
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed,
+		U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0);
+  u2p_set_timestamp(&pkt.fixed, T_NOW);
+
+  memcpy_wa(buffer_ram(DSP_TX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_TX_BUF_1), &pkt, sizeof(pkt));
+
+
+  int tx_scale = 256;
+
+  // setup Tx DSP regs
+  dsp_tx_regs->clear_state = 1;			// reset
+  dsp_tx_regs->freq = 408021893;		// 9.5 MHz [2**32 * fc/fsample]
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = 32;
+
+  // kick off the state machine
+  // dbsm_start(&dsp_rx_sm);
+
+  SEND_CONST_TO_DSP_TX();	// send constant buffer to DSP TX
+}
+
+
+void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  if (0){
+    putstr("irq: ");
+    puthex32(status);
+    putchar('\n');
+  }
+
+  if (status & BPS_ERROR_ALL){
+    // FIXME rare path, handle error conditions
+  }
+
+  if (status & BPS_DONE(DSP_TX_BUF_0)){
+    bp_clear_buf(DSP_TX_BUF_0);
+    SEND_CONST_TO_DSP_TX();
+    hal_toggle_leds(0x1);
+  }
+
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
+  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+
+  putstr("\ntx_only\n");
+  
+  // Control LEDs
+  hal_set_leds(0x0, 0x3);
+
+  if (USE_BUFFER_INTERRUPT)
+    pic_register_handler(IRQ_BUFFER,   buffer_irq_handler);
+
+  pic_register_handler(IRQ_OVERRUN,  overrun_irq_handler);
+  pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
+
+  //pic_register_handler(IRQ_TIMER, timer_irq_handler);
+  //hal_set_timeout(timer_delta);
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+
+  ethernet_init();
+
+  // initialize double buffering state machine for DSP RX -> Ethernet
+  dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+	    &dsp_rx_recv_args, &dsp_rx_send_args,
+	    dbsm_nop_inspector);
+
+  // setup receive from ETH
+  // bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+#if 0
+  if (hwconfig_simulation_p()){
+    // If we're simulating, pretend that we got a start command from the host
+    eth_mac_addr_t host = {{ 0x00, 0x0A, 0xE4, 0x3E, 0xD2, 0xD5 }};
+    start_rx_cmd(&host);
+  }
+#endif
+
+  start_tx_transfers();		// send constant buffers to DSP TX
+
+  while(1){
+    if (!USE_BUFFER_INTERRUPT)
+      buffer_irq_handler(0);
+  }
+}
+
+// ----------------------------------------------------------------
+
+// debugging output on tx pins
+#define LS_MASK  0xE0000
+#define LS_1000  0x80000
+#define LS_100   0x40000
+#define LS_10    0x20000
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  int v = 0;
+  switch(speed){
+  case 10:
+    v = LS_10;
+    link_is_up = true;
+    break;
+    
+  case 100:
+    v = LS_100;
+    link_is_up = true;
+    break;
+    
+  case 1000:
+    v = LS_100;
+    link_is_up = true;
+    break;
+
+  default:
+    v = 0;
+    link_is_up = false;
+    break;
+  }
+
+  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
+
+  // hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
+
+  printf("\neth link changed: speed = %d\n", speed);
+}
diff --git a/firmware/microblaze/apps/double_buffer_fragment.c b/firmware/microblaze/apps/double_buffer_fragment.c
deleted file mode 100644
index cfc061247..000000000
--- a/firmware/microblaze/apps/double_buffer_fragment.c
+++ /dev/null
@@ -1,138 +0,0 @@
-#if 0
-void 
-double_buffering(int port) {
-  unsigned int localstatus = buffer_pool_status->status;
-
-  if(localstatus & BPS_DONE_0) {
-    bp_clear_buf(0);
-    if(buffer_state[0] == FILLING) {
-      buffer_state[0] = FULL;
-      if(buffer_state[1] == EMPTY) {
-	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[1] = FILLING;
-      }
-      else
-	dsp_rx_idle = 1;
-      if(serdes_tx_idle) {
-	serdes_tx_idle = 0;
-	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
-	buffer_state[0] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[0] = EMPTY;
-      if(dsp_rx_idle) {
-	dsp_rx_idle = 0;
-	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
-	buffer_state[0] = FILLING;
-      }
-      if(buffer_state[1] == FULL) {
-	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
-	buffer_state[1] = EMPTYING;
-      }
-      else
-	serdes_tx_idle = 1;
-    }
-    putstr("Int Proc'ed 0\n");
-  }
-
-  if(localstatus & BPS_DONE_1) {
-    bp_clear_buf(1);
-    if(buffer_state[1] == FILLING) {
-      buffer_state[1] = FULL;
-      if(buffer_state[0] == EMPTY) {
-	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[0] = FILLING;
-      }
-      else
-	dsp_rx_idle = 1;
-      if(serdes_tx_idle) {
-	serdes_tx_idle = 0;
-	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
-	buffer_state[1] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[1] = EMPTY;
-      if(dsp_rx_idle) {
-	dsp_rx_idle = 0;
-	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[1] = FILLING;
-      }
-      if(buffer_state[0] == FULL) {
-	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
-	buffer_state[0] = EMPTYING;
-      }
-      else
-	serdes_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 1\n");
-  }
-
-  if(localstatus & BPS_DONE_2) {
-    bp_clear_buf(2);
-    if(buffer_state[2] == FILLING) {
-      buffer_state[2] = FULL;
-      if(buffer_state[3] == EMPTY) {
-	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3, use 500 lines
-	buffer_state[3] = FILLING;
-      }
-      else
-	serdes_rx_idle = 1;
-      if(dsp_tx_idle) {
-	dsp_tx_idle = 0;
-	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
-	buffer_state[2] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[2] = EMPTY;
-      if(serdes_rx_idle) {
-	serdes_rx_idle = 0;
-	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2
-	buffer_state[2] = FILLING;
-      }
-      if(buffer_state[3] == FULL) {
-	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
-	buffer_state[3] = EMPTYING;
-      }
-      else
-	dsp_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 2\n");
-  }
-
-  if(localstatus & BPS_DONE_3) {
-    bp_clear_buf(3);
-    if(buffer_state[3] == FILLING) {
-      buffer_state[3] = FULL;
-      if(buffer_state[2] == EMPTY) {
-	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2, use 500 lines
-	buffer_state[2] = FILLING;
-      }
-      else
-	serdes_rx_idle = 1;
-      if(dsp_tx_idle) {
-	dsp_tx_idle = 0;
-	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
-	buffer_state[3] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[3] = EMPTY;
-      if(serdes_rx_idle) {
-	serdes_rx_idle = 0;
-	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3
-	buffer_state[3] = FILLING;
-      }
-      if(buffer_state[2] == FULL) {
-	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
-	buffer_state[2] = EMPTYING;
-      }
-      else
-	dsp_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 3\n");
-  }
-}
-#endif
diff --git a/firmware/microblaze/apps/echo.c b/firmware/microblaze/apps/echo.c
deleted file mode 100644
index 89108ee80..000000000
--- a/firmware/microblaze/apps/echo.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "u2_init.h"
-#include "stdio.h"
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("\n>>> echo <<<");
-
-  while (1){
-    int ch = getchar();
-    putchar(ch);
-  }
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/eth_serdes.c b/firmware/microblaze/apps/eth_serdes.c
deleted file mode 100644
index 2d2ddc1ca..000000000
--- a/firmware/microblaze/apps/eth_serdes.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_passthru_v2.h"
-#include "memcpy_wa.h"
-#include "clocks.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno __attribute__((unused));	// used when f/w is filling in sequence numbers
-#endif
-
-
-/*
- * Full duplex Tx and Rx between ethernet and serdes
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
- * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-
-#define	DSP_RX_BUF_0	2	// serdes -> eth (double buffer)
-#define	DSP_RX_BUF_1	3	// serdes -> eth
-#define	DSP_TX_BUF_0	4	// eth -> serdes (double buffer)
-#define	DSP_TX_BUF_1	5	// eth -> serdes
-
-/*
- * ================================================================
- *   configure serdes double buffering state machine (eth -> serdes)
- * ================================================================
- */
-
-
-// Receive from ethernet
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_ETH,
-  0,
-  BP_LAST_LINE
-};
-
-// send to serdes
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_SERDES,
-  0,
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-/*
- * ====================================================================
- *   configure serdes RX double buffering state machine (serdes -> eth)
- * ====================================================================
- */
-
-// receive from serdes
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_SERDES,
-  0,
-  BP_LAST_LINE
-};
-
-// send to ETH
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_ETH,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-// ----------------------------------------------------------------
-
-
-#if (FW_SETS_SEQNO)
-/*
- * Debugging ONLY.  This will be handled by the tx_protocol_engine.
- *
- * This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet.  A bit of a kludge
- * but it should work.
- */
-
-bool 
-fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
-{
-#if 0
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t last_line = buffer_pool_status->last_line[buf_this] - sm->last_line_adj;
-  printf("fw_sets_seqno_inspector: buf_this = %d, last_line = %d\n",
-	 buf_this, last_line);
-
-  print_buffer(p, (last_line + 1));
-#endif
-
-#if 0
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t seqno = fw_seqno++;
-
-  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
-  uint32_t t = p[4];
-  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
-  p[4] = t;
-#endif
-
-  return false;		// we didn't handle the packet
-}
-#endif
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  uint32_t  status = buffer_pool_status->status;
-
-  if (0 && (status & ~BPS_IDLE_ALL)){
-    putstr("status = ");
-    puthex32_nl(status);
-  }
-    
-  dbsm_process_status(&dsp_tx_sm, status);
-  dbsm_process_status(&dsp_rx_sm, status);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  output_regs->led_src = 0x3;		// h/w controls bottom two bits
-  clocks_enable_test_clk(true, 1);
-
-  putstr("\neth <-> serdes\n");
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-  ethernet_init();
-
-  // clocks_mimo_config(MC_WE_LOCK_TO_SMA | MC_PROVIDE_CLK_TO_MIMO);
-  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
-
-#if 0
-  // make bit 15 of Tx gpio's be a s/w output
-  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-#if 1
-  output_regs->debug_mux_ctrl = 1;
-  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
-  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
-  // initialize double buffering state machine for ethernet -> serdes
-
-  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
-	    &dsp_tx_recv_args, &dsp_tx_send_args,
-	    eth_pkt_inspector);
-
-
-  // initialize double buffering state machine for serdes -> ethernet
-
-  if (FW_SETS_SEQNO){
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      fw_sets_seqno_inspector);
-  }
-  else {
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      dbsm_nop_inspector);
-  }
-
-  // tell app_common that this dbsm could be sending to the ethernet
-  ac_could_be_sending_to_eth = &dsp_rx_sm;
-
-
-  // kick off the state machines
-  dbsm_start(&dsp_tx_sm);
-  dbsm_start(&dsp_rx_sm);
-
-  //int which = 0;
-
-  while(1){
-    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
-    // which ^= 0x8000;
-
-    buffer_irq_handler(0);
-  }
-}
diff --git a/firmware/microblaze/apps/factory_test.c b/firmware/microblaze/apps/factory_test.c
deleted file mode 100644
index e1fbb0e40..000000000
--- a/firmware/microblaze/apps/factory_test.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-#include <clocks.h>
-#include "sd.h"
-
-#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno;	// used when f/w is filling in sequence numbers
-#endif
-
-
-/*
- * Full duplex Tx and Rx between ethernet and DSP pipelines
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
- * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-
-#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
-#define	DSP_RX_BUF_1	3	// dsp rx -> eth
-#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
-#define	DSP_TX_BUF_1	5	// eth -> dsp tx
-
-/*
- * ================================================================
- *   configure DSP TX double buffering state machine (eth -> dsp)
- * ================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
-
-// Receive from ethernet
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_ETH,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past transport header
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-/*
- * ================================================================
- *   configure DSP RX double buffering state machine (dsp -> eth)
- * ================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
-// DSP Rx writes timestamp followed by nlines_per_frame of samples
-#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
-
-// receive from DSP
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_DSP,
-  DSP_RX_FIRST_LINE,
-  BP_LAST_LINE
-};
-
-// send to ETH
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_ETH,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-// variables for streaming mode
-
-static bool         streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static int          streaming_frame_count = 0;
-#define FRAMES_PER_CMD	1000
-
-bool is_streaming(void){ return streaming_p; }
-
-// ----------------------------------------------------------------
-
-
-void
-restart_streaming(void)
-{
-  // setup RX DSP regs
-  dsp_rx_regs->clear_state = 1;			// reset
-
-  streaming_p = true;
-  streaming_frame_count = FRAMES_PER_CMD;
-
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);			// set "chain" bit
-
-  // kick off the state machine
-  dbsm_start(&dsp_rx_sm);
-
-  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
-
-  // make sure this one and the rest have the "now" and "chain" bits set.
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);				
-
-  dsp_rx_regs->rx_time = 0;		// enqueue second command
-}
-
-void
-start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
-{
-  host_mac_addr = *host;	// remember who we're sending to
-
-  /*
-   * Construct  ethernet header and word0 and preload into two buffers
-   */
-  u2_eth_packet_t	pkt;
-  memset(&pkt, 0, sizeof(pkt));
-  pkt.ehdr.dst = *host;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  u2p_set_word0(&pkt.fixed, 0, 0);
-  // DSP RX will fill in timestamp
-
-  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
-  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
-
-
-  if (FW_SETS_SEQNO)
-    fw_seqno = 0;
-
-  streaming_items_per_frame = p->items_per_frame;
-  restart_streaming();
-}
-
-
-void
-stop_rx_cmd(void)
-{
-  streaming_p = false;
-  dsp_rx_regs->clear_state = 1;	// flush cmd queue
-  bp_clear_buf(DSP_RX_BUF_0);
-  bp_clear_buf(DSP_RX_BUF_1);
-}
-
-
-static void
-setup_tx()
-{
-  dsp_tx_regs->clear_state = 1;
-  bp_clear_buf(DSP_TX_BUF_0);
-  bp_clear_buf(DSP_TX_BUF_1);
-
-  int tx_scale = 256;
-  int interp = 32;
-
-  // setup some defaults
-
-  dsp_tx_regs->freq = 0;
-  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
-  dsp_tx_regs->interp_rate = interp;
-}
-
-
-#if (FW_SETS_SEQNO)
-/*
- * Debugging ONLY.  This will be handled by the tx_protocol_engine.
- *
- * This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet.  A bit of a kludge
- * but it should work.
- */
-bool 
-fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
-{
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t seqno = fw_seqno++;
-
-  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
-  uint32_t t = p[4];
-  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
-  p[4] = t;
-
-  // queue up another rx command when required
-  if (streaming_p && --streaming_frame_count == 0){
-    streaming_frame_count = FRAMES_PER_CMD;
-    dsp_rx_regs->rx_time = 0;
-  }
-
-  return false;		// we didn't handle the packet
-}
-#endif
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  uint32_t  status = buffer_pool_status->status;
-
-  dbsm_process_status(&dsp_tx_sm, status);
-  dbsm_process_status(&dsp_rx_sm, status);
-}
-
-int test_ram()
-{
-  int i,j,k;
-  output_regs->ram_page = 1<<10;
-  
-  extram[0] = 0xDEADBEEF;
-  extram[1] = 0xF00D1234;
-  extram[7] = 0x76543210;
-  
-  output_regs->ram_page = 2<<10;
-  extram[7] = 0x55555555;
-  extram[1] = 0xaaaaaaaa;
-  extram[0] = 0xeeeeeeee;
-  
-  output_regs->ram_page = 1<<10;
-  
-  i = extram[0];
-  k = extram[1];
-  j = extram[7];
-  
-  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
-    puts("RAM FAIL1!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  
-  output_regs->ram_page = 2<<10;
-
-  j = extram[7];
-  k = extram[1];
-  i = extram[0];
-
-  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
-    puts("RAM FAIL2!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  return 1;
-}
-
-int test_sd()
-{
-  int i = sd_init();
-  if(i==0) {
-    puts("FAILED INIT of Card\n");
-    return 0;
-  }
-  
-  unsigned char buf[512];
-  i = sd_read_block(2048,buf);
-  if(i == 0) {
-    puts("READ Command Rejected\n");
-    return 0;
-  }
-  if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50))
-    ;
-  else {
-    puts("Read bad data from SD Card\n");
-    return 0;
-  }
-  return 1;
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nFactory Test\n");
-
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  if(test_sd())
-    puts("SD OK\n");
-  else {
-    puts("SD FAIL\n");
-    //    hal_finish();
-    //return 0;
-  }
-  if(test_ram())
-    puts("RAM OK\n");
-  else {
-    puts("RAM FAIL\n");
-    hal_finish();
-    return 0;
-  }
-
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  output_regs->led_src = 0x7;  // make bottom 3 controlled by HW
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-  ethernet_init();
-
-  clocks_enable_tx_dboard(true,1);
-  clocks_mimo_config(MC_WE_LOCK_TO_SMA);
-#if 0
-  // make bit 15 of Tx gpio's be a s/w output
-  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-  output_regs->debug_mux_ctrl = 1;
-#if 0
-  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
-  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
-  // initialize double buffering state machine for ethernet -> DSP Tx
-
-  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
-	    &dsp_tx_recv_args, &dsp_tx_send_args,
-	    eth_pkt_inspector);
-
-
-  // initialize double buffering state machine for DSP RX -> Ethernet
-
-  if (FW_SETS_SEQNO){
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      fw_sets_seqno_inspector);
-  }
-  else {
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      dbsm_nop_inspector);
-  }
-
-  // tell app_common that this dbsm could be sending to the ethernet
-  ac_could_be_sending_to_eth = &dsp_rx_sm;
-
-
-  // program tx registers
-  setup_tx();
-
-  // kick off the state machine
-  dbsm_start(&dsp_tx_sm);
-
-  //int which = 0;
-
-  while(1){
-    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
-    // which ^= 0x8000;
-
-    buffer_irq_handler(0);
-
-    int pending = pic_regs->pending;		// poll for under or overrun
-
-    if (pending & PIC_UNDERRUN_INT){
-      dbsm_handle_tx_underrun(&dsp_tx_sm);
-      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
-      putchar('U');
-    }
-
-    if (pending & PIC_OVERRUN_INT){
-      dbsm_handle_rx_overrun(&dsp_rx_sm);
-      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
-
-      // FIXME Figure out how to handle this robustly.
-      // Any buffers that are emptying should be allowed to drain...
-
-      if (streaming_p){
-	// restart_streaming();
-	// FIXME report error
-      }
-      else {
-	// FIXME report error
-      }
-      putchar('O');
-    }
-  }
-}
diff --git a/firmware/microblaze/apps/gen_eth_packets.c b/firmware/microblaze/apps/gen_eth_packets.c
deleted file mode 100644
index 4d521f6bf..000000000
--- a/firmware/microblaze/apps/gen_eth_packets.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "memcpy_wa.h"
-#include "print_rmon_regs.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-// ----------------------------------------------------------------
-
-static eth_mac_addr_t dst_mac_addr =
-  {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
-
-// ----------------------------------------------------------------
-
-// #define	PACKET_SIZE 1500		// bytes
-// #define ETH_DATA_RATE 1000000		// 1MB/s
-// #define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
-
-// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE;	// ticks between interrupts
-
-static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3);		// tick at 1 kHz
-static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6);	// tick at 10 kHz
-
-static volatile bool send_packet_now = false;   // timer handler sets this
-static volatile bool link_is_up = false;	// eth handler sets this
-
-int packet_number = 0;
-
-
-#define CPU_TX_BUF	0	// cpu xmits ethernet frames from here
-#define CPU_RX_BUF	1	// receive ethernet frames here
-
-// ----------------------------------------------------------------
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  link_is_up = speed == 0 ? false : true;
-  hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
-  printf("\neth link changed: speed = %d\n", speed);
-}
-
-void
-timer_irq_handler(unsigned irq)
-{
-  hal_set_timeout(timer_delta);	// schedule next timeout
-  send_packet_now = 1;
-}
-
-
-static void
-init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
-{
-  int i = 0;
-  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
-
-  for (i = 0; i < BP_NLINES; i++){
-    buf[i] = mark | i;
-    mark ^= 0x00FF0000;
-  }
-
-  // copy header into buffer
-  memcpy_wa(buf, pkt, sizeof(*pkt));
-}
-
-static void
-init_packets(void)
-{
-  u2_eth_packet_t	pkt __attribute__((aligned (4)));
-
-  memset(&pkt, 0, sizeof(pkt));
-
-  pkt.ehdr.dst = dst_mac_addr;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  pkt.fixed.word0 = 0x01234567;
-  pkt.fixed.timestamp = 0xffffffff;
-
-  // init just the one we're using
-  init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF);
-}
-
-int
-main(void)
-{
-  int npackets_sent = 0;
-
-  u2_init();
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\ngen_eth_packets\n");
-  
-  hal_set_leds(0x0, 0x3);
-
-  init_packets();
-
-  pic_register_handler(IRQ_TIMER, timer_irq_handler);
-
-  if (hwconfig_simulation_p())
-    timer_delta = sim_timer_delta;
-
-  hal_set_timeout(timer_delta);
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-  ethernet_init();
-
-  /*
-  if (hwconfig_simulation_p()){
-    eth_mac->speed = 4;	// hardcode mac speed to 1000
-    link_is_up = true;
-  }
-  */
-
-  // fire off a receive from the ethernet
-  bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
-
-  while(1){
-    uint32_t status = buffer_pool_status->status;
-
-    if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){
-      bp_clear_buf(CPU_RX_BUF);
-      // ignore incoming ethernet packets; they were looped back in sim
-      bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
-    }
-
-    if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){
-      if (status & BPS_ERROR(CPU_TX_BUF)){
-	putchar('E');
-      }
-      bp_clear_buf(CPU_TX_BUF);
-      npackets_sent++;
-      if ((npackets_sent & 0xF) == 0){	// print after every 16 packets
-	//print_rmon_regs();
-	putchar('.');
-      }
-    }
-
-    if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){
-      send_packet_now = false;
-
-      // kick off the next packet
-      // FIXME set packet number in packet
-
-      bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255);	// 1KB total
-      hal_toggle_leds(0x1);
-    }
-  }
-
-  hal_finish();
-  return 1;
-}
diff --git a/firmware/microblaze/apps/gen_pause_frames.c b/firmware/microblaze/apps/gen_pause_frames.c
deleted file mode 100644
index 0f81dafff..000000000
--- a/firmware/microblaze/apps/gen_pause_frames.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "u2_eth_packet.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-
-
-// ----------------------------------------------------------------
-
-unsigned char dst_mac_addr[6] = {
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-// ----------------------------------------------------------------
-
-// #define	PACKET_SIZE 1500		// bytes
-// #define ETH_DATA_RATE 1000000		// 1MB/s
-// #define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
-
-// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE;	// ticks between interrupts
-
-static int timer_delta = MASTER_CLK_RATE/1000;	// tick at 1kHz
-
-static volatile bool send_packet_now = false;   // timer handler sets this
-static volatile bool link_is_up = false;	// eth handler sets this
-
-int packet_number = 0;
-
-// ----------------------------------------------------------------
-
-// debugging output on tx pins
-#define LS_MASK  0xE0000
-#define LS_1000  0x80000
-#define LS_100   0x40000
-#define LS_10    0x20000
-
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  int v = 0;
-  switch(speed){
-  case 10:
-    v = LS_10;
-    link_is_up = true;
-    break;
-    
-  case 100:
-    v = LS_100;
-    link_is_up = true;
-    break;
-    
-  case 1000:
-    v = LS_100;
-    link_is_up = true;
-    break;
-
-  default:
-    v = 0;
-    link_is_up = false;
-    break;
-  }
-
-  hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
-
-  putstr("\neth link changed: speed = ");
-  puthex16_nl(speed);
-}
-
-void
-timer_irq_handler(unsigned irq)
-{
-  hal_set_timeout(timer_delta);	// schedule next timeout
-  send_packet_now = 1;
-}
-
-
-void
-buffer_irq_handler(unsigned irq)
-{
-  // FIXME
-}
-
-static void
-init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
-{
-  int i = 0;
-  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
-
-  for (i = 0; i < BP_NLINES; i++){
-    buf[i] = mark | i;
-    mark ^= 0x00FF0000;
-  }
-
-  // copy header into buffer
-  memcpy_wa(buf, pkt, sizeof(*pkt));
-}
-
-static void
-init_packets(void)
-{
-  int	i;
-  
-  u2_eth_packet_t	pkt __attribute__((aligned (4)));
-
-  for (i = 0; i < 6; i++){
-    pkt.ehdr.dst.addr[i] = dst_mac_addr[i];
-  }
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-
-  // fill ALL buffers for debugging
-  for (i = 0; i < 8; i++)
-    init_packet((void *)buffer_ram(i), &pkt, i);
-}
-
-static int led_counter = 0;
-
-int
-main(void)
-{
-  int send_pause = 1;
-  
-  u2_init();
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\ngen_eth_packets\n");
-  
-  // Control LEDs
-  output_regs->leds = 0x00;
-
-  init_packets();
-
-  // pic_register_handler(IRQ_BUFFER, buffer_irq_handler);  // poll for now
-  pic_register_handler(IRQ_TIMER, timer_irq_handler);
-  hal_set_timeout(timer_delta);
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-
-  ethernet_init();
-
-  eth_mac->pause_frame_send_en = 1;
-  eth_mac->pause_quanta_set = 16384 / 512;
-
-  // eth_mac->speed = 4;	// FIXME hardcode mac speed to 1000
-
-  while(1){
-    if (link_is_up && send_packet_now){
-      send_packet_now = false;
-
-
-      if (send_pause)
-	eth_mac->xon_cpu = 1;
-      else
-	eth_mac->xon_cpu = 0;
-
-      send_pause ^= 1;
-
-      // kick off the next packet
-      // FIXME set packet number in packet
-
-#if 0
-      bp_send_from_buf(0, PORT_ETH, 1, 0, 255);	// 1KB total
-
-      while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0)
-	;
-      bp_clear_buf(0);
-#endif
-
-      output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0);
-    }
-  }
-
-  hal_finish();
-  return 1;
-}
diff --git a/firmware/microblaze/apps/hello.c b/firmware/microblaze/apps/hello.c
deleted file mode 100644
index bce843093..000000000
--- a/firmware/microblaze/apps/hello.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "u2_init.h"
-#include "stdio.h"
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("Hello World");
-  puts("Goodbye World");
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/ibs_rx_test.c b/firmware/microblaze/apps/ibs_rx_test.c
deleted file mode 100644
index bdc04747e..000000000
--- a/firmware/microblaze/apps/ibs_rx_test.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "nonstdio.h"
-
-#define PORT 2    // ethernet = 2, serdes = 0
-int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
-int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
-
-int buffer_state[4];
-
-static void __attribute__((unused))
-wait_until_status_nonzero(void) 
-{
-  while (buffer_pool_status->status == 0)
-    ;
-}
-
-int
-main(void)
-{
-  int i;
-  
-  u2_init();
-
-  output_regs->adc_ctrl = 0x0A;
-
-  dsp_rx_regs->freq = 0;
-  dsp_rx_regs->scale_iq = (1 << 16) | 1;
-  dsp_rx_regs->decim_rate = 8;
-
-  volatile unsigned int *buffer0 = buffer_ram(0);
-  volatile unsigned int *buffer1 = buffer_ram(1);
-  volatile unsigned int *buffer2 = buffer_ram(2);
-  
-  putstr("Starting RX\n");
-  bp_clear_buf(0);
-  bp_receive_to_buf(0, 1, 1, 0, 99);
-
-  dsp_rx_regs->rx_command = (50 << 9) | 100;   // Numlines, lines per frame
-  dsp_rx_regs->rx_time = 0x2000;
-
-  dsp_rx_regs->rx_command = (137 << 9) | 50;   // Numlines, lines per frame
-  dsp_rx_regs->rx_time = 0x2200;
-
-  while (buffer_pool_status->status == 0)
-    ;
-  bp_clear_buf(0);
-  bp_clear_buf(1);
-  bp_receive_to_buf(1, 1, 1, 0, 99);
-  while (buffer_pool_status->status == 0)
-    ;
-  bp_clear_buf(2);
-  bp_receive_to_buf(2, 1, 1, 0, 99);
-  while (buffer_pool_status->status == 0)
-    ;
-  
-  for(i=0;i<100;i++) {
-    puthex(i);
-    putstr("   ");
-    puthex_nl(buffer0[i]);
-  }
-  for(i=0;i<60;i++) {
-    puthex(i);
-    putstr("   ");
-    puthex_nl(buffer1[i]);
-  }
-  for(i=0;i<60;i++) {
-    puthex(i);
-    putstr("   ");
-    puthex_nl(buffer2[i]);
-  }
-  //while(timer_regs -> time < 0x6000)
-  //  {}
-
-  putstr("Done\n");
-  hal_finish();
-  
-  return 1;
-}
diff --git a/firmware/microblaze/apps/ibs_tx_test.c b/firmware/microblaze/apps/ibs_tx_test.c
deleted file mode 100644
index ff9446d92..000000000
--- a/firmware/microblaze/apps/ibs_tx_test.c
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "nonstdio.h"
-
-// Globals
-#define EMPTY 0
-#define FILLING 1
-#define FULL 2
-#define EMPTYING 3
-
-#define PORT 2    // ethernet = 2, serdes = 0
-int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
-int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
-
-int buffer_state[4];
-
-static void
-wait_until_status_nonzero(void)
-{
-  while (buffer_pool_status->status == 0)
-    ;
-}
-
-int
-main(void)
-{
-  int i;
-  
-  u2_init();
-  
-  dsp_tx_regs->freq = 0;
-  dsp_tx_regs->scale_iq = (1 << 16) | 1;
-  dsp_tx_regs->interp_rate = 8;
-
-  // Write data to be sent into the first buffer
-  volatile unsigned int *buffer0 = buffer_ram(0);
-  volatile unsigned int *buffer1 = buffer_ram(1);
-  
-
-  putstr("Starting to fill in RAM\n");
-  for(i=0;i<512;i++) 
-    buffer0[i] = i;
-  putstr("Filled in RAM\n");
-  
-  buffer0[0] = 7; // start and end of buffer, send immediately
-  buffer0[1] = 0x0000;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-  while(timer_regs -> time < 0x6000)
-    {}
-
-  buffer0[0] = 3; // start and end of buffer
-  buffer0[1] = 0x8000;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-  while(timer_regs -> time < 0x8400)
-    {}
-
-  buffer0[0] = 3; // start and end of buffer
-  buffer0[1] = 0x8800;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-  while(timer_regs -> time < 0x9000)
-    {}
-
-  buffer0[0] = 0x2;  // not last
-  buffer0[1] = 0x9100;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-  buffer0[0] = 0x1;  // last
-  buffer0[1] = 0x0000;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-
-  
-  buffer0[0] = 0x3;  // first and last
-  buffer0[1] = 0x8000;  // Time in the past
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-
-  /*
-  buffer0[0] = 0x2; // not last
-  buffer0[1] = 0x9600;  // start time
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 1, 1, 0, 9);
-  while (buffer_pool_status->status == 0)
-    ;
-  */
-
-  while(timer_regs -> time < 0xa000)
-    {}
-
-  putstr("Done\n");
-
-  while(1)
-    {}
-  hal_finish();
-  
-  // Send a bunch, let them pile up in FIFO
-  bp_send_from_buf(0, 2, 1, 21, 80);    wait_until_status_nonzero();
-  bp_clear_buf(0);
-  putstr("First add'l TX done\n");
-  bp_send_from_buf(0, 2, 1, 81, 288);   wait_until_status_nonzero();
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 2, 1, 289, 292);  wait_until_status_nonzero();
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 2, 1, 293, 326);  wait_until_status_nonzero();
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 2, 1, 327, 399);  wait_until_status_nonzero();
-  bp_clear_buf(0);
-  bp_send_from_buf(0, 2, 1, 400, 511);  wait_until_status_nonzero();
-  bp_clear_buf(0);
-  putstr("All add'l TX done\n");
-  
-  bp_receive_to_buf(1, 2, 1, 21, 80);   wait_until_status_nonzero();
-  bp_clear_buf(1);
-  putstr("First add'l RX done\n");
-  bp_receive_to_buf(1, 2, 1, 81, 288);  wait_until_status_nonzero();
-  bp_clear_buf(1);
-  bp_receive_to_buf(1, 2, 1, 289, 292); wait_until_status_nonzero();
-  bp_clear_buf(1);
-  bp_receive_to_buf(1, 2, 1, 293, 326); wait_until_status_nonzero();
-  bp_clear_buf(1);
-  bp_receive_to_buf(1, 2, 1, 327, 399); wait_until_status_nonzero();
-  bp_clear_buf(1);
-  bp_receive_to_buf(1, 2, 1, 400, 511); wait_until_status_nonzero();
-  bp_clear_buf(1);
-  putstr("All add'l RX done\n");
-
-  for(i=0;i<512;i++)
-    if(buffer0[i] != buffer1[i]) {
-      putstr("ERROR at location: ");
-      puthex_nl(i);
-      putstr("Value sent: ");
-      puthex_nl(buffer0[i]);
-      putstr("Value rcvd: ");
-      puthex_nl(buffer1[i]);
-      //break;
-    }
-  
-  putstr("Done Testing\n");
-  
-  hal_finish();
-  return 1;
-}
diff --git a/firmware/microblaze/apps/mimo_app_common_v2.c b/firmware/microblaze/apps/mimo_app_common_v2.c
deleted file mode 100644
index 5dbecb0d0..000000000
--- a/firmware/microblaze/apps/mimo_app_common_v2.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mimo_app_common_v2.h"
-#include "buffer_pool.h"
-#include "memcpy_wa.h"
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "print_rmon_regs.h"
-#include "db.h"
-#include "db_base.h"
-#include "clocks.h"
-#include "u2_init.h"
-#include <string.h>
-
-volatile bool link_is_up = false;	// eth handler sets this
-int cpu_tx_buf_dest_port = PORT_ETH;
-
-// If this is non-zero, this dbsm could be writing to the ethernet
-dbsm_t *ac_could_be_sending_to_eth;
-
-static unsigned char exp_seqno __attribute__((unused)) = 0;
-
-void abort(void);
-
-static bool
-burn_mac_addr(const op_burn_mac_addr_t *p)
-{
-  return ethernet_set_mac_addr(&p->addr);
-}
-
-static bool
-sync_to_pps(const op_generic_t *p)
-{
-  timesync_regs->sync_on_next_pps = 1;
-  putstr("SYNC to PPS\n");
-  return true;
-}
-
-static bool
-config_mimo_cmd(const op_config_mimo_t *p)
-{
-  clocks_mimo_config(p->flags);
-  return true;
-}
-
-void
-set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
-{
-  reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
-  reply_pkt->ehdr.src = *ethernet_mac_addr();
-  reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
-  reply_pkt->thdr.flags = 0;
-  reply_pkt->thdr.fifo_status = 0;	// written by protocol engine
-  reply_pkt->thdr.seqno = 0;		// written by protocol engine
-  reply_pkt->thdr.ack = 0;		// written by protocol engine
-  u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
-  reply_pkt->fixed.timestamp = timer_regs->time;
-}
-
-static void
-send_reply(unsigned char *reply, size_t reply_len)
-{
-  if (reply_len < 64)
-    reply_len = 64;
-
-  // wait for buffer to become idle
-  hal_set_leds(0x4, 0x4);
-  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
-    ;
-  hal_set_leds(0x0, 0x4);
-
-  // copy reply into CPU_TX_BUF
-  memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
-
-  // wait until nobody else is sending to the ethernet
-  if (ac_could_be_sending_to_eth){
-    hal_set_leds(0x8, 0x8);
-    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
-    hal_set_leds(0x0, 0x8);
-  }
-
-  if (0){
-    printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, (int)reply_len);
-    print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4);
-  }
-
-  // fire it off
-  bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4);
-
-  // wait for it to complete (not long, it's a small pkt)
-  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
-    ;
-
-  bp_clear_buf(CPU_TX_BUF);
-}
-
-
-static size_t
-op_id_cmd(const op_generic_t *p,
-	  void *reply_payload, size_t reply_payload_space)
-{
-  op_id_reply_t *r = (op_id_reply_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))	// no room
-    return 0;
-
-  // Build reply subpacket
-
-  r->opcode = OP_ID_REPLY;
-  r->len = sizeof(op_id_reply_t);
-  r->rid = p->rid;
-  r->addr = *ethernet_mac_addr();
-  r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor;
-  // r->fpga_md5sum = ;	// FIXME
-  // r->sw_md5sum = ;	// FIXME
-
-  return r->len;
-}
-
-
-static size_t
-config_tx_v2_cmd(const op_config_tx_v2_t *p,
-		 void *reply_payload, size_t reply_payload_space)
-{
-  op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))
-    return 0;					// no room
-
-  struct tune_result	tune_result;
-  memset(&tune_result, 0, sizeof(tune_result));
-
-  bool ok = true;
-  
-#if 0
-  if (p->valid & CFGV_GAIN){
-    ok &= db_set_gain(tx_dboard, p->gain);
-  }
-
-  if (p->valid & CFGV_FREQ){
-    bool was_streaming = is_streaming();
-    if (was_streaming)
-      stop_rx_cmd();
-    
-    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
-    bool tune_ok = db_tune(tx_dboard, f, &tune_result);
-    ok &= tune_ok;
-    print_tune_result("Tx", tune_ok, f, &tune_result);
-
-    if (was_streaming)
-      restart_streaming();
-  }
-
-  if (p->valid & CFGV_INTERP_DECIM){
-    int interp = p->interp;
-    int hb1 = 0;
-    int hb2 = 0;
-
-    if (!(interp & 1)){
-      hb2 = 1;
-      interp = interp >> 1;
-    }
-
-    if (!(interp & 1)){
-      hb1 = 1;
-      interp = interp >> 1;
-    }
-    
-    if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP)
-      ok = false;
-    else {
-      dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp;
-      // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp);
-    }
-  }
-
-  if (p->valid & CFGV_SCALE_IQ){
-    dsp_tx_regs->scale_iq = p->scale_iq;
-  }
-#endif
-
-  // Build reply subpacket
-
-  r->opcode = OP_CONFIG_TX_REPLY_V2;
-  r->len = sizeof(*r);
-  r->rid = p->rid;
-  r->ok = ok;
-  r->inverted = tune_result.inverted;
-  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
-  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
-  r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
-  r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
-  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
-  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
-  return r->len;
-}
-
-static size_t
-config_rx_v2_cmd(const op_config_rx_v2_t *p, 
-		 void *reply_payload, size_t reply_payload_space)
-{
-  op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))
-    return 0;				// no room
-
-  struct tune_result	tune_result;
-  memset(&tune_result, 0, sizeof(tune_result));
-
-  bool ok = true;
-  
-  if (p->valid & CFGV_GAIN){
-    ok &= db_set_gain(rx_dboard, p->gain);
-  }
-
-  if (p->valid & CFGV_FREQ){
-    bool was_streaming = is_streaming();
-    if (was_streaming)
-      stop_rx_cmd();
-    
-    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
-    bool tune_ok = db_tune(rx_dboard, f, &tune_result);
-    ok &= tune_ok;
-    print_tune_result("Rx", tune_ok, f, &tune_result);
-
-    if (was_streaming)
-      restart_streaming();
-  }
-
-  if (p->valid & CFGV_INTERP_DECIM){
-    int decim = p->decim;
-    int hb1 = 0;
-    int hb2 = 0;
-    
-    if(!(decim & 1)) {
-      hb2 = 1;
-      decim = decim >> 1;
-    }
-    
-    if(!(decim & 1)) {
-      hb1 = 1;
-      decim = decim >> 1;
-    }
-    
-    if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM)
-      ok = false;
-    else {
-      dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim;
-      // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim);
-    }
-  }
-
-  if (p->valid & CFGV_SCALE_IQ){
-    dsp_rx_regs->scale_iq = p->scale_iq;
-  }
-
-  // Build reply subpacket
-
-  r->opcode = OP_CONFIG_RX_REPLY_V2;
-  r->len = sizeof(*r);
-  r->rid = p->rid;
-  r->ok = ok;
-  r->inverted = tune_result.inverted;
-  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
-  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
-  r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
-  r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
-  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
-  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
-
-  return r->len;
-}
-
-static size_t
-read_time_cmd(const op_generic_t *p,
-	      void *reply_payload, size_t reply_payload_space)
-{
-  op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))		
-    return 0;					// no room
-
-  r->opcode = OP_READ_TIME_REPLY;
-  r->len = sizeof(*r);
-  r->rid = p->rid;
-  r->time = timer_regs->time;
-
-  return r->len;
-}
-
-static void
-fill_db_info(u2_db_info_t *p, const struct db_base *db)
-{
-  p->dbid = db->dbid;
-  p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min);
-  p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min);
-  p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max);
-  p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max);
-  p->gain_min = db->gain_min;
-  p->gain_max = db->gain_max;
-  p->gain_step_size = db->gain_step_size;
-}
-
-static size_t
-dboard_info_cmd(const op_generic_t *p,
-		void *reply_payload, size_t reply_payload_space)
-{
-  op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))		
-    return 0;					// no room
-
-  r->opcode = OP_DBOARD_INFO_REPLY;
-  r->len = sizeof(*r);
-  r->rid = p->rid;
-  r->ok = true;
-
-  fill_db_info(&r->tx_db_info, tx_dboard);
-  fill_db_info(&r->rx_db_info, rx_dboard);
-
-  return r->len;
-}
-
-static size_t
-peek_cmd(const op_peek_t *p,
-	 void *reply_payload, size_t reply_payload_space)
-{
-  op_generic_t *r = (op_generic_t *) reply_payload;
-
-  putstr("peek: addr="); puthex32(p->addr);
-  printf(" bytes=%u\n", p->bytes);
-
-  if ((reply_payload_space < (sizeof(*r) + p->bytes)) ||
-      p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) {
-    putstr("peek: insufficient reply packet space\n");
-    return 0;			// FIXME do partial read?
-  }
-
-  r->opcode = OP_PEEK_REPLY;
-  r->len = sizeof(*r)+p->bytes;
-  r->rid = p->rid;
-  r->ok = true;
-
-  memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes);
-
-  return r->len;
-}
-
-static bool
-poke_cmd(const op_poke_t *p)
-{
-  int bytes = p->len - sizeof(*p);
-  putstr("poke: addr="); puthex32(p->addr);
-  printf(" bytes=%u\n", bytes);
-
-  uint8_t *src = (uint8_t *)p + sizeof(*p);
-  memcpy_wa((void *)p->addr, src, bytes);
-
-  return true;
-}
-
-static size_t
-generic_reply(const op_generic_t *p,
-	      void *reply_payload, size_t reply_payload_space,
-	      bool ok)
-{
-  op_generic_t *r = (op_generic_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))		
-    return 0;					// no room
-
-  r->opcode = p->opcode | OP_REPLY_BIT;
-  r->len = sizeof(*r);
-  r->rid = p->rid;
-  r->ok = ok;
-
-  return r->len;
-}
-
-static size_t
-add_eop(void *reply_payload, size_t reply_payload_space)
-{
-  op_generic_t *r = (op_generic_t *) reply_payload;
-  if (reply_payload_space < sizeof(*r))		
-    return 0;					// no room
-
-  r->opcode = OP_EOP;
-  r->len = sizeof(*r);
-  r->rid = 0;
-  r->ok =  0;
-
-  return r->len;
-}
-
-void
-handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
-{
-  unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
-  unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
-  int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
-
-  // initialize reply
-  memset(reply, 0, sizeof(reply));
-  set_reply_hdr((u2_eth_packet_t *) reply, pkt);
-
-  // point to beginning of payload (subpackets)
-  unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
-  int payload_len = len - sizeof(u2_eth_packet_t);
-
-  size_t subpktlen = 0;
-
-  while (payload_len >= sizeof(op_generic_t)){
-    const op_generic_t *gp = (const op_generic_t *) payload;
-    subpktlen = 0;
-
-    // printf("\nopcode = %d\n", gp->opcode);
-
-    switch(gp->opcode){
-    case OP_EOP:		// end of subpackets
-      goto end_of_subpackets;
-
-    case OP_ID:
-      subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
-      break;
-    
-    case OP_CONFIG_TX_V2:
-      subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload,
-				   reply_payload, reply_payload_space);
-      break;
-
-    case OP_CONFIG_RX_V2:
-      subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload,
-				   reply_payload, reply_payload_space);
-      break;
-
-    case OP_START_RX_STREAMING:
-      start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
-      break;
-    
-    case OP_STOP_RX:
-      stop_rx_cmd();
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
-      break;
-    
-    case OP_BURN_MAC_ADDR:
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
-				burn_mac_addr((op_burn_mac_addr_t *) payload));
-      break;
-
-    case OP_CONFIG_MIMO:
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
-				config_mimo_cmd((op_config_mimo_t *) payload));
-      break;
-
-    case OP_READ_TIME:
-      subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space);
-      break;
-
-    case OP_DBOARD_INFO:
-      subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space);
-      break;
-
-    case OP_SYNC_TO_PPS:
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
-				sync_to_pps((op_generic_t *) payload));
-      break;
-
-    case OP_PEEK:
-      subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space);
-      break;
-
-    case OP_POKE:
-      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
-				poke_cmd((op_poke_t *)payload));
-      break;
-
-    default:
-      printf("app_common_v2: unhandled opcode = %d\n", gp->opcode);
-      break;
-    }
-
-    int t = (gp->len + 3) & ~3;		// bump to a multiple of 4
-    payload += t;
-    payload_len -= t;
-
-    subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
-    reply_payload += subpktlen;
-    reply_payload_space -= subpktlen;
-  }
-
- end_of_subpackets:
-
-  // add the EOP marker
-  subpktlen = add_eop(reply_payload, reply_payload_space);
-  subpktlen = (subpktlen + 3) & ~3;	// bump to a multiple of 4
-  reply_payload += subpktlen;
-  reply_payload_space -= subpktlen;
-
-  send_reply(reply, reply_payload - reply);
-}
-
-
-/*
- * Called when an ethernet packet is received.
- * Return true if we handled it here, otherwise
- * it'll be passed on to the DSP Tx pipe
- */
-int
-eth_pkt_inspector(bsm12_t *sm, int bufno)
-{
-  u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
-  size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
-
-  //static size_t last_len = 0;
-
-  // hal_toggle_leds(0x1);
-
-  // inspect rcvd frame and figure out what do do.
-
-  if (pkt->ehdr.ethertype != U2_ETHERTYPE)
-    return true;	// ignore, probably bogus PAUSE frame from MAC
-
-  int chan = u2p_chan(&pkt->fixed);
-
-  switch (chan){
-  case CONTROL_CHAN:
-    handle_control_chan_frame(pkt, byte_len);
-    return -1;
-    break;
-
-  case 0:
-    return 0;	// pass it off to DSP TX
-
-  case 1:
-    return 1;	// pass it off to SERDES TX
-
-  default:
-    abort();
-    break;
-  }
-}
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  link_is_up = speed != 0;
-  hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45);
-  printf("\neth link changed: speed = %d\n", speed);
-}
-
-
-void
-print_tune_result(char *msg, bool tune_ok,
-		  u2_fxpt_freq_t target_freq, struct tune_result *r)
-{
-#if 0
-  printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
-  putstr("  target_freq   "); print_fxpt_freq(target_freq); newline();
-  putstr("  baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
-  putstr("  dxc_freq      "); print_fxpt_freq(r->dxc_freq); newline();
-  putstr("  residual_freq "); print_fxpt_freq(r->residual_freq); newline();
-  printf("  inverted      %s\n", r->inverted ? "true" : "false");
-#endif
-}
diff --git a/firmware/microblaze/apps/mimo_app_common_v2.h b/firmware/microblaze/apps/mimo_app_common_v2.h
deleted file mode 100644
index 1e62ced37..000000000
--- a/firmware/microblaze/apps/mimo_app_common_v2.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_APP_COMMON_H
-#define INCLUDED_APP_COMMON_H
-
-#include <stdbool.h>
-#include "usrp2_eth_packet.h"
-#include "bsm12.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include <stddef.h>
-#include <db.h>
-
-#define CPU_TX_BUF 	7	// cpu -> eth
-
-#define	_AL4 __attribute__((aligned (4)))
-
-extern volatile bool link_is_up;	// eth handler sets this
-
-// If there's a dbsm that sends to the ethernet, put it's address here
-extern dbsm_t *ac_could_be_sending_to_eth;
-
-extern int cpu_tx_buf_dest_port;
-
-void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
-
-/*
- * Called when an ethernet packet is received.
- */
-int eth_pkt_inspector(bsm12_t *sm, int bufno);
-
-
-void link_changed_callback(int speed);
-
-void
-print_tune_result(char *msg, bool tune_ok,
-		  u2_fxpt_freq_t target_freq, struct tune_result *r);
-
-
-void start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p);
-void stop_rx_cmd(void);
-void restart_streaming(void);
-bool is_streaming(void);
-
-void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
-
-#endif /* INCLUDED_APP_COMMON_H */
diff --git a/firmware/microblaze/apps/mimo_tx.c b/firmware/microblaze/apps/mimo_tx.c
deleted file mode 100644
index e0f8aa6fa..000000000
--- a/firmware/microblaze/apps/mimo_tx.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * This is a down and dirty test program that confirms that the we can
- * coherently transmit different signals to two USRP2s connected via a
- * mimo cable.  This code runs in the USRP2 connected to the ethernet.
- * The other USRP runs mimo_tx_slave.  The host runs test_mimo_tx.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "bsm12.h"
-#include "mimo_app_common_v2.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include "clocks.h"
-
-#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno;	// used when f/w is filling in sequence numbers
-#endif
-
-
-/*
- * Experimental code to transmit packets to DSP Tx and SERDES
- *
- * Hard wire the Tx config so we don't have to deal with control stuff yet.
- */
-
-#define	BUF_BSM12_0	4
-#define	BUF_BSM12_1	5
-#define	BUF_BSM12_2	6
-
-//#define CPU_TX_BUF	7	// cpu -> eth
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
-
-// Receive from ethernet
-buf_cmd_args_t bsm12_recv_args = {
-  PORT_ETH,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t bsm12_send0_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past transport header
-  0			// filled in from last_line register
-};
-
-// send to SERDES
-buf_cmd_args_t bsm12_send1_args = {
-  PORT_SERDES,
-  0,			// starts just past transport header
-  0			// filled in from last_line register
-};
-
-bsm12_t bsm12_sm;	// the state machine
-
-#if 0
-/*
- * ================================================================
- *   configure DSP RX double buffering state machine (dsp -> eth)
- * ================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
-// DSP Rx writes timestamp followed by nlines_per_frame of samples
-#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
-
-// receive from DSP
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_DSP,
-  DSP_RX_FIRST_LINE,
-  BP_LAST_LINE
-};
-
-// send to ETH
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_ETH,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-#endif
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-// variables for streaming mode
-
-static bool         streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static int          streaming_frame_count = 0;
-#define FRAMES_PER_CMD	1000
-
-bool is_streaming(void){ return streaming_p; }
-
-
-// ----------------------------------------------------------------
-
-
-void
-restart_streaming(void)
-{
-#if 0
-  // setup RX DSP regs
-  dsp_rx_regs->clear_state = 1;			// reset
-
-  streaming_p = true;
-  streaming_frame_count = FRAMES_PER_CMD;
-
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);			// set "chain" bit
-
-  // kick off the state machine
-  dbsm_start(&dsp_rx_sm);
-
-  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
-
-  // make sure this one and the rest have the "now" and "chain" bits set.
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);				
-
-  dsp_rx_regs->rx_time = 0;		// enqueue second command
-#endif
-}
-
-void
-start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
-{
-#if 0
-  host_mac_addr = *host;	// remember who we're sending to
-
-  /*
-   * Construct  ethernet header and word0 and preload into two buffers
-   */
-  u2_eth_packet_t	pkt;
-  memset(&pkt, 0, sizeof(pkt));
-  pkt.ehdr.dst = *host;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  u2p_set_word0(&pkt.fixed, 0, 0);
-  // DSP RX will fill in timestamp
-
-  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
-  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
-
-
-  if (FW_SETS_SEQNO)
-    fw_seqno = 0;
-
-  streaming_items_per_frame = p->items_per_frame;
-  restart_streaming();
-#endif
-}
-
-
-void
-stop_rx_cmd(void)
-{
-#if 0
-  streaming_p = false;
-  dsp_rx_regs->clear_state = 1;	// flush cmd queue
-  bp_clear_buf(DSP_RX_BUF_0);
-  bp_clear_buf(DSP_RX_BUF_1);
-#endif
-}
-
-
-static void
-setup_tx()
-{
-  dsp_tx_regs->clear_state = 1;
-
-  int tx_scale = 2500;
-  int interp = 8;		// * 4
-
-  // setup some defaults
-
-  dsp_tx_regs->freq = 429496730;	// 10MHz
-  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
-  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
-}
-
-
-#if 0
-#if (FW_SETS_SEQNO)
-/*
- * Debugging ONLY.  This will be handled by the tx_protocol_engine.
- *
- * This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet.  A bit of a kludge
- * but it should work.
- */
-int
-fw_sets_seqno_inspector(bsm12_t *sm, int buf_this)
-{
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t seqno = fw_seqno++;
-
-  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
-  uint32_t t = p[4];
-  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
-  p[4] = t;
-
-  // queue up another rx command when required
-  if (streaming_p && --streaming_frame_count == 0){
-    streaming_frame_count = FRAMES_PER_CMD;
-    dsp_rx_regs->rx_time = 0;
-  }
-
-  return false;		// we didn't handle the packet
-}
-#endif
-#endif
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  uint32_t  status = buffer_pool_status->status;
-
-  bsm12_process_status(&bsm12_sm, status);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nMIMO Tx\n");
-  print_mac_addr(ethernet_mac_addr()->addr);
-  newline();
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-  ethernet_init();
-
-  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
-
-#if 0
-  // make bit 15 of Tx gpio's be a s/w output
-  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-  output_regs->debug_mux_ctrl = 1;
-#if 0
-  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
-  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
-  // initialize double buffering state machine for ethernet -> DSP Tx
-
-  bsm12_init(&bsm12_sm, BUF_BSM12_0,
-	     &bsm12_recv_args, &bsm12_send0_args, &bsm12_send1_args,
-	     eth_pkt_inspector);
-
-
-#if 0
-  // initialize double buffering state machine for DSP RX -> Ethernet
-
-  if (FW_SETS_SEQNO){
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      fw_sets_seqno_inspector);
-  }
-  else {
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      dbsm_nop_inspector);
-  }
-
-  // tell app_common that this dbsm could be sending to the ethernet
-  ac_could_be_sending_to_eth = &dsp_rx_sm;
-#endif
-
-
-  // program tx registers
-  setup_tx();
-
-  // kick off the state machine
-  bsm12_start(&bsm12_sm);
-
-  //int which = 0;
-
-  while(1){
-    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
-    // which ^= 0x8000;
-
-    buffer_irq_handler(0);
-
-    int pending = pic_regs->pending;		// poll for under or overrun
-
-    if (pending & PIC_UNDERRUN_INT){
-      // dbsm_handle_tx_underrun(&dsp_tx_sm);
-      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
-      putchar('U');
-    }
-
-    if (pending & PIC_OVERRUN_INT){
-      // dbsm_handle_rx_overrun(&dsp_rx_sm);
-      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
-
-      // FIXME Figure out how to handle this robustly.
-      // Any buffers that are emptying should be allowed to drain...
-
-      if (streaming_p){
-	// restart_streaming();
-	// FIXME report error
-      }
-      else {
-	// FIXME report error
-      }
-      putchar('O');
-    }
-  }
-}
diff --git a/firmware/microblaze/apps/mimo_tx_slave.c b/firmware/microblaze/apps/mimo_tx_slave.c
deleted file mode 100644
index cdf9c03c2..000000000
--- a/firmware/microblaze/apps/mimo_tx_slave.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * This is a down and dirty test program that confirms that the we can
- * coherently transmit different signals to two USRP2s connected via a
- * mimo cable.  This code runs in the USRP2 NOT connected to the
- * ethernet.  The USRP connected to the ethernet runs mimo_tx.  The
- * host runs test_mimo_tx.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include "clocks.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno;	// used when f/w is filling in sequence numbers
-#endif
-
-
-/*
- * Full duplex Tx and Rx between serdes and DSP pipelines
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow
- * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-
-#define	DSP_RX_BUF_0	2	// dsp rx -> serdes (double buffer)
-#define	DSP_RX_BUF_1	3	// dsp rx -> serdes
-#define	DSP_TX_BUF_0	4	// serdes -> dsp tx (double buffer)
-#define	DSP_TX_BUF_1	5	// serdes -> dsp tx
-
-/*
- * ==================================================================
- *   configure DSP TX double buffering state machine (serdes -> dsp)
- * ==================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
-
-// Receive from serdes
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_SERDES,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past transport header
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-/*
- * =================================================================
- *   configure DSP RX double buffering state machine (dsp -> serdes)
- * =================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
-// DSP Rx writes timestamp followed by nlines_per_frame of samples
-#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
-
-// receive from DSP
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_DSP,
-  DSP_RX_FIRST_LINE,
-  BP_LAST_LINE
-};
-
-// send to serdes
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_SERDES,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-// variables for streaming mode
-
-static bool         streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static int          streaming_frame_count = 0;
-#define FRAMES_PER_CMD	1000
-
-bool is_streaming(void){ return streaming_p; }
-
-// ----------------------------------------------------------------
-
-
-void
-restart_streaming(void)
-{
-  // setup RX DSP regs
-  dsp_rx_regs->clear_state = 1;			// reset
-
-  streaming_p = true;
-  streaming_frame_count = FRAMES_PER_CMD;
-
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);			// set "chain" bit
-
-  // kick off the state machine
-  dbsm_start(&dsp_rx_sm);
-
-  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
-
-  // make sure this one and the rest have the "now" and "chain" bits set.
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);				
-
-  dsp_rx_regs->rx_time = 0;		// enqueue second command
-}
-
-void
-start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
-{
-  host_mac_addr = *host;	// remember who we're sending to
-
-  /*
-   * Construct  ethernet header and word0 and preload into two buffers
-   */
-  u2_eth_packet_t	pkt;
-  memset(&pkt, 0, sizeof(pkt));
-  pkt.ehdr.dst = *host;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  u2p_set_word0(&pkt.fixed, 0, 0);
-  // DSP RX will fill in timestamp
-
-  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
-  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
-
-
-  if (FW_SETS_SEQNO)
-    fw_seqno = 0;
-
-  streaming_items_per_frame = p->items_per_frame;
-  restart_streaming();
-}
-
-
-void
-stop_rx_cmd(void)
-{
-  streaming_p = false;
-  dsp_rx_regs->clear_state = 1;	// flush cmd queue
-  bp_clear_buf(DSP_RX_BUF_0);
-  bp_clear_buf(DSP_RX_BUF_1);
-}
-
-
-static void
-setup_tx()
-{
-  dsp_tx_regs->clear_state = 1;
-  bp_clear_buf(DSP_TX_BUF_0);
-  bp_clear_buf(DSP_TX_BUF_1);
-
-  int tx_scale = 2500;
-  int interp = 8;		// * 4
-
-  // setup some defaults
-
-  dsp_tx_regs->freq = 429496730;	// 10MHz
-  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
-  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
-}
-
-
-#if (FW_SETS_SEQNO)
-/*
- * Debugging ONLY.  This will be handled by the tx_protocol_engine.
- *
- * This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet.  A bit of a kludge
- * but it should work.
- */
-bool 
-fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
-{
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t seqno = fw_seqno++;
-
-  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
-  uint32_t t = p[4];
-  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
-  p[4] = t;
-
-  // queue up another rx command when required
-  if (streaming_p && --streaming_frame_count == 0){
-    streaming_frame_count = FRAMES_PER_CMD;
-    dsp_rx_regs->rx_time = 0;
-  }
-
-  return false;		// we didn't handle the packet
-}
-#endif
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  // hal_toggle_leds(LED_A);
-
-  uint32_t  status = buffer_pool_status->status;
-
-  if (0 && (status & ~BPS_IDLE_ALL)){
-    putstr("status = ");
-    puthex32_nl(status);
-  }
-
-  dbsm_process_status(&dsp_tx_sm, status);
-  dbsm_process_status(&dsp_rx_sm, status);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  output_regs->led_src = 0x3;		// h/w controls bottom two bits
-  clocks_enable_test_clk(true, 1);
-
-  putstr("\nMIMO Tx Slave\n");
-
-  cpu_tx_buf_dest_port = PORT_SERDES;
-
-  // ethernet_register_link_changed_callback(link_changed_callback);
-  // ethernet_init();
-
-  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
-
-  // puts("post clocks_mimo_config");
-
-#if 0
-  // make bit 15 of Tx gpio's be a s/w output
-  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-#if 0
-  output_regs->debug_mux_ctrl = 1;
-  hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
-  hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
-  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
-  // initialize double buffering state machine for ethernet -> DSP Tx
-
-  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
-	    &dsp_tx_recv_args, &dsp_tx_send_args,
-	    eth_pkt_inspector);
-
-
-  //output_regs->flush_icache = 1;
- 
-  // initialize double buffering state machine for DSP RX -> Ethernet
-
-  if (FW_SETS_SEQNO){
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      fw_sets_seqno_inspector);
-  }
-  else {
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      dbsm_nop_inspector);
-  }
-
-  // puts("post dbsm_init's");
-
-  // tell app_common that this dbsm could be sending to the ethernet
-  ac_could_be_sending_to_eth = &dsp_rx_sm;
-
-
-  // program tx registers
-  setup_tx();
-
-  // puts("post setup_tx");
-
-  // kick off the state machine
-  dbsm_start(&dsp_tx_sm);
-
-  // puts("post dbsm_start");
-
-  //int which = 0;
-
-  while(1){
-    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
-    // which ^= 0x8000;
-
-    buffer_irq_handler(0);
-
-    int pending = pic_regs->pending;		// poll for under or overrun
-
-    if (pending & PIC_UNDERRUN_INT){
-      dbsm_handle_tx_underrun(&dsp_tx_sm);
-      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
-      putchar('U');
-    }
-
-    if (pending & PIC_OVERRUN_INT){
-      dbsm_handle_rx_overrun(&dsp_rx_sm);
-      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
-
-      // FIXME Figure out how to handle this robustly.
-      // Any buffers that are emptying should be allowed to drain...
-
-      if (streaming_p){
-	// restart_streaming();
-	// FIXME report error
-      }
-      else {
-	// FIXME report error
-      }
-      putchar('O');
-    }
-  }
-}
diff --git a/firmware/microblaze/apps/rcv_eth_packets.c b/firmware/microblaze/apps/rcv_eth_packets.c
deleted file mode 100644
index 03fc94354..000000000
--- a/firmware/microblaze/apps/rcv_eth_packets.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "memcpy_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-
-
-// ----------------------------------------------------------------
-
-static eth_mac_addr_t dst_mac_addr =
-  {{  0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
-
-
-// ----------------------------------------------------------------
-
-#define	PACKET_SIZE 1500		// bytes
-#define ETH_DATA_RATE 1000000		// 1MB/s
-#define	ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE)	// 13,3333 pkts/s
-
-#define TIMER_RATE 100000000		// 100 MHz clock
-
-static int timer_delta = TIMER_RATE/ETH_PACKET_RATE;	// ticks between interrupts
-
-static volatile bool send_packet_now = false;   // timer handler sets this
-static volatile bool link_is_up = false;	// eth handler sets this
-
-int packet_number = 0;
-
-// ----------------------------------------------------------------
-
-// debugging output on tx pins
-#define LS_MASK  0xE0000
-#define LS_1000  0x80000
-#define LS_100   0x40000
-#define LS_10    0x20000
-
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  int v = 0;
-  switch(speed){
-  case 10:
-    v = LS_10;
-    link_is_up = true;
-    break;
-    
-  case 100:
-    v = LS_100;
-    link_is_up = true;
-    break;
-    
-  case 1000:
-    v = LS_100;
-    link_is_up = true;
-    break;
-
-  default:
-    v = 0;
-    link_is_up = false;
-    break;
-  }
-
-  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
-
-  putstr("\neth link changed: speed = ");
-  puthex16_nl(speed);
-}
-
-void
-timer_irq_handler(unsigned irq)
-{
-  hal_set_timeout(timer_delta);	// schedule next timeout
-  send_packet_now = 1;
-}
-
-
-void
-buffer_irq_handler(unsigned irq)
-{
-  // FIXME
-}
-
-static void
-init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum)
-{
-  int i = 0;
-  int mark = ((bufnum & 0xff) << 24) | 0x005A0000;
-
-  for (i = 0; i < BP_NLINES; i++){
-    buf[i] = mark | i;
-    mark ^= 0x00FF0000;
-  }
-
-  // copy header into buffer
-  memcpy_wa(buf, pkt, sizeof(*pkt));
-}
-
-static void
-init_packets(void)
-{
-  int	i;
-  
-  u2_eth_packet_t	pkt __attribute__((aligned (4)));
-
-  pkt.ehdr.dst = dst_mac_addr;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-
-  // fill ALL buffers for debugging
-  for (i = 0; i < 8; i++)
-    init_packet((void *)buffer_ram(i), &pkt, i);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  int	prev_leds = -1;
-  int	new_leds  = 0x00;
-  output_regs->leds = 0x00;
-
-  int peak_hold_count = 0;
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\nrcv_eth_packets\n");
-  
-  init_packets();
-
-  // pic_register_handler(IRQ_BUFFER, buffer_irq_handler);  // poll for now
-
-  // FIXME turn off timer since I don't think MTS and MFS instructions are implemented
-  // pic_register_handler(IRQ_TIMER, timer_irq_handler);
-  // hal_set_timeout(timer_delta);
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-
-  ethernet_init();
-
-  //eth_mac->speed = 4;	// FIXME hardcode mac speed to 1000
-
-  // kick off a receive
-  bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
-
-  while(1){
-    // u2_eth_packet_t	pkt;
-
-    new_leds = 0;
-    if (link_is_up)
-      new_leds = 0x2;
-
-    if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){
-      // we've got a packet!
-
-#if 0
-      // copy to stack buffer so we can byte address it
-      memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt));
-      
-      putstr("Rx: src: ");
-      print_mac_addr(pkt.ehdr.dst_addr);
-      putstr(" dst: ");
-      print_mac_addr(pkt.ehdr.src_addr);
-      putstr(" ethtype: ");
-      puthex16(pkt.ehdr.ethertype);
-      putstr(" len: ");
-      int len = (buffer_pool_status->last_line[2] + 1) * 4;
-      puthex16_nl(len);
-#else
-      volatile int *bp = buffer_ram(2);
-      int	i;
-      for (i = 0; i < 16; i++){
-	puthex8(i);
-	putchar(':');
-	puthex32_nl(bp[i]);
-      }
-#endif
-      
-      // kick off next receive
-      bp_clear_buf(2);
-      bp_receive_to_buf(2, PORT_ETH, 1, 0, 511);
-
-      peak_hold_count = 2048 * 10;
-    }
-
-    if (peak_hold_count > 0){
-      peak_hold_count--;
-      new_leds |= 0x1;
-    }
-
-    if (new_leds != prev_leds){
-      prev_leds = new_leds;
-      output_regs->leds = new_leds;
-    }
-  }
-
-  hal_finish();
-  return 1;
-}
diff --git a/firmware/microblaze/apps/read_dbids.c b/firmware/microblaze/apps/read_dbids.c
deleted file mode 100644
index 24c6d9ab4..000000000
--- a/firmware/microblaze/apps/read_dbids.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <nonstdio.h>
-#include <u2_init.h>
-#include <stdbool.h>
-#include <usrp2_i2c_addr.h>
-#include <i2c.h>
-
-
-int main(void)
-{
-  u2_init();
-
-  puts("\nread_dbids");
-
-  unsigned char dbid_tx[2];
-  unsigned char dbid_rx[2];
-  bool ok;
-
-  ok = eeprom_read(I2C_ADDR_TX_A, 1, dbid_tx, 2);
-  if (!ok){
-    puts("failed to read Tx Daugherboard EEPROM");
-  }
-  else {
-    putstr("Tx Daugherboard ID: ");
-    puthex8(dbid_tx[1]);    // MSB
-    puthex8(dbid_tx[0]);    // LSB
-    newline();
-  }
-
-  ok = eeprom_read(I2C_ADDR_RX_A, 1, dbid_rx, 2);
-  if (!ok){
-    puts("failed to read Rx Daugherboard EEPROM");
-  }
-  else {
-    putstr("Rx Daugherboard ID: ");
-    puthex8(dbid_rx[1]);    // MSB
-    puthex8(dbid_rx[0]);    // LSB
-    newline();
-  }
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/sd_bounce.c b/firmware/microblaze/apps/sd_bounce.c
deleted file mode 100644
index c1b48f170..000000000
--- a/firmware/microblaze/apps/sd_bounce.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* 
- * Loopback SERDES to SERDES
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "nonstdio.h"
-#include "memset_wa.h"
-#include <dbsm.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <clocks.h>
-
-
-
-// ----------------------------------------------------------------
-
-#define SERDES_RX_BUF_0		0
-#define	SERDES_RX_BUF_1		1
-
-/*
- * ================================================================
- *      configure SD RX double buffering state machine
- * ================================================================
- */
-
-// receive from SERDES
-buf_cmd_args_t sd_recv_args = {
-  PORT_SERDES,
-  0,
-  BP_LAST_LINE
-};
-
-// send to SERDES
-buf_cmd_args_t sd_send_args = {
-  PORT_SERDES,
-  0,		// starts with packet in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t sd_sm;	// the state machine
-
-
-
-
-// ----------------------------------------------------------------
-
-#if 0
-static bool
-check_packet(int *buf, int nlines)
-{
-  bool ok = true;
-  int i = 0;
-  for (i = 0; i < nlines; i++){
-    int expected = ((2*i + 0) << 16) | (2*i+1);
-    if (buf[i] != expected){
-      ok = false;
-      printf("buf[%d] = 0x%x  expected = 0x%x\n", i, buf[i], expected);
-    }
-  }
-  return ok;
-}
-
-static void
-zero_buffer(int bufno)
-{
-  memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
-}
-#endif
-
-
-bool
-sd_rx_inspector(dbsm_t *sm, int buf_this)
-{
-  hal_toggle_leds(0x2);
-
-#if 0
-  int last_line = buffer_pool_status->last_line[buf_this];
-  bool ok = check_packet(buffer_ram(buf_this), last_line);
-  static int good = 0;
-  static int bad = 0;
-
-  if (ok)
-    good++;
-  else
-    bad++;
-
-  if(good+bad == 10000) {
-    printf("Good %d\tBad %d\n",good,bad);
-    good = 0;
-    bad = 0;
-  }
-#endif
-
-  return false;
-}
-
-
-inline static void
-buffer_irq_handler(void)
-{
-  uint32_t  status = buffer_pool_status->status;
-  dbsm_process_status(&sd_sm, status);
-}
-
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nsd_bounce\n");
-
-  // Get our clock from the mimo interface
-  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
-
-  dbsm_init(&sd_sm, SERDES_RX_BUF_0,
-	    &sd_recv_args, &sd_send_args,
-	    sd_rx_inspector);
-
-  // kick off the state machine
-  dbsm_start(&sd_sm);
-
-  while(1){
-    buffer_irq_handler();
-  }
-}
diff --git a/firmware/microblaze/apps/sd_gentest.c b/firmware/microblaze/apps/sd_gentest.c
deleted file mode 100644
index 35e912615..000000000
--- a/firmware/microblaze/apps/sd_gentest.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "nonstdio.h"
-#include "memset_wa.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <clocks.h>
-#include <mdelay.h>
-
-// ----------------------------------------------------------------
-
-int packet_number = 0;
-volatile bool send_packet_now = 0;
-
-#define SERDES_TX_BUF	0
-#define	SERDES_RX_BUF 	1
-
-
-#define NLINES_PER_PKT	380
-
-
-// ----------------------------------------------------------------
-
-//static int timer_delta = (int)(MASTER_CLK_RATE * 100e-6);
-static int timer_delta = 1000000; // .01 second
-
-void
-timer_irq_handler(unsigned irq)
-{
-  hal_set_timeout(timer_delta);	// schedule next timeout
-  send_packet_now = true;
-}
-
-
-static void
-init_packet(int *buf)
-{
-  int i = 0;
-  for (i = 0; i < BP_NLINES; i++){
-    buf[i] = ((2*i + 0) << 16) | (2*i+1);
-  }
-}
-
-static bool
-check_packet(int *buf, int nlines)
-{
-  bool ok = true;
-  int i = 0;
-  for (i = 0; i < nlines; i++){
-    int expected = ((2*i + 0) << 16) | (2*i+1);
-    if (buf[i] != expected){
-      ok = false;
-      printf("buf[%d] = 0x%x  expected = 0x%x\n", i, buf[i], expected);
-    }
-  }
-  return ok;
-}
-
-static void
-zero_buffer(int bufno)
-{
-  memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4);
-}
-
-static void
-init_packets(void)
-{
-  // init just the one we're using
-  init_packet(buffer_ram(SERDES_TX_BUF));
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  // We're free running and provide clock to the MIMO interface
-  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
-
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  // output_regs->debug_mux_ctrl = 1;
-  // hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  // hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\nsd_gentest\n");
-  
-  // Set up serdes (already enabled)
-  //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN | SERDES_LOOPEN);
-  //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN);
-
-  init_packets();
-
-  // pic_register_handler(IRQ_TIMER, timer_irq_handler);
-
-  //if (hwconfig_simulation_p())
-  //  timer_delta = sim_timer_delta;
-
-  // start a receive from sd
-  zero_buffer(SERDES_RX_BUF);
-  bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
-
-  // fire off the first packet
-  bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
-  hal_set_timeout(timer_delta);
-  int ready_to_send = 0;
-
-  int counter __attribute__((unused)) = 0;
-  int sent = 1;
-  int txerr = 0;
-  int rxerr = 0;
-  int rcvd = 0;
-  int rxcrc = 0;
-  int sent_acc = 0;
-  int txerr_acc = 0;
-  int rxerr_acc = 0;
-  int rcvd_acc = 0;
-  int rxcrc_acc = 0;
-
-#define EXPECTING_PKT() ((counter & 0x1) == 0)
-#define	SEND_PKT()      ((counter & 0x1) != 0)
-
-  bool got_packet = false;
-
-  while(1){
-    uint32_t status = buffer_pool_status->status;
-
-    if (status & (BPS_DONE(SERDES_RX_BUF))){
-      bp_clear_buf(SERDES_RX_BUF);
-      got_packet = true;
-
-      //hal_toggle_leds(0x2);
-
-      // check packet
-      int last_line = buffer_pool_status->last_line[SERDES_RX_BUF]-1;
-      bool ok = check_packet(buffer_ram(SERDES_RX_BUF), last_line);
-      
-      if (ok) {
-	rcvd++;
-	//putchar('r');
-      }
-      else {
-	rcvd++;
-	rxcrc++;
-	//putchar('P');
-      }
-      // start a receive from sd
-      zero_buffer(SERDES_RX_BUF);
-      bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
-    }
-
-    if (status & (BPS_ERROR(SERDES_RX_BUF))){
-      bp_clear_buf(SERDES_RX_BUF);
-      got_packet = true;
-      rcvd++;
-      rxerr++;
-      //putchar('E');
-
-      // start a receive from sd
-      zero_buffer(SERDES_RX_BUF);
-      bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE);
-    }
-
-    if (status & (BPS_DONE(SERDES_TX_BUF))){
-      bp_clear_buf(SERDES_TX_BUF);
-      //putchar('t');
-      bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
-      //mdelay(1);
-      int	i;
-      for (i = 0; i < 50; i++){
-	asm volatile ("or  r0, r0, r0\n\
-		   or  r0, r0, r0\n    \
-		   or  r0, r0, r0\n    \
-		   or  r0, r0, r0\n    \
-		   or  r0, r0, r0\n    \
-		   or  r0, r0, r0\n    \
-		   or  r0, r0, r0\n");
-      }
-      sent ++;
-      ready_to_send = 1;
-      //hal_toggle_leds(0x1);
-    }
-
-    if (status & BPS_ERROR(SERDES_TX_BUF)){
-      bp_clear_buf(SERDES_TX_BUF);
-      sent++;
-      txerr++;
-      ready_to_send = 1;
-      //putchar('X');
-    }
-
-    if(sent >=1000) {
-      printf("Status\tSENT %d\tTXERR %d\t",sent,txerr);
-      printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n",rcvd, rxerr, rxcrc, sent-rcvd);
-      sent_acc += sent; sent = 0;
-      txerr_acc += txerr; txerr = 0;
-      rcvd_acc += rcvd; rcvd = 0;
-      rxerr_acc += rxerr; rxerr = 0;
-      rxcrc_acc += rxcrc; rxcrc = 0;
-    }
-
-    if(sent_acc >=10000) {
-      printf("\nOverall\tSENT %d\tTXERR %d\t",sent_acc,txerr_acc);
-      printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n\n",rcvd_acc, rxerr_acc, rxcrc_acc, sent_acc-rcvd_acc);
-      sent_acc = 0;
-      txerr_acc = 0;
-      rcvd_acc = 0;
-      rxerr_acc = 0;
-      rxcrc_acc = 0;
-    }
-#if 0
-    int pending = pic_regs->pending;
-    if (pending & PIC_TIMER_INT){
-      hal_set_timeout(timer_delta);
-      
-      /*
-	if (EXPECTING_PKT()){
-	if (!got_packet)
-	  putchar('T');
-	got_packet = false;
-      }
-
-      if (SEND_PKT()){
-	if (status & BPS_IDLE(SERDES_TX_BUF))
-	  bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
-      }
-      counter++;
-      */
-
-      putchar('T');
-      if(ready_to_send) {
-	bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT);
-	counter++;
-	ready_to_send = 0;
-      }
-      
-      pic_regs->pending = PIC_TIMER_INT;	// clear pending interrupt
-    }
-#endif
-  }
-  
-  return 0;
-}
diff --git a/firmware/microblaze/apps/serdes_to_dsp.c b/firmware/microblaze/apps/serdes_to_dsp.c
deleted file mode 100644
index 4994e0a69..000000000
--- a/firmware/microblaze/apps/serdes_to_dsp.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/*
- * This program can respond to queries from the host
- * and stream rx samples.
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
- * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-//#define CPU_TX_BUF 	1	// cpu -> eth
-
-#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
-#define	DSP_RX_BUF_1	3	// dsp rx -> eth
-#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
-#define	DSP_TX_BUF_1	5	// eth -> dsp tx
-
-/*
- * ================================================================
- *      configure DSP TX double buffering state machine
- * ================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
-
-// Receive from ethernet
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_SERDES,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past transport header
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-
-// ----------------------------------------------------------------
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-void
-start_rx_cmd(const eth_mac_addr_t *host, op_start_rx_t *p)
-{
-}
-
-void
-stop_rx_cmd(void)
-{
-}
-
-static void
-setup_tx()
-{
-  dsp_tx_regs->clear_state = 1;
-  bp_clear_buf(DSP_TX_BUF_0);
-  bp_clear_buf(DSP_TX_BUF_1);
-
-  int tx_scale = 256;
-  int interp = 32;
-
-  op_config_tx_t def_config;
-  memset(&def_config, 0, sizeof(def_config));
-  def_config.phase_inc  = 408021893;			// 9.5 MHz [2**32 * fc/fsample]
-  def_config.scale_iq = (tx_scale << 16) | tx_scale;
-  def_config.interp = interp;
-
-  // setup Tx DSP regs
-  config_tx_cmd(&def_config);
-}
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  //hal_toggle_leds(0x2);
-
-  uint32_t  status = buffer_pool_status->status;
-
-  dbsm_process_status(&dsp_tx_sm, status);
-
-  if (status & BPS_DONE(CPU_TX_BUF)){
-    bp_clear_buf(CPU_TX_BUF);
-  }
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  // Get our clock from the mimo interface
-
-  clocks_enable_test_clk(true,1);
-  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
-  
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\nserdes_to_dsp\n");
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-  ethernet_init();
-
-
-  // initialize double buffering state machine for ethernet -> DSP Tx
-
-  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
-	    &dsp_tx_recv_args, &dsp_tx_send_args,
-	    eth_pkt_inspector);
-
-  // program tx registers
-  setup_tx();
-
-  // kick off the state machine
-  dbsm_start(&dsp_tx_sm);
-
-  while(1){
-    buffer_irq_handler(0);
-
-    int pending = pic_regs->pending;	// poll for under or overrun
-
-    if (pending & PIC_UNDERRUN_INT){
-      dbsm_handle_tx_underrun(&dsp_tx_sm);
-      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
-      putchar('U');
-    }
-  }
-}
-
diff --git a/firmware/microblaze/apps/serdes_txrx.c b/firmware/microblaze/apps/serdes_txrx.c
deleted file mode 100644
index 2c47c9628..000000000
--- a/firmware/microblaze/apps/serdes_txrx.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "dbsm.h"
-#include "app_common_v2.h"
-#include "memcpy_wa.h"
-#include "clocks.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#define FW_SETS_SEQNO	1	// define to 0 or 1 (FIXME must be 1 for now)
-
-#if (FW_SETS_SEQNO)
-static int fw_seqno;	// used when f/w is filling in sequence numbers
-#endif
-
-
-/*
- * Full duplex Tx and Rx between serdes and DSP pipelines
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow
- * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-
-#define	DSP_RX_BUF_0	2	// dsp rx -> serdes (double buffer)
-#define	DSP_RX_BUF_1	3	// dsp rx -> serdes
-#define	DSP_TX_BUF_0	4	// serdes -> dsp tx (double buffer)
-#define	DSP_TX_BUF_1	5	// serdes -> dsp tx
-
-/*
- * ==================================================================
- *   configure DSP TX double buffering state machine (serdes -> dsp)
- * ==================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
-
-// Receive from serdes
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_SERDES,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past transport header
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-/*
- * =================================================================
- *   configure DSP RX double buffering state machine (dsp -> serdes)
- * =================================================================
- */
-
-// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
-// DSP Rx writes timestamp followed by nlines_per_frame of samples
-#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
-
-// receive from DSP
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_DSP,
-  DSP_RX_FIRST_LINE,
-  BP_LAST_LINE
-};
-
-// send to serdes
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_SERDES,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from list_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-// variables for streaming mode
-
-static bool         streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static int          streaming_frame_count = 0;
-#define FRAMES_PER_CMD	1000
-
-bool is_streaming(void){ return streaming_p; }
-
-// ----------------------------------------------------------------
-
-
-void
-restart_streaming(void)
-{
-  // setup RX DSP regs
-  dsp_rx_regs->clear_state = 1;			// reset
-
-  streaming_p = true;
-  streaming_frame_count = FRAMES_PER_CMD;
-
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);			// set "chain" bit
-
-  // kick off the state machine
-  dbsm_start(&dsp_rx_sm);
-
-  dsp_rx_regs->rx_time = 0;		// enqueue first of two commands
-
-  // make sure this one and the rest have the "now" and "chain" bits set.
-  dsp_rx_regs->rx_command =
-    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
-	      streaming_items_per_frame,
-	      1, 1);				
-
-  dsp_rx_regs->rx_time = 0;		// enqueue second command
-}
-
-void
-start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p)
-{
-  host_mac_addr = *host;	// remember who we're sending to
-
-  /*
-   * Construct  ethernet header and word0 and preload into two buffers
-   */
-  u2_eth_packet_t	pkt;
-  memset(&pkt, 0, sizeof(pkt));
-  pkt.ehdr.dst = *host;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  u2p_set_word0(&pkt.fixed, 0, 0);
-  // DSP RX will fill in timestamp
-
-  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
-  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
-
-
-  if (FW_SETS_SEQNO)
-    fw_seqno = 0;
-
-  streaming_items_per_frame = p->items_per_frame;
-  restart_streaming();
-}
-
-
-void
-stop_rx_cmd(void)
-{
-  streaming_p = false;
-  dsp_rx_regs->clear_state = 1;	// flush cmd queue
-  bp_clear_buf(DSP_RX_BUF_0);
-  bp_clear_buf(DSP_RX_BUF_1);
-}
-
-
-static void
-setup_tx()
-{
-  dsp_tx_regs->clear_state = 1;
-  bp_clear_buf(DSP_TX_BUF_0);
-  bp_clear_buf(DSP_TX_BUF_1);
-
-  int tx_scale = 256;
-  int interp = 32;
-
-  // setup some defaults
-
-  dsp_tx_regs->freq = 0;
-  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
-  dsp_tx_regs->interp_rate = interp;
-}
-
-
-#if (FW_SETS_SEQNO)
-/*
- * Debugging ONLY.  This will be handled by the tx_protocol_engine.
- *
- * This is called when the DSP Rx chain has filled in a packet.
- * We set and increment the seqno, then return false, indicating
- * that we didn't handle the packet.  A bit of a kludge
- * but it should work.
- */
-bool 
-fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false
-{
-  uint32_t *p = buffer_ram(buf_this);
-  uint32_t seqno = fw_seqno++;
-
-  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
-  uint32_t t = p[4];
-  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
-  p[4] = t;
-
-  // queue up another rx command when required
-  if (streaming_p && --streaming_frame_count == 0){
-    streaming_frame_count = FRAMES_PER_CMD;
-    dsp_rx_regs->rx_time = 0;
-  }
-
-  return false;		// we didn't handle the packet
-}
-#endif
-
-
-inline static void
-buffer_irq_handler(unsigned irq)
-{
-  // hal_toggle_leds(LED_A);
-
-  uint32_t  status = buffer_pool_status->status;
-
-  if (0 && (status & ~BPS_IDLE_ALL)){
-    putstr("status = ");
-    puthex32_nl(status);
-  }
-
-  dbsm_process_status(&dsp_tx_sm, status);
-  dbsm_process_status(&dsp_rx_sm, status);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  output_regs->led_src = 0x3;		// h/w controls bottom two bits
-  clocks_enable_test_clk(true, 1);
-
-  putstr("\nSERDES TxRx\n");
-
-  cpu_tx_buf_dest_port = PORT_SERDES;
-
-  // ethernet_register_link_changed_callback(link_changed_callback);
-  // ethernet_init();
-
-  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
-
-  // puts("post clocks_mimo_config");
-
-#if 0
-  // make bit 15 of Tx gpio's be a s/w output
-  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-#if 0
-  output_regs->debug_mux_ctrl = 1;
-  hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
-  hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
-  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
-  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
-  // initialize double buffering state machine for ethernet -> DSP Tx
-
-  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
-	    &dsp_tx_recv_args, &dsp_tx_send_args,
-	    eth_pkt_inspector);
-
-
-  //output_regs->flush_icache = 1;
- 
-  // initialize double buffering state machine for DSP RX -> Ethernet
-
-  if (FW_SETS_SEQNO){
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      fw_sets_seqno_inspector);
-  }
-  else {
-    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	      &dsp_rx_recv_args, &dsp_rx_send_args,
-	      dbsm_nop_inspector);
-  }
-
-  // puts("post dbsm_init's");
-
-  // tell app_common that this dbsm could be sending to the ethernet
-  ac_could_be_sending_to_eth = &dsp_rx_sm;
-
-
-  // program tx registers
-  setup_tx();
-
-  // puts("post setup_tx");
-
-  // kick off the state machine
-  dbsm_start(&dsp_tx_sm);
-
-  // puts("post dbsm_start");
-
-  //int which = 0;
-
-  while(1){
-    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
-    // which ^= 0x8000;
-
-    buffer_irq_handler(0);
-
-    int pending = pic_regs->pending;		// poll for under or overrun
-
-    if (pending & PIC_UNDERRUN_INT){
-      dbsm_handle_tx_underrun(&dsp_tx_sm);
-      pic_regs->pending = PIC_UNDERRUN_INT;	// clear interrupt
-      putchar('U');
-    }
-
-    if (pending & PIC_OVERRUN_INT){
-      dbsm_handle_rx_overrun(&dsp_rx_sm);
-      pic_regs->pending = PIC_OVERRUN_INT;	// clear pending interrupt
-
-      // FIXME Figure out how to handle this robustly.
-      // Any buffers that are emptying should be allowed to drain...
-
-      if (streaming_p){
-	// restart_streaming();
-	// FIXME report error
-      }
-      else {
-	// FIXME report error
-      }
-      putchar('O');
-    }
-  }
-}
diff --git a/firmware/microblaze/apps/set_hw_rev.c b/firmware/microblaze/apps/set_hw_rev.c
deleted file mode 100644
index d4ac8ff81..000000000
--- a/firmware/microblaze/apps/set_hw_rev.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include <u2_init.h>
-#include <nonstdio.h>
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-
-#define HW_REV_MAJOR 0
-#define HW_REV_MINOR 3
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\nset_hw_rev\n");
-
-  bool ok = true;
-  unsigned char maj = HW_REV_MAJOR;
-  unsigned char min = HW_REV_MINOR;
-  ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1);
-  ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1);
-
-  if (ok)
-    printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-  else
-    printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR);
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/test1.c b/firmware/microblaze/apps/test1.c
deleted file mode 100644
index c3cc3be56..000000000
--- a/firmware/microblaze/apps/test1.c
+++ /dev/null
@@ -1,282 +0,0 @@
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include "nonstdio.h"
-
-// Globals
-#define EMPTY 0
-#define FILLING 1
-#define FULL 2
-#define EMPTYING 3
-
-#define PORT 2    // ethernet = 2, serdes = 0
-int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf;
-int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle;
-
-int buffer_state[4];
-
-
-void double_buffering(int port);
-
-//
-// We register this in the secondary interrupt vector.
-// It's called on buffer manager interrupts
-//
-void
-buffer_irq_handler(unsigned irq)
-{
-  double_buffering(PORT);
-}
-
-int
-main(void)
-{
-  int i;
-
-  u2_init();
-
-  // Control LEDs
-  output_regs->leds = 0x02;
-
-  // Turn on ADCs
-  output_regs->adc_ctrl = 0x0A;
-
-  // Set up TX Chain
-  dsp_tx_regs->freq = 0;
-  dsp_tx_regs->scale_iq = (1 << 16) | 1;
-  dsp_tx_regs->interp_rate = 8;
-
-  // Set up RX Chain
-  dsp_rx_regs->freq = 0;
-  dsp_rx_regs->scale_iq = (1 << 16) | 1;
-  dsp_rx_regs->decim_rate = 8;
-
-  // Set up buffer control, using only 4 for now
-  for(i=0;i<4;i++) 
-    buffer_state[i] = EMPTY;
-
-  // Set up DSP RX
-  buffer_state[0] = FILLING;
-  serdes_tx_idle = 1;
-  bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
-
-  //dsp_rx_regs->run_rx = 1;           // Start DSP_RX
-  putstr("Done DSP RX setup\n");
-
-  // Set up serdes RX
-  buffer_state[2] = FILLING;
-  dsp_tx_idle = 1;
-  bp_receive_to_buf(2, PORT, 1, 5, 504);
-
-  while (buffer_pool_status->status == 0)  // wait for completion of DSP RX
-    ;
-
-  putstr("Done DSP TX setup\n");
-  //dsp_tx_regs->run_tx = 1;
-
-  // register interrupt handler
-  pic_register_handler(IRQ_BUFFER, buffer_irq_handler);
-
-  while (1)
-    ;
-
-  hal_finish();
-  return 1;
-}
-
-void 
-double_buffering(int port) {
-  unsigned int localstatus = buffer_pool_status->status;
-
-  if(localstatus & BPS_DONE_0) {
-    bp_clear_buf(0);
-    if(buffer_state[0] == FILLING) {
-      buffer_state[0] = FULL;
-      if(buffer_state[1] == EMPTY) {
-	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[1] = FILLING;
-      }
-      else
-	dsp_rx_idle = 1;
-      if(serdes_tx_idle) {
-	serdes_tx_idle = 0;
-	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
-	buffer_state[0] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[0] = EMPTY;
-      if(dsp_rx_idle) {
-	dsp_rx_idle = 0;
-	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 0, use 500 lines
-	buffer_state[0] = FILLING;
-      }
-      if(buffer_state[1] == FULL) {
-	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
-	buffer_state[1] = EMPTYING;
-      }
-      else
-	serdes_tx_idle = 1;
-    }
-    putstr("Int Proc'ed 0\n");
-  }
-  if(localstatus & BPS_DONE_1) {
-    bp_clear_buf(1);
-    if(buffer_state[1] == FILLING) {
-      buffer_state[1] = FULL;
-      if(buffer_state[0] == EMPTY) {
-	bp_receive_to_buf(0, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[0] = FILLING;
-      }
-      else
-	dsp_rx_idle = 1;
-      if(serdes_tx_idle) {
-	serdes_tx_idle = 0;
-	bp_send_from_buf(1, port, 1, 10, 509);  // SERDES_TX from buffer 1
-	buffer_state[1] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[1] = EMPTY;
-      if(dsp_rx_idle) {
-	dsp_rx_idle = 0;
-	bp_receive_to_buf(1, 1, 1, 10, 509);  // DSP_RX to buffer 1, use 500 lines
-	buffer_state[1] = FILLING;
-      }
-      if(buffer_state[0] == FULL) {
-	bp_send_from_buf(0, port, 1, 10, 509);  // SERDES_TX from buffer 0
-	buffer_state[0] = EMPTYING;
-      }
-      else
-	serdes_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 1\n");
-  }
-  if(localstatus & BPS_DONE_2) {
-    bp_clear_buf(2);
-    if(buffer_state[2] == FILLING) {
-      buffer_state[2] = FULL;
-      if(buffer_state[3] == EMPTY) {
-	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3, use 500 lines
-	buffer_state[3] = FILLING;
-      }
-      else
-	serdes_rx_idle = 1;
-      if(dsp_tx_idle) {
-	dsp_tx_idle = 0;
-	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
-	buffer_state[2] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[2] = EMPTY;
-      if(serdes_rx_idle) {
-	serdes_rx_idle = 0;
-	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2
-	buffer_state[2] = FILLING;
-      }
-      if(buffer_state[3] == FULL) {
-	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
-	buffer_state[3] = EMPTYING;
-      }
-      else
-	dsp_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 2\n");
-  }
-  if(localstatus & BPS_DONE_3) {
-    bp_clear_buf(3);
-    if(buffer_state[3] == FILLING) {
-      buffer_state[3] = FULL;
-      if(buffer_state[2] == EMPTY) {
-	bp_receive_to_buf(2, port, 1, 5, 504);  // SERDES_RX to buffer 2, use 500 lines
-	buffer_state[2] = FILLING;
-      }
-      else
-	serdes_rx_idle = 1;
-      if(dsp_tx_idle) {
-	dsp_tx_idle = 0;
-	bp_send_from_buf(3, 1, 1, 5, 504);  // DSP_TX from buffer 3
-	buffer_state[3] = EMPTYING;
-      }
-    }
-    else {  // buffer was emptying
-      buffer_state[3] = EMPTY;
-      if(serdes_rx_idle) {
-	serdes_rx_idle = 0;
-	bp_receive_to_buf(3, port, 1, 5, 504);  // SERDES_RX to buffer 3
-	buffer_state[3] = FILLING;
-      }
-      if(buffer_state[2] == FULL) {
-	bp_send_from_buf(2, 1, 1, 5, 504);  // DSP_TX from buffer 2
-	buffer_state[2] = EMPTYING;
-      }
-      else
-	dsp_tx_idle = 1;
-    }
-  putstr("Int Proc'ed 3\n");
-  }
-}
-
-// Spare Code
-
-#if 0  
-  // Set up LSDAC
-  int i = 0;
-  while(1) {
-    int command = (3 << 19) | (0 << 16) |  (i & 0xffff);
-    spi_transact(SPI_TXONLY, SPI_SS_TX_DAC, command, 24, 1); // negate TX phase
-    i++;
-  }
-#endif
-
-#if 0  
-  // Write to buffer 0
-  int *buf = (int *)(BUFFER_BASE + BUFFER_0);
-  puthex_nl((int)buf);
-
-  for(i=0;i<BUFFER_SIZE;i++)
-    buf[i] = i;
-
-  putstr("Filled buffer 0\n");
-
-  // Write to buffer 1
-  buf = (int *)(BUFFER_BASE + BUFFER_1);
-  puthex_nl((int)buf);
-  for(i=0;i<BUFFER_SIZE;i++)
-    buf[i] =  i + ((i^0xFFFF) << 16);
-
-  putstr("Filled buffer 1\n");
-
-#endif
-
-#if 0
-  // rx SERDES into buffer #2  (buf,port,step,fl,ll)
-  bp_receive_to_buf(2, 0, 1, 10, 300);
-  putstr("SERDES RX buffer setup\n");
-
-  // send SERDES from buffer #0 (buf,port,step,fl,ll)
-  bp_send_from_buf(0, 0, 1, 20, 200);
-  putstr("SERDES TX buffer setup\n");
-
-#endif
-
-#if 0
-  // send to DACs from buffer #1
-  bp_send_from_buf(1 /*buf#*/, 1 /*port*/, 1 /*step*/, 20 /*fl*/, 250 /*ll*/);
-  putstr("DAC Buffer setup\n");
-#endif
-
-#if 0
-  //putstr("ENTER INT\n");
-  for(i=0;i<8;i++)
-    if(*status & (1<<i)) {
-      //putstr("Clearing buf ");
-      puthex_nl(i);
-      bp_clear_buf(i);
-    }
-  //putstr("EXIT INT\n");
-#endif
diff --git a/firmware/microblaze/apps/test_db_spi.c b/firmware/microblaze/apps/test_db_spi.c
deleted file mode 100644
index f4fa98ef1..000000000
--- a/firmware/microblaze/apps/test_db_spi.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <u2_init.h>
-#include <nonstdio.h>
-#include <hal_io.h>
-#include <spi.h>
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("\ntest_db_spi");
-
-  while(1){
-    spi_transact(SPI_TXONLY, SPI_SS_RX_DB, 0xCC33, 16, SPIF_PUSH_FALL);
-    spi_transact(SPI_TXONLY, SPI_SS_TX_DB, 0x33CC, 16, SPIF_PUSH_FALL);
-  }
-}
diff --git a/firmware/microblaze/apps/test_i2c.c b/firmware/microblaze/apps/test_i2c.c
deleted file mode 100644
index f349ead88..000000000
--- a/firmware/microblaze/apps/test_i2c.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <u2_init.h>		/* FIXME */
-#include <i2c.h>
-#include <usrp2_i2c_addr.h>
-#include <string.h>
-#include <hal_io.h>
-
-
-
-#define ASSERT_TRUE(x) \
-  do { \
-    if (!(x)){ \
-      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-#define ASSERT_FALSE(x) \
-  do { \
-    if (x){ \
-      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-
-#define BUFSIZE 128
-
-int
-main(void)
-{
-  int i;
-  bool ok;
-  int  nerrors = 0;
-  uint8_t buf[BUFSIZE];
-  int not_dev_addr = 0x35;	// no device with this address on the i2c bus.
-  int offset;
-  int len;
-  
-  u2_init();
-
-  puts("test_i2c\n");
-
-  // try writing a non-existent device
-  buf[0] = 0xA5;
-  ok = i2c_write(not_dev_addr, buf, 1);
-  ASSERT_FALSE(ok);
-
-  // try read from non-existent device
-  buf[0] = 0;
-  ok = i2c_read(not_dev_addr, buf, 1);
-  ASSERT_FALSE(ok);
-
-  // try writing eeprom
-  offset = 31;
-  len = 8;
-  memset(buf, 0, sizeof(buf));
-  for (i = 0; i < len; i++)
-    buf[i] = i;
-  ok = eeprom_write(I2C_ADDR_MBOARD, offset, buf, len);
-  ASSERT_TRUE(ok);
-
-  // now try to read it back
-  offset = 31;
-  len = 8;
-  memset(buf, 0, sizeof(buf));
-  ok = eeprom_read(I2C_ADDR_MBOARD, offset, buf, len);
-  ASSERT_TRUE(ok);
-
-  // check result
-  for (i = 0; i < len; i++){
-    if (buf[i] != i){
-      printf("buf[%d] = %d, should be %d\n", i, buf[i], i);
-      nerrors++;
-    }
-  }
-  
-  if (nerrors == 0){
-    output_regs->leds = 0x3;
-    puts("PASSED\n");
-  }
-  else {
-    output_regs->leds = 0x0;
-    puts("FAILED\n");
-  }
-
-  hal_finish();
-  return 0;
-}
-
diff --git a/firmware/microblaze/apps/test_lsadc.c b/firmware/microblaze/apps/test_lsadc.c
deleted file mode 100644
index 5fda29cd7..000000000
--- a/firmware/microblaze/apps/test_lsadc.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <lsadc.h>
-#include <lsdac.h>
-#include <u2_init.h>
-#include <nonstdio.h>
-#include <hal_io.h>
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("\ntest_lsadc");
-
-  uint32_t r;
-
-  unsigned int up_counter = 0;
-  
-  while (1){
-    unsigned int v;
-    v = up_counter;
-
-    lsdac_write_rx(0, v << 0);
-    lsdac_write_rx(2, v << 1);
-
-#if 1
-    r = lsadc_read_rx(0);
-    lsdac_write_rx(1, r & 0x0fff);
-    //puthex32_nl(r);
-#endif
-
-#if 1
-    r = lsadc_read_rx(1);
-    lsdac_write_rx(3, r & 0x0fff);
-    //puthex32_nl(r);
-#endif
-
-    up_counter++;
-  }
-}
diff --git a/firmware/microblaze/apps/test_lsdac.c b/firmware/microblaze/apps/test_lsdac.c
deleted file mode 100644
index 8c1bf333b..000000000
--- a/firmware/microblaze/apps/test_lsdac.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <lsdac.h>
-#include <u2_init.h>
-#include <nonstdio.h>
-#include <hal_io.h>
-
-int
-main(void)
-{
-  u2_init();
-
-  puts("\ntest_lsdac");
-
-  unsigned int up_counter = 0;
-  unsigned int dn_counter = 0;
-
-  while(1){
-    unsigned int v;
-    v = up_counter;
-    lsdac_write_rx(0, v << 0);
-    lsdac_write_rx(1, v << 1);
-    lsdac_write_rx(2, v << 2);
-    lsdac_write_rx(3, v << 3);
-
-    v = up_counter;
-    lsdac_write_tx(0, v << 0);
-    lsdac_write_tx(1, v << 1);
-    lsdac_write_tx(2, v << 2);
-    lsdac_write_tx(3, v << 3);
-
-    up_counter++;
-    dn_counter--;
-  }
-}
diff --git a/firmware/microblaze/apps/test_phy_comm.c b/firmware/microblaze/apps/test_phy_comm.c
deleted file mode 100644
index d312ca4cc..000000000
--- a/firmware/microblaze/apps/test_phy_comm.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-// check communication with ethernet PHY chip
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include "ethernet.h"
-#include "pic.h"
-#include "nonstdio.h"
-
-
-#define DELTA_T     12500000  		// .125s (10ns per tick)
-//#define DELTA_T      10000
-
-// debugging output on tx pins
-#define LS_MASK  0xE0000
-#define LS_1000  0x80000
-#define LS_100   0x40000
-#define LS_10    0x20000
-
-
-
-#define U2_ETHERTYPE 0xBEEF
-
-
-static volatile int led_link_up_flag = 0;
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  int v = 0;
-  switch(speed){
-  case 10:
-    v = LS_10;
-    led_link_up_flag = 0x2;
-    break;
-    
-  case 100:
-    v = LS_100;
-    led_link_up_flag = 0x2;
-    break;
-    
-  case 1000:
-    v = LS_100;
-    led_link_up_flag = 0x2;
-    break;
-
-  default:
-    v = 0;
-    led_link_up_flag = 0;
-    break;
-  }
-
-  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
-
-  putstr("\neth link changed: speed = ");
-  puthex_nl(speed);
-}
-
-void
-timer_handler(unsigned irq)
-{
-  static int led_counter = 0;
-
-  hal_set_timeout(DELTA_T);	// schedule next timeout
-  output_regs->leds = (led_counter++ & 0x1) | led_link_up_flag;
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  putstr("\n test_phy_comm\n");
-
-  pic_register_handler(IRQ_ONETIME, timer_handler);
-  hal_set_timeout(DELTA_T);	// schedule timeout
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-
-  output_regs->phy_ctrl = 1;	/* reset the eth PHY */
-  output_regs->phy_ctrl = 0;
-
-  ethernet_init();
-
-  while(1)
-    ;
-
-  return 0;
-}
diff --git a/firmware/microblaze/apps/test_ram.c b/firmware/microblaze/apps/test_ram.c
deleted file mode 100644
index 77ee693f6..000000000
--- a/firmware/microblaze/apps/test_ram.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <u2_init.h>		/* FIXME */
-#include <sd.h>
-#include <string.h>
-#include <hal_io.h>
-#include <nonstdio.h>
-#include <hal_uart.h>
-
-#define ASSERT_TRUE(x) \
-  do { \
-    if (!(x)){ \
-      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-#define ASSERT_FALSE(x) \
-  do { \
-    if (x){ \
-      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-
-#define BUFSIZE 128
-
-int test_ram()
-{
-  int i,j,k;
-  output_regs->ram_page = 1<<10;
-  
-  extram[0] = 0xDEADBEEF;
-  extram[1] = 0xF00D1234;
-  extram[7] = 0x76543210;
-  
-  output_regs->ram_page = 2<<10;
-  extram[7] = 0x55555555;
-  extram[1] = 0xaaaaaaaa;
-  extram[0] = 0xeeeeeeee;
-  
-  output_regs->ram_page = 1<<10;
-  
-  i = extram[0];
-  k = extram[1];
-  j = extram[7];
-  
-  if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
-    puts("RAM FAIL1!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  
-  output_regs->ram_page = 2<<10;
-
-  j = extram[7];
-  k = extram[1];
-  i = extram[0];
-
-  if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) {
-    puts("RAM FAIL2!\n");
-    puthex32_nl(i);
-    puthex32_nl(j);
-    puthex32_nl(k);
-    return 0;
-  }
-  return 1;
-}
-
-int
-main(void)
-{
-
-  u2_init();
-  puts("\ntest_ram\n");
-  int success = test_ram();
-  if(success)
-    puts("RAM Passed Tests\n");
-  else
-    puts("RAM Failed\n");
-
-  hal_finish();
-  return 0;
-}
-
diff --git a/firmware/microblaze/apps/test_sd.c b/firmware/microblaze/apps/test_sd.c
deleted file mode 100644
index 494432d7f..000000000
--- a/firmware/microblaze/apps/test_sd.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <u2_init.h>		/* FIXME */
-#include <sd.h>
-#include <string.h>
-#include <hal_io.h>
-#include <nonstdio.h>
-
-
-#define ASSERT_TRUE(x) \
-  do { \
-    if (!(x)){ \
-      printf("ASSERT_TRUE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-#define ASSERT_FALSE(x) \
-  do { \
-    if (x){ \
-      printf("ASSERT_FALSE failed on line %d\n", __LINE__); \
-      nerrors++; \
-    } \
-  } while(0)
-
-
-#define BUFSIZE 128
-
-int
-main(void)
-{
-  int i;
-  unsigned char buf[512];
-
-  u2_init();
-
-  puts("\ntest_sd\n");
-  
-
-  i = sd_init();
-  if(i)
-    puts("Successfully Init'ed Card\n");
-  else
-    puts("FAILED INIT of Card\n");
-
-  i = sd_read_block(2048,buf);
-  if(i) {
-    puts("READ Command accepted\n");
-    for(i=0;i<512;i++)
-      if((i&15) == 15)
-	puthex8_nl(buf[i]);
-      else {
-	puthex8(buf[i]);
-	putchar(' ');
-      }
-  }
-  else
-    puts("READ Command Rejected\n");
-  
-  puts("Done");
-  hal_finish();
-  return 0;
-}
-
diff --git a/firmware/microblaze/apps/timer_test.c b/firmware/microblaze/apps/timer_test.c
deleted file mode 100644
index 44e80b5f1..000000000
--- a/firmware/microblaze/apps/timer_test.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include "nonstdio.h"
-#include "hal_io.h"
-
-#define DELTA_T  500  		// 5 us (10ns per tick)
-
-
-void 
-timer_handler(unsigned irq)
-{
-  hal_set_timeout(DELTA_T);
-
-  putstr("Tick: ");
-  puthex_nl(0);
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  // setup timer
-
-  putstr("Setting up timer\n");
-  pic_register_handler(IRQ_ONETIME, timer_handler);
-
-  hal_set_timeout(DELTA_T);
-
-  while (1)
-    ;
-
-  putstr("Done Testing\n");
-  
-  hal_finish();
-  return 1;
-}
diff --git a/firmware/microblaze/apps/tx_standalone.c b/firmware/microblaze/apps/tx_standalone.c
deleted file mode 100644
index 1645fa8ba..000000000
--- a/firmware/microblaze/apps/tx_standalone.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "u2_init.h"
-#include "memory_map.h"
-#include "spi.h"
-#include "hal_io.h"
-#include "buffer_pool.h"
-#include "pic.h"
-#include <stdbool.h>
-#include "ethernet.h"
-#include "nonstdio.h"
-#include "usrp2_eth_packet.h"
-#include "memcpy_wa.h"
-#include "dbsm.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define	_AL4 __attribute__((aligned (4)))
-
-#define USE_BUFFER_INTERRUPT	0	// 0 or 1
-
-
-static int timer_delta = MASTER_CLK_RATE/1000;	// tick at 1kHz
-
-/*
- * This program can respond to queries from the host
- * and stream rx samples.
- *
- * Buffer 1 is used by the cpu to send frames to the host.
- * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
- * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
- */
-//#define CPU_RX_BUF	0	// eth -> cpu
-#define CPU_TX_BUF 	1	// cpu -> eth
-
-#define	DSP_RX_BUF_0	2	// dsp rx -> eth (double buffer)
-#define	DSP_RX_BUF_1	3	// dsp rx -> eth
-#define	DSP_TX_BUF_0	4	// eth -> dsp tx (double buffer)
-#define	DSP_TX_BUF_1	5	// eth -> dsp tx
-
-
-/*
- * ================================================================
- *      configure DSP RX double buffering state machine
- * ================================================================
- */
-
-
-// 4 lines of ethernet hdr + 1 line (word0)
-// DSP Rx writes timestamp followed by nlines_per_frame of samples
-#define DSP_RX_FIRST_LINE		  5
-#define DSP_RX_SAMPLES_PER_FRAME	128
-#define	DSP_RX_EXTRA_LINES		  1	// writes timestamp
-
-// Receive from DSP Rx
-buf_cmd_args_t dsp_rx_recv_args = {
-  PORT_DSP,
-  DSP_RX_FIRST_LINE,
-  BP_LAST_LINE
-};
-
-// send to ethernet
-buf_cmd_args_t dsp_rx_send_args = {
-  PORT_ETH,
-  0,		// starts with ethernet header in line 0
-  0,		// filled in from last_line register
-};
-
-dbsm_t dsp_rx_sm;	// the state machine
-
-/*
- * ================================================================
- *      configure DSP TX double buffering state machine
- * ================================================================
- */
-
-// 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
-// DSP Tx reads word0 (flags) + timestamp followed by samples
-
-#define DSP_TX_FIRST_LINE		  4
-#define DSP_TX_SAMPLES_PER_FRAME	250	// not used except w/ debugging
-#define	DSP_TX_EXTRA_LINES		  2	// reads word0 + timestamp
-
-// Receive from ethernet
-buf_cmd_args_t dsp_tx_recv_args = {
-  PORT_ETH,
-  0,
-  BP_LAST_LINE
-};
-
-// send to DSP Tx
-buf_cmd_args_t dsp_tx_send_args = {
-  PORT_DSP,
-  DSP_TX_FIRST_LINE,	// starts just past ethernet header
-  0			// filled in from last_line register
-};
-
-dbsm_t dsp_tx_sm;	// the state machine
-
-/*
- * send constant buffer to DSP TX
- */
-static inline void 
-SEND_CONST_TO_DSP_TX(void)
-{
-  bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1,
-		   DSP_TX_FIRST_LINE,
-		   DSP_TX_FIRST_LINE + DSP_TX_EXTRA_LINES + DSP_TX_SAMPLES_PER_FRAME - 1);
-}
-
-// ----------------------------------------------------------------
-
-
-
-// The mac address of the host we're sending to.
-eth_mac_addr_t host_mac_addr;
-
-
-void link_changed_callback(int speed);
-static volatile bool link_is_up = false;	// eth handler sets this
-
-
-void
-timer_irq_handler(unsigned irq)
-{
-  hal_set_timeout(timer_delta);	// schedule next timeout
-}
-
-// Tx DSP underrun
-void
-underrun_irq_handler(unsigned irq)
-{
-  dsp_tx_regs->clear_state = 1;
-  bp_clear_buf(DSP_TX_BUF_0);
-  bp_clear_buf(DSP_TX_BUF_1);
-  dbsm_stop(&dsp_tx_sm);
-
-  // FIXME anything else?
-
-  putstr("\nirq: underrun\n");
-}
-
-// Rx DSP overrun
-void
-overrun_irq_handler(unsigned irq)
-{
-  dsp_rx_regs->clear_state = 1;
-  bp_clear_buf(DSP_RX_BUF_0);
-  bp_clear_buf(DSP_RX_BUF_1);
-  dbsm_stop(&dsp_rx_sm);
-
-  // FIXME anything else?
-
-  putstr("\nirq: overrun\n");
-}
-
-static void
-start_tx_transfers(void)
-{
-  bp_clear_buf(DSP_TX_BUF_0);	// FIXME, really goes in state machine
-  bp_clear_buf(DSP_TX_BUF_1);
-
-  // fill everything with a constant 32k + 0j
-
-  uint32_t const_sample = (32000 << 16) | 0;
-  int i;
-  for (i = 0; i < BP_NLINES; i++){
-    buffer_ram(DSP_TX_BUF_0)[i] = const_sample;
-    buffer_ram(DSP_TX_BUF_1)[i] = const_sample;
-  }
-
-  /*
-   * Construct  ethernet header and word0 and preload into two buffers
-   */
-  u2_eth_packet_t	pkt;
-  memset(&pkt, 0, sizeof(pkt));
-  //pkt.ehdr.dst = *host;
-  pkt.ehdr.src = *ethernet_mac_addr();
-  pkt.ehdr.ethertype = U2_ETHERTYPE;
-  u2p_set_word0(&pkt.fixed,
-		U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0);
-  u2p_set_timestamp(&pkt.fixed, T_NOW);
-
-  memcpy_wa(buffer_ram(DSP_TX_BUF_0), &pkt, sizeof(pkt));
-  memcpy_wa(buffer_ram(DSP_TX_BUF_1), &pkt, sizeof(pkt));
-
-
-  int tx_scale = 256;
-
-  // setup Tx DSP regs
-  dsp_tx_regs->clear_state = 1;			// reset
-  dsp_tx_regs->freq = 408021893;		// 9.5 MHz [2**32 * fc/fsample]
-  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
-  dsp_tx_regs->interp_rate = 32;
-
-  // kick off the state machine
-  // dbsm_start(&dsp_rx_sm);
-
-  SEND_CONST_TO_DSP_TX();	// send constant buffer to DSP TX
-}
-
-
-void
-buffer_irq_handler(unsigned irq)
-{
-  uint32_t  status = buffer_pool_status->status;
-
-  if (0){
-    putstr("irq: ");
-    puthex32(status);
-    putchar('\n');
-  }
-
-  if (status & BPS_ERROR_ALL){
-    // FIXME rare path, handle error conditions
-  }
-
-  if (status & BPS_DONE(DSP_TX_BUF_0)){
-    bp_clear_buf(DSP_TX_BUF_0);
-    SEND_CONST_TO_DSP_TX();
-    hal_toggle_leds(0x1);
-  }
-
-}
-
-int
-main(void)
-{
-  u2_init();
-
-  // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
-  //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
-  //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
-
-  putstr("\ntx_only\n");
-  
-  // Control LEDs
-  hal_set_leds(0x0, 0x3);
-
-  if (USE_BUFFER_INTERRUPT)
-    pic_register_handler(IRQ_BUFFER,   buffer_irq_handler);
-
-  pic_register_handler(IRQ_OVERRUN,  overrun_irq_handler);
-  pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
-
-  //pic_register_handler(IRQ_TIMER, timer_irq_handler);
-  //hal_set_timeout(timer_delta);
-
-  ethernet_register_link_changed_callback(link_changed_callback);
-
-  ethernet_init();
-
-  // initialize double buffering state machine for DSP RX -> Ethernet
-  dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
-	    &dsp_rx_recv_args, &dsp_rx_send_args,
-	    dbsm_nop_inspector);
-
-  // setup receive from ETH
-  // bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
-
-#if 0
-  if (hwconfig_simulation_p()){
-    // If we're simulating, pretend that we got a start command from the host
-    eth_mac_addr_t host = {{ 0x00, 0x0A, 0xE4, 0x3E, 0xD2, 0xD5 }};
-    start_rx_cmd(&host);
-  }
-#endif
-
-  start_tx_transfers();		// send constant buffers to DSP TX
-
-  while(1){
-    if (!USE_BUFFER_INTERRUPT)
-      buffer_irq_handler(0);
-  }
-}
-
-// ----------------------------------------------------------------
-
-// debugging output on tx pins
-#define LS_MASK  0xE0000
-#define LS_1000  0x80000
-#define LS_100   0x40000
-#define LS_10    0x20000
-
-/*
- * Called when eth phy state changes (w/ interrupts disabled)
- */
-void
-link_changed_callback(int speed)
-{
-  int v = 0;
-  switch(speed){
-  case 10:
-    v = LS_10;
-    link_is_up = true;
-    break;
-    
-  case 100:
-    v = LS_100;
-    link_is_up = true;
-    break;
-    
-  case 1000:
-    v = LS_100;
-    link_is_up = true;
-    break;
-
-  default:
-    v = 0;
-    link_is_up = false;
-    break;
-  }
-
-  //hal_gpio_set_tx(v, LS_MASK);	/* set debug bits on d'board */
-
-  // hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2);
-
-  printf("\neth link changed: speed = %d\n", speed);
-}
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c
index 6b45f8f3b..092d216aa 100644
--- a/firmware/microblaze/apps/txrx_uhd.c
+++ b/firmware/microblaze/apps/txrx_uhd.c
@@ -41,7 +41,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include "clocks.h"
-#include <vrt/bits.h>
 #include "usrp2/fw_common.h"
 #include <i2c.h>
 #include <ethertype.h>
@@ -266,7 +265,7 @@ void handle_udp_ctrl_packet(
      * Peek and Poke Register
      ******************************************************************/
     case USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO:
-        if (ctrl_data_in->data.poke_args.addr < 0xC000){
+        if (0){//ctrl_data_in->data.poke_args.addr < 0xC000){
             printf("error! tried to poke into 0x%x\n", ctrl_data_in->data.poke_args.addr);
         }
         else switch(ctrl_data_in->data.poke_args.num_bytes){
diff --git a/firmware/microblaze/bootstrap b/firmware/microblaze/bootstrap
index 2343025cc..5786c1624 100755
--- a/firmware/microblaze/bootstrap
+++ b/firmware/microblaze/bootstrap
@@ -17,6 +17,7 @@
 #
 
 rm -rf *.cache
+rm -rf libusrp2/.deps
 
 aclocal
 autoconf
diff --git a/firmware/microblaze/config.guess b/firmware/microblaze/config.guess
deleted file mode 120000
index 405bc3235..000000000
--- a/firmware/microblaze/config.guess
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/automake-1.11/config.guess
\ No newline at end of file
diff --git a/firmware/microblaze/config.sub b/firmware/microblaze/config.sub
deleted file mode 120000
index 4d47fbcbc..000000000
--- a/firmware/microblaze/config.sub
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/automake-1.11/config.sub
\ No newline at end of file
diff --git a/firmware/microblaze/configure.ac b/firmware/microblaze/configure.ac
index 46968b7fb..e27bcb557 100644
--- a/firmware/microblaze/configure.ac
+++ b/firmware/microblaze/configure.ac
@@ -32,6 +32,7 @@ m4_if(m4_defn([m4_PACKAGE_VERSION]), [2.64],
      [m4_define([_AC_LANG_IO_PROGRAM(]_GCC_LANG[)], m4_defn([AC_LANG_PROGRAM(]_GCC_LANG[)]))])]) 
 
 AC_PROG_CC([mb-gcc])
+AM_PROG_CC_C_O
 LT_INIT
 
 ##################################################
@@ -46,9 +47,6 @@ AC_PATH_PROG([HEXDUMP],    [hexdump])
 ##################################################
 AC_CONFIG_FILES([ \
     Makefile \
-    apps/Makefile \
-    include/Makefile \
-    include/net/Makefile \
-    lib/Makefile \
+    usrp2/Makefile \
 ])
 AC_OUTPUT
diff --git a/firmware/microblaze/include/.gitignore b/firmware/microblaze/include/.gitignore
deleted file mode 100644
index b336cc7ce..000000000
--- a/firmware/microblaze/include/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/Makefile
-/Makefile.in
diff --git a/firmware/microblaze/include/Makefile.am b/firmware/microblaze/include/Makefile.am
deleted file mode 100644
index 6afbbcd12..000000000
--- a/firmware/microblaze/include/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright 2010 Ettus Research LLC
-#
-# Copyright 2008 Free Software Foundation, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-include $(top_srcdir)/Makefile.common
-
-SUBDIRS = net
-
-noinst_HEADERS = \
-    usrp2_fpga_regs.h \
-    usrp2_i2c_addr.h \
-    usrp2_clock_bits.h \
-    usrp2_types.h \
-    vrt/bits.h \
-    vrt/types.h
diff --git a/firmware/microblaze/include/compiler.h b/firmware/microblaze/include/compiler.h
deleted file mode 100644
index 4fa9b49f8..000000000
--- a/firmware/microblaze/include/compiler.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_COMPILER_H
-#define INCLUDED_COMPILER_H
-
-// FIXME gcc specific.
-#define _AL4   __attribute__((aligned (4)))
-
-
-#endif /* INCLUDED_COMPILER_H */
diff --git a/firmware/microblaze/include/net/.gitignore b/firmware/microblaze/include/net/.gitignore
deleted file mode 100644
index 282522db0..000000000
--- a/firmware/microblaze/include/net/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/firmware/microblaze/include/net/Makefile.am b/firmware/microblaze/include/net/Makefile.am
deleted file mode 100644
index 32b0bf9dc..000000000
--- a/firmware/microblaze/include/net/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright 2010 Ettus Research LLC
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-include $(top_srcdir)/Makefile.common
-
-noinst_HEADERS = \
-	eth_mac_addr.h \
-	padded_eth_hdr.h \
-	socket_address.h
diff --git a/firmware/microblaze/include/net/eth_mac_addr.h b/firmware/microblaze/include/net/eth_mac_addr.h
deleted file mode 100644
index b44fb68f7..000000000
--- a/firmware/microblaze/include/net/eth_mac_addr.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_ETH_MAC_ADDR_H
-#define INCLUDED_ETH_MAC_ADDR_H
-
-#include <stdint.h>
-
-// Ethernet MAC address
-
-typedef struct {
-  uint8_t	addr[6];
-} eth_mac_addr_t;
-
-#endif /* INCLUDED_ETH_MAC_ADDR_H */
diff --git a/firmware/microblaze/include/net/padded_eth_hdr.h b/firmware/microblaze/include/net/padded_eth_hdr.h
deleted file mode 100644
index df816734f..000000000
--- a/firmware/microblaze/include/net/padded_eth_hdr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009,2010 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_PADDED_ETH_HDR_H
-#define INCLUDED_PADDED_ETH_HDR_H
-
-#include <compiler.h>
-#include <net/eth_mac_addr.h>
-
-/*!
- * \brief Standard 14-byte ethernet header plus two leading bytes of padding.
- *
- * This is what a buffer contains in line 1 when using the "slow mode"
- */
-typedef struct {
-  uint16_t	 pad;
-  eth_mac_addr_t dst;
-  eth_mac_addr_t src;
-  uint16_t 	 ethertype;
-} _AL4 padded_eth_hdr_t;
-
-
-#endif /* INCLUDED_PADDED_ETH_HDR_H */
diff --git a/firmware/microblaze/include/net/socket_address.h b/firmware/microblaze/include/net/socket_address.h
deleted file mode 100644
index 336f30a0c..000000000
--- a/firmware/microblaze/include/net/socket_address.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2010 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_SOCKET_ADDRESS_H
-#define INCLUDED_SOCKET_ADDRESS_H
-
-#include <lwip/ip_addr.h>
-
-// port and address are in network byte order
-
-typedef struct socket_address {
-  unsigned short   port;
-  struct ip_addr   addr;
-} socket_address_t;
-
-static inline struct socket_address 
-make_socket_address(struct ip_addr addr, int port)
-{
-  struct socket_address r;
-  r.port = port;
-  r.addr = addr;
-  return r;
-}
-
-
-
-#endif /* INCLUDED_SOCKET_ADDRESS_H */
diff --git a/firmware/microblaze/include/usrp2_clock_bits.h b/firmware/microblaze/include/usrp2_clock_bits.h
deleted file mode 100644
index d2052e941..000000000
--- a/firmware/microblaze/include/usrp2_clock_bits.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_USRP2_CLOCK_BITS_H
-#define INCLUDED_USRP2_CLOCK_BITS_H
-
-#define	_MC_WE_LOCK			0x0001
-#define	_MC_MIMO_CLK_INPUT		0x0002		// else SMA input
-
-/*
- * Derived masks (use these):
- *
- * We get our input from 1 of three places:
- *  Our free running oscilator, our SMA connector, or from the MIMO connector
- */
-#define	MC_WE_DONT_LOCK			0x0000
-#define	MC_WE_LOCK_TO_SMA		(_MC_WE_LOCK | 0)
-#define	MC_WE_LOCK_TO_MIMO		(_MC_WE_LOCK | _MC_MIMO_CLK_INPUT)
-
-/*
- * Independent of the source of the clock, we may or may not drive our
- * clock onto the mimo connector.  Note that there are dedicated clock
- * signals in each direction, so disaster doesn't occurs if we're
- * unnecessarily providing clock.
- */
-#define	MC_PROVIDE_CLK_TO_MIMO		0x0004
-
-#define MC_REF_CLK_MASK          0x0f
-
-#define MC_PPS_SOURCE_SMA        (0x00 << 4)
-#define MC_PPS_SOURCE_MIMO       (0x01 << 4)
-
-#define MC_PPS_POLARITY_NEG      (0x00 << 5)
-#define MC_PPS_POLARITY_POS      (0x01 << 5)
-
-#endif /* INCLUDED_USRP2_CLOCK_BITS_H */
diff --git a/firmware/microblaze/include/usrp2_fpga_regs.h b/firmware/microblaze/include/usrp2_fpga_regs.h
deleted file mode 100644
index b0f83df60..000000000
--- a/firmware/microblaze/include/usrp2_fpga_regs.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_USRP2_FPGA_REGS_H
-#define INCLUDED_USSRP2_FPGA_REGS_H
-
-#include "usrp2_cdefs.h"
-
-__U2_BEGIN_DECLS
-
-// ----------------------------------------------------------------
-
-#define	DSP_CORE_TX_BASE	128
-
-// DUC center frequency tuning word (phase increment)
-#define FR_TX_FREQ_0		(0 + DSP_CORE_TX_BASE)
-
-// I & Q output scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE)
-#define FR_TX_SCALE_0		(1 + DSP_CORE_TX_BASE)
-
-// Tx interpolation rate (set to 1 less than desired rate)
-#define FR_TX_INTERP_RATE_0	(2 + DSP_CORE_TX_BASE)
-
-// Write 1 (actually anything) to clear tx state
-#define FR_TX_CLEAR_STATE_0	(3 + DSP_CORE_TX_BASE)
-
-// ----------------------------------------------------------------
-
-#define	DSP_CORE_RX_BASE	160
-
-// DDC center frequency tuning word (phase increment)
-#define FR_RX_FREQ_0		(0 + DSP_CORE_RX_BASE)
-
-// I & Q input scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE)
-#define FR_RX_SCALE_0		(1 + DSP_CORE_RX_BASE)
-
-// Rx decimation rate (set to 1 less than desired rate)
-#define FR_RX_DECIM_RATE_0	(2 + DSP_CORE_RX_BASE)
-
-// The next two registers concatenated are the Rx command register.
-//
-// Writing FR_RX_TIME_TO_RX_0 writes the concatenated value into the
-// cmd queue.  Thus, if you're writing both, be sure to write
-// FR_RX_QTY_0 first.
-//
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |                          Timestamp                            |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-#define FR_RX_TIME_TO_RX	(3 + DSP_CORE_RX_BASE)
-
-//                          23-bits                       9-bits
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |                number_of_lines              | lines_per_frame |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-#define FR_RX_QTY_0		(4 + DSP_CORE_RX_BASE)
-
-// write a 1 (anything actually) to clear the overrun 
-#define FR_RX_CLR_OVERRUN_0	(5 + DSP_CORE_RX_BASE)
-
-
-__U2_END_DECLS
-
-#endif /* INCLUDED_USRP2_FPGA_REGS_H */
diff --git a/firmware/microblaze/include/usrp2_i2c_addr.h b/firmware/microblaze/include/usrp2_i2c_addr.h
deleted file mode 100644
index 46f5a7556..000000000
--- a/firmware/microblaze/include/usrp2_i2c_addr.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_USRP2_I2C_ADDR_H
-#define INCLUDED_USRP2_I2C_ADDR_H
-
-// I2C addresses
-
-#define I2C_DEV_EEPROM	0x50		// 24LC02[45]:  7-bits 1010xxx
-
-#define	I2C_ADDR_MBOARD	(I2C_DEV_EEPROM	| 0x0)
-#define	I2C_ADDR_TX_A	(I2C_DEV_EEPROM | 0x4)
-#define	I2C_ADDR_RX_A	(I2C_DEV_EEPROM | 0x5)
-
-
-// format of USRP2 motherboard rom
-//	00: 0x00	h/w rev (LSB)
-//	01: 0x00	h/w rev (MSB)
-//	02: 0x00	MAC addr 0
-//	03: 0x50	MAC addr 1
-//	04: 0xC2	MAC addr 2
-//	05: 0x85	MAC addr 3
-//	06: 0x3.	MAC addr 4
-//	07: 0x..	MAC addr 5
-
-#define MBOARD_REV_LSB	0x00
-#define	MBOARD_REV_MSB  0x01
-#define	MBOARD_MAC_ADDR 0x02
-#define MBOARD_IP_ADDR  0x0C
-
-
-// format of daughterboard EEPROM
-//	00: 0xDB	code for ``I'm a daughterboard''
-//	01:   ..	Daughterboard ID (LSB)
-//	02:   ..	Daughterboard ID (MSB)
-//	03:   ..	io bits  7-0 direction (bit set if it's an output from m'board)
-//	04:   ..	io bits 15-8 direction (bit set if it's an output from m'board)
-//	05:   ..	ADC0 DC offset correction (LSB)
-//	06:   ..	ADC0 DC offset correction (MSB)
-//	07:   ..	ADC1 DC offset correction (LSB)
-//	08:   ..	ADC1 DC offset correction (MSB)
-// 	...
-//	1f:   ..	negative of the sum of bytes [0x00, 0x1e]
-
-#define	DB_EEPROM_MAGIC		0x00
-#define	  DB_EEPROM_MAGIC_VALUE			0xDB
-#define	DB_EEPROM_ID_LSB		0x01
-#define	DB_EEPROM_ID_MSB		0x02
-#define	DB_EEPROM_OE_LSB		0x03
-#define	DB_EEPROM_OE_MSB		0x04
-#define	DB_EEPROM_OFFSET_0_LSB		0x05	// offset correction for ADC or DAC 0
-#define	DB_EEPROM_OFFSET_0_MSB		0x06
-#define	DB_EEPROM_OFFSET_1_LSB		0x07	// offset correction for ADC or DAC 1
-#define	DB_EEPROM_OFFSET_1_MSB		0x08
-#define	DB_EEPROM_CHKSUM		0x1f
-
-#define	DB_EEPROM_CLEN			0x20	// length of common portion of eeprom
-
-#define	DB_EEPROM_CUSTOM_BASE		DB_EEPROM_CLEN	// first avail offset for
-							//   daughterboard specific use
-
-#endif /* INCLUDED_USRP2_I2C_ADDR_H */
-
diff --git a/firmware/microblaze/include/usrp2_types.h b/firmware/microblaze/include/usrp2_types.h
deleted file mode 100644
index fe45936f0..000000000
--- a/firmware/microblaze/include/usrp2_types.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_USRP2_TYPES_H
-#define INCLUDED_USRP2_TYPES_H
-
-#include <stdint.h>
-
-/*!
- * \brief Fixed point representation of a frequency in Hertz (VITA-49 compatible)
- *
- * 64-bit two's complement, with the radix point 20 bits up from the bottom. 
- * Q44.20 format (20 bits to the right of the radix point)
- *
- * Values range from +/- 8.79 terahertz with a resolution of 0.95 microhertz.
- */
-typedef int64_t	u2_fxpt_freq_t;
-
-#define U2_FPF_RP	20	// location of radix point in u2_fxpt_freq_t
-
-// macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1LL << U2_FPF_RP))
-
-static inline u2_fxpt_freq_t
-u2_double_to_fxpt_freq(double f)
-{
-  return U2_DOUBLE_TO_FXPT_FREQ(f);
-}
-
-static inline int
-u2_fxpt_freq_round_to_int(u2_fxpt_freq_t fx)
-{
-  return (int)((fx+(1<<(U2_FPF_RP-1)))>>U2_FPF_RP);
-}
-
-static inline double
-u2_fxpt_freq_to_double(u2_fxpt_freq_t fx)
-{
-  return ((double) fx) * 1.0/(1 << U2_FPF_RP);
-}
-
-static inline uint32_t
-u2_fxpt_freq_hi(u2_fxpt_freq_t f)
-{
-  return ((f >> 32) & 0xffffffff);
-}
-
-static inline uint32_t
-u2_fxpt_freq_lo(u2_fxpt_freq_t f)
-{
-  return (f & 0xffffffff);
-}
-
-static inline u2_fxpt_freq_t
-u2_fxpt_freq_from_hilo(uint32_t hi, uint32_t lo)
-{
-  return (((u2_fxpt_freq_t) hi) << 32) | lo;
-}
-
-/*!
- * \brief Fixed point representation of a gain in dB (VITA-49 compatible)
- *
- * 16-bit two's complement, with the radix point 7 bits up from the bottom. 
- * Q9.7 format (7 bits to the right of the radix point)
- */
-typedef int16_t u2_fxpt_gain_t;
-
-#define U2_FPG_RP	7	// location of radix point in u2_fxpt_gain_t
-
-// macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << U2_FPG_RP))
-
-static inline u2_fxpt_gain_t
-u2_double_to_fxpt_gain(double g)
-{
-  return U2_DOUBLE_TO_FXPT_GAIN(g);
-}
-
-static inline float
-u2_fxpt_gain_to_double(u2_fxpt_gain_t fx)
-{
-  return ((double) fx) * 1.0/(1 << U2_FPG_RP);
-}
-
-static inline int
-u2_fxpt_gain_round_to_int(u2_fxpt_gain_t fx)
-{ 
-  return (int)((fx+(1<<(U2_FPG_RP-1)))>>U2_FPG_RP);
-}
-
-#endif /* INCLUDED_USRP2_TYPES_H */
diff --git a/firmware/microblaze/include/vrt/bits.h b/firmware/microblaze/include/vrt/bits.h
deleted file mode 100644
index 54eeec7b4..000000000
--- a/firmware/microblaze/include/vrt/bits.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_VRT_BITS_H
-#define INCLUDED_VRT_BITS_H
-
-#include <stdint.h>
-
-
-/* VRT Header bits */
-
-#define	VRTH_PT_MASK		  (0xf << 28)
-#define	VRTH_PT_IF_DATA_NO_SID	  (0x0 << 28)	// IF-Data, no stream id
-#define	VRTH_PT_IF_DATA_WITH_SID  (0x1 << 28)	// IF-Data, w/ stream id
-#define VRTH_PT_EXT_DATA_NO_SID	  (0x2 << 28)
-#define	VRTH_PT_EXT_DATA_WITH_SID (0x3 << 28)
-#define	VRTH_PT_IF_CONTEXT	  (0x4 << 28)
-#define	VRTH_PT_EXT_CONTEXT	  (0x5 << 28)
-
-#define	VRTH_HAS_CLASSID	  (1 << 27)
-#define	VRTH_HAS_TRAILER	  (1 << 26)	// Data pkts only
-#define	VRTH_START_OF_BURST	  (1 << 25)	// Data (Tx) pkts only
-#define	VRTH_END_OF_BURST	  (1 << 24)	// Data (Tx) pkts only
-#define	VRTH_TSM		  (1 << 24)	// Context pkts only
-
-#define	VRTH_TSI_MASK		  (0x3 << 22)
-#define	VRTH_TSI_NONE		  (0x0 << 22)
-#define	VRTH_TSI_UTC		  (0x1 << 22)
-#define	VRTH_TSI_GPS		  (0x2 << 22)
-#define VRTH_TSI_OTHER		  (0x3 << 22)
-
-#define	VRTH_TSF_MASK		  (0x3 << 20)
-#define	VRTH_TSF_NONE		  (0x0 << 20)
-#define	VRTH_TSF_SAMPLE_CNT	  (0x1 << 20)
-#define	VRTH_TSF_REAL_TIME_PS	  (0x2 << 20)
-#define	VRTH_TSF_FREE_RUNNING	  (0x3 << 20)
-
-#define	VRTH_PKT_CNT_SHIFT	  16
-#define	VRTH_PKT_CNT_MASK	  (0xf << 16)
-
-#define	VRTH_PKT_SIZE_MASK	  0xffff		    
-
-
-static inline int
-vrth_pkt_cnt(uint32_t h)
-{
-  return (h & VRTH_PKT_CNT_MASK) >> 16;
-}
-
-static inline int
-vrth_pkt_size(uint32_t h)
-{
-  return h & VRTH_PKT_SIZE_MASK;
-}
-
-/*
- * Trailer bits
- */
-#define	TR_E		      (1 << 8)
-
-#define TR_ENABLE(x) ((x) << 20)
-#define	TR_STATE(x)  ((x) <<  8)
-
-// Use these with TR_ENABLE and TR_STATE
-#define	TR_CAL_TIME	      (1 << 11)
-#define	TR_VALID_DATA	      (1 << 10)
-#define TR_REF_LOCK	      (1 <<  9)
-#define	TR_AGC		      (1 <<  8)
-#define TR_DETECTED_SIG	      (1 <<  7)
-#define	TR_SPECTRAL_INVERSION (1 <<  6)
-#define	TR_OVER_RANGE	      (1 <<  5)
-#define	TR_SAMPLE_LOSS	      (1 <<  4)
-#define TR_USER_3	      (1 <<  3)
-#define TR_USER_2	      (1 <<  2)
-#define TR_USER_1	      (1 <<  1)
-#define TR_USER_0	      (1 <<  0)
-
-#endif /* INCLUDED_VRT_BITS_H */
diff --git a/firmware/microblaze/include/vrt/types.h b/firmware/microblaze/include/vrt/types.h
deleted file mode 100644
index edfa4ec37..000000000
--- a/firmware/microblaze/include/vrt/types.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef INCLUDED_VRT_TYPES_H
-#define INCLUDED_VRT_TYPES_H
-
-#include <stdint.h>
-
-/* macros for dealing with fixed point numbers */
-#define _FXPT_C(_type, _x, _rp) ((_type)((_x)*(1ll << _rp)))
-#define _FXPT_TO_INT(_x, _one) (((_x) + ((_one)/2))/(_one))
-#define _FXPT_TO_DOUBLE(_x, _one) ((double)(_x) * (1.0/(_one)))
-
-/***********************************************************************
- * The VRT Altitude Type (meters)
- **********************************************************************/
-typedef int32_t vrt_altitude_t;
-#define VRT_ALTITUDE_RP 5
-#define VRT_ALTITUDE_C(_x) _FXPT_C(vrt_altitude_t, _x, VRT_ALTITUDE_RP)
-
-static inline vrt_altitude_t
-double_to_vrt_altitude(double num){
-  return VRT_ALTITUDE_C(num);
-}
-
-static inline int32_t
-vrt_altitude_round_to_int(vrt_altitude_t fx){
-  return _FXPT_TO_INT(fx, VRT_ALTITUDE_C(1));
-}
-
-static inline double
-vrt_altitude_to_double(vrt_altitude_t fx){
-  return _FXPT_TO_DOUBLE(fx, VRT_ALTITUDE_C(1));
-}
-
-/***********************************************************************
- * The VRT Geolocation Angle Type (degrees)
- **********************************************************************/
-typedef int32_t vrt_geo_angle_t;
-#define VRT_GEO_ANGLE_RP 22
-#define VRT_GEO_ANGLE_C(_x) _FXPT_C(vrt_geo_angle_t, _x, VRT_GEO_ANGLE_RP)
-
-static inline vrt_geo_angle_t
-double_to_vrt_geo_angle(double num){
-  return VRT_GEO_ANGLE_C(num);
-}
-
-static inline int16_t
-vrt_geo_angle_round_to_int(vrt_geo_angle_t fx){
-  return _FXPT_TO_INT(fx, VRT_GEO_ANGLE_C(1));
-}
-
-static inline double
-vrt_geo_angle_to_double(vrt_geo_angle_t fx){
-  return _FXPT_TO_DOUBLE(fx, VRT_GEO_ANGLE_C(1));
-}
-
-/***********************************************************************
- * The VRT Frequency Type (Hz)
- **********************************************************************/
-typedef int64_t vrt_freq_t;
-#define VRT_FREQ_RP 20
-#define VRT_FREQ_C(_x) _FXPT_C(vrt_freq_t, _x, VRT_FREQ_RP)
-
-static inline vrt_freq_t
-double_to_vrt_freq(double num){
-  return VRT_FREQ_C(num);
-}
-
-static inline int64_t
-vrt_freq_round_to_int(vrt_freq_t fx){
-  return _FXPT_TO_INT(fx, VRT_FREQ_C(1));
-}
-
-static inline double
-vrt_freq_to_double(vrt_freq_t fx){
-  return _FXPT_TO_DOUBLE(fx, VRT_FREQ_C(1));
-}
-
-/***********************************************************************
- * The VRT Gain Type (dB)
- **********************************************************************/
-typedef int16_t vrt_gain_t;
-#define VRT_GAIN_RP 7
-#define VRT_GAIN_C(_x) _FXPT_C(vrt_gain_t, _x, VRT_GAIN_RP)
-
-static inline vrt_gain_t
-double_to_vrt_gain(double num){
-  return VRT_GAIN_C(num);
-}
-
-static inline int16_t
-vrt_gain_round_to_int(vrt_gain_t fx){
-  return _FXPT_TO_INT(fx, VRT_GAIN_C(1));
-}
-
-static inline double
-vrt_gain_to_double(vrt_gain_t fx){
-  return _FXPT_TO_DOUBLE(fx, VRT_GAIN_C(1));
-}
-
-/***********************************************************************
- * The VRT Temperature Type (Celcius)
- **********************************************************************/
-typedef int16_t vrt_temp_t;
-#define VRT_TEMP_RP 6
-#define VRT_TEMP_C(_x) _FXPT_C(vrt_temp_t, _x, VRT_TEMP_RP)
-
-static inline vrt_temp_t
-double_to_vrt_temp(double num){
-  return VRT_TEMP_C(num);
-}
-
-static inline int16_t
-vrt_temp_round_to_int(vrt_temp_t fx){
-  return _FXPT_TO_INT(fx, VRT_TEMP_C(1));
-}
-
-static inline double
-vrt_temp_to_double(vrt_temp_t fx){
-  return _FXPT_TO_DOUBLE(fx, VRT_TEMP_C(1));
-}
-
-#endif /* INCLUDED_VRT_TYPES_H */
diff --git a/firmware/microblaze/lib/.gitignore b/firmware/microblaze/lib/.gitignore
deleted file mode 100644
index 5d838bf6c..000000000
--- a/firmware/microblaze/lib/.gitignore
+++ /dev/null
@@ -1,40 +0,0 @@
-*~
-/*-stamp
-/*.a
-/*.bin
-/*.dump
-/*.log
-/*.rom
-/.deps
-/Makefile
-/Makefile.in
-/aclocal.m4
-/autom4te.cache
-/blink_leds
-/blink_leds2
-/build
-/compile
-/config.h
-/config.h.in
-/config.log
-/config.status
-/configure
-/depcomp
-/eth_test
-/gen_eth_packets
-/ibs_rx_test
-/ibs_tx_test
-/install-sh
-/libtool
-/ltmain.sh
-/missing
-/py-compile
-/rcv_eth_packets
-/run_tests.sh
-/stamp-h1
-/test1
-/test_phy_comm
-/timer_test
-/buf_ram_test
-/buf_ram_zero
-/hello
diff --git a/firmware/microblaze/lib/Makefile.am b/firmware/microblaze/lib/Makefile.am
deleted file mode 100644
index b51d74463..000000000
--- a/firmware/microblaze/lib/Makefile.am
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Copyright 2010 Ettus Research LLC
-#
-# Copyright 2007 Free Software Foundation, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-include $(top_srcdir)/Makefile.common
-
-noinst_LIBRARIES = \
-	libu2fw.a
-
-libu2fw_a_SOURCES = \
-	abort.c \
-	ad9510.c \
-	bsm12.c \
-	buffer_pool.c \
-	clocks.c \
-	dbsm.c \
-	eeprom.c \
-	ethernet.c \
-	eth_mac.c \
-	_exit.c \
-	exit.c \
-	hal_io.c \
-	hal_uart.c \
-	i2c.c \
-	mdelay.c \
-	memcpy_wa.c \
-	memset_wa.c \
-	nonstdio.c \
-	pic.c \
-	print_mac_addr.c \
-	print_rmon_regs.c \
-	print_buffer.c \
-	printf.c \
-	sd.c \
-	spi.c \
-	u2_init.c \
-	net_common.c \
-	arp_cache.c \
-	banal.c
-
-noinst_HEADERS = \
-	ad9510.h \
-	bsm12.h \
-	buffer_pool.h \
-	clocks.h \
-	dbsm.h \
-	eth_mac.h \
-	eth_mac_regs.h \
-	eth_phy.h \
-	ethernet.h \
-	hal_io.h \
-	hal_uart.h \
-	i2c.h \
-	mdelay.h \
-	memcpy_wa.h \
-	memory_map.h \
-	memset_wa.h \
-	nonstdio.h \
-	pic.h \
-	print_rmon_regs.h \
-	sd.h \
-	spi.h \
-	stdint.h \
-	stdio.h \
-	u2_init.h \
-	usrp2_bytesex.h \
-	wb16550.h \
-	net_common.h \
-	if_arp.h \
-	arp_cache.h \
-	banal.h \
-	ethertype.h
diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc
new file mode 100644
index 000000000..a576d1ccb
--- /dev/null
+++ b/firmware/microblaze/lib/Makefile.inc
@@ -0,0 +1,47 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+COMMON_SRCS = \
+	$(top_srcdir)/lib/u2_init.c \
+	$(top_srcdir)/lib/abort.c \
+	$(top_srcdir)/lib/ad9510.c \
+	$(top_srcdir)/lib/bsm12.c \
+	$(top_srcdir)/lib/buffer_pool.c \
+	$(top_srcdir)/lib/clocks.c \
+	$(top_srcdir)/lib/dbsm.c \
+	$(top_srcdir)/lib/eeprom.c \
+	$(top_srcdir)/lib/eth_mac.c \
+	$(top_srcdir)/lib/_exit.c \
+	$(top_srcdir)/lib/exit.c \
+	$(top_srcdir)/lib/hal_io.c \
+	$(top_srcdir)/lib/hal_uart.c \
+	$(top_srcdir)/lib/i2c.c \
+	$(top_srcdir)/lib/mdelay.c \
+	$(top_srcdir)/lib/memcpy_wa.c \
+	$(top_srcdir)/lib/memset_wa.c \
+	$(top_srcdir)/lib/nonstdio.c \
+	$(top_srcdir)/lib/pic.c \
+	$(top_srcdir)/lib/print_mac_addr.c \
+	$(top_srcdir)/lib/print_rmon_regs.c \
+	$(top_srcdir)/lib/print_buffer.c \
+	$(top_srcdir)/lib/printf.c \
+	$(top_srcdir)/lib/spi.c \
+	$(top_srcdir)/lib/net_common.c \
+	$(top_srcdir)/lib/arp_cache.c \
+	$(top_srcdir)/lib/banal.c
diff --git a/firmware/microblaze/lib/clock_bits.h b/firmware/microblaze/lib/clock_bits.h
new file mode 100644
index 000000000..d2052e941
--- /dev/null
+++ b/firmware/microblaze/lib/clock_bits.h
@@ -0,0 +1,55 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP2_CLOCK_BITS_H
+#define INCLUDED_USRP2_CLOCK_BITS_H
+
+#define	_MC_WE_LOCK			0x0001
+#define	_MC_MIMO_CLK_INPUT		0x0002		// else SMA input
+
+/*
+ * Derived masks (use these):
+ *
+ * We get our input from 1 of three places:
+ *  Our free running oscilator, our SMA connector, or from the MIMO connector
+ */
+#define	MC_WE_DONT_LOCK			0x0000
+#define	MC_WE_LOCK_TO_SMA		(_MC_WE_LOCK | 0)
+#define	MC_WE_LOCK_TO_MIMO		(_MC_WE_LOCK | _MC_MIMO_CLK_INPUT)
+
+/*
+ * Independent of the source of the clock, we may or may not drive our
+ * clock onto the mimo connector.  Note that there are dedicated clock
+ * signals in each direction, so disaster doesn't occurs if we're
+ * unnecessarily providing clock.
+ */
+#define	MC_PROVIDE_CLK_TO_MIMO		0x0004
+
+#define MC_REF_CLK_MASK          0x0f
+
+#define MC_PPS_SOURCE_SMA        (0x00 << 4)
+#define MC_PPS_SOURCE_MIMO       (0x01 << 4)
+
+#define MC_PPS_POLARITY_NEG      (0x00 << 5)
+#define MC_PPS_POLARITY_POS      (0x01 << 5)
+
+#endif /* INCLUDED_USRP2_CLOCK_BITS_H */
diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c
index ccc4a7cc7..2b352a385 100644
--- a/firmware/microblaze/lib/clocks.c
+++ b/firmware/microblaze/lib/clocks.c
@@ -25,40 +25,60 @@
 #include "ad9510.h"
 #include "spi.h"
 #include "u2_init.h"
-#include "nonstdio.h"
+
+//USRP2PLUS clocks:
+//Clock 0: testclk
+//Clock 1: FPGA clk
+//Clock 2: ADC clk
+//Clock 3: DAC clk
+//Clock 4: SER clk
+//Clock 5: TX dboard clk
+//Clock 6: EXP clk
+//Clock 7: RX dboard clk
+
+//TODO: should have enough brains to init the FPGA clock for USRP2+. all others are suspect.
+//note that without EEPROM support u2_hw_rev_major is going to be incorrect.
 
 void 
 clocks_init(void)
 {
   // Set up basic clocking functions in AD9510
-  ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution
+  ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution
 
+  //enable the 100MHz clock output to the FPGA for 50MHz CPU clock
   clocks_enable_fpga_clk(true, 1);
 
   spi_wait();
 
   // Set up PLL for 10 MHz reference
   // Reg 4, A counter, Don't Care
-  ad9510_write_reg(0x05, 0x00);  // Reg 5, B counter MSBs, 0
-  ad9510_write_reg(0x06, 0x05);  // Reg 6, B counter LSBs, 5
+//  ad9510_write_reg(0x05, 0x00);  // Reg 5, B counter MSBs, 0
+//  ad9510_write_reg(0x06, 0x05);  // Reg 6, B counter LSBs, 5
   // Reg 7, Loss of reference detect, doesn't work yet, 0
-  ad9510_write_reg(0x5A, 0x01); // Update Regs
+//  ad9510_write_reg(0x5A, 0x01); // Update Regs
 
   // Primary clock configuration
-  clocks_mimo_config(MC_WE_DONT_LOCK);
+//  clocks_mimo_config(MC_WE_DONT_LOCK);
+
+
+  //wait for the clock to stabilize
+  while(!clocks_lock_detect());
+
+  //issue a reset to the DCM so it locks up to the new freq
+  output_regs->clk_ctrl |= CLK_RESET;
 
   // Set up other clocks
   //clocks_enable_test_clk(false, 0);
   //clocks_enable_tx_dboard(false, 0);
   //clocks_enable_rx_dboard(false, 0);
-  clocks_enable_eth_phyclk(false, 0);
+//  clocks_enable_eth_phyclk(false, 0); //PHY clk is separate now (u2r4, u2p)
 
   // Enable clock to ADCs and DACs
   //clocks_enable_dac_clk(true, 1);
   //clocks_enable_adc_clk(true, 1);
 }
 
-
+/*
 void
 clocks_mimo_config(int flags)
 {
@@ -86,7 +106,7 @@ clocks_mimo_config(int flags)
   spi_wait();
   
   // Allow for clock switchover
-  
+  // The below masks include 0x10, which issues a reset to the DCM.  
   if (flags & _MC_WE_LOCK){		// WE LOCK
     if (flags & _MC_MIMO_CLK_INPUT) {
       // Turn on ref output and choose the MIMO connector
@@ -103,18 +123,17 @@ clocks_mimo_config(int flags)
   }
 
   // Do we drive a clock onto the MIMO connector?
-  if (flags & MC_PROVIDE_CLK_TO_MIMO)
-    clocks_enable_clkexp_out(true,10);
-  else
-    clocks_enable_clkexp_out(false,0); 
+//  if (flags & MC_PROVIDE_CLK_TO_MIMO)
+//    clocks_enable_clkexp_out(true,10);
+//  else
+//    clocks_enable_clkexp_out(false,0); 
 }
+*/
 
 bool 
 clocks_lock_detect()
 {
-  if(pic_regs->pending & PIC_CLKSTATUS)
-    return true;
-  return false;
+    return (pic_regs->pending & PIC_CLKSTATUS);
 }
 
 int inline
@@ -136,21 +155,23 @@ clocks_gen_div(int divisor)
 #define CLOCK_MODE_LVDS 2
 #define CLOCK_MODE_CMOS 3
 
+//CHANGED: set to PECL for default behavior
 void 
 clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode)
 {
   int enable_word, div_word, div_en_word;
 
   switch(mode) {
-  case CLOCK_MODE_PECL :
-    enable_word = enable ? 0x08 : 0x0A;
-    break;
   case CLOCK_MODE_LVDS :
     enable_word = enable ? 0x02 : 0x03;
     break;
   case CLOCK_MODE_CMOS :
     enable_word = enable ? 0x08 : 0x09;
     break;
+  case CLOCK_MODE_PECL :
+	default:
+    enable_word = enable ? 0x08 : 0x0A;
+    break;
   }
   if(enable && (divisor>1)) {
     div_word = clocks_gen_div(divisor);
@@ -180,8 +201,8 @@ clocks_enable_fpga_clk(bool enable, int divisor)
 {
   clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL);
 }
-
-// Clock 2 on Rev 3, Clock 5 on Rev 4
+/*
+// Clock 2 on Rev 3, Clock 5 on Rev 4, Clock 6 on USRP2+
 void
 clocks_enable_clkexp_out(bool enable, int divisor)
 {
@@ -192,13 +213,19 @@ clocks_enable_clkexp_out(bool enable, int divisor)
     ad9510_write_reg(0x35,0x00);  // Set Full Scale to nearly 10ns
     ad9510_write_reg(0x36,0x1c);  // Set fine delay.  0x20 is midscale
     clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS);
-    
   }
+	else if(u2_hw_rev_major == 10) {
+		ad9510_write_reg(0x34, 0x00);
+		ad9510_write_reg(0x35, 0x00);
+		ad9510_write_reg(0x36, 0x1C);
+		clocks_enable_XXX_clk(enable, divisor, 0x42, 0x52, CLOCK_MODE_LVDS);
+	}
   else
-    putstr("ERR: Invalid Rev\n");
+    putstr("ERR (clocks_enable_clkexp_out): Invalid hw rev, don't know what to do!\n");
 }
-
-// Clock 5 on Rev 3, none (was 2) on Rev 4
+*/
+/*
+// Clock 5 on Rev 3, none (was 2) on Rev 4, none on USRP2+
 void
 clocks_enable_eth_phyclk(bool enable, int divisor)
 {
@@ -207,9 +234,9 @@ clocks_enable_eth_phyclk(bool enable, int divisor)
   else if(u2_hw_rev_major == 4)
     clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL);
   else
-    putstr("ERR: Invalid Rev\n");
+    putstr("(clocks_enable_eth_phyclk): no eth PHY clock or invalid hw rev\n"); //not really an error
 }
-
+*/
 // Clock 3
 /*void
 clocks_enable_dac_clk(bool enable, int divisor)
diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h
index 43d5a05c2..28d1d542f 100644
--- a/firmware/microblaze/lib/clocks.h
+++ b/firmware/microblaze/lib/clocks.h
@@ -26,7 +26,7 @@
  */
 
 #include <stdbool.h>
-#include <usrp2_clock_bits.h>
+#include "clock_bits.h"
 
 
 /*!
@@ -43,7 +43,7 @@ void clocks_init(void);
  * Configure our master clock source, and whether or not we drive a
  * clock onto the mimo connector.  See MC_flags in usrp2_mimo_config.h.
  */
-void clocks_mimo_config(int flags);
+//void clocks_mimo_config(int flags);
 
 /*!
  * \brief Lock Detect -- Return True if our PLL is locked
@@ -63,12 +63,12 @@ void clocks_enable_fpga_clk(bool enable, int divisor);
 /*!
  * \brief Enable or disable clock output sent to MIMO connector
  */
-void clocks_enable_clkexp_out(bool enable, int divisor);
+//void clocks_enable_clkexp_out(bool enable, int divisor);
 
 /*!
  * \brief Enable or disable ethernet phyclk, should always be disabled
  */
-void clocks_enable_eth_phyclk(bool enable, int divisor);
+//void clocks_enable_eth_phyclk(bool enable, int divisor);
 
 /*!
  * \brief Enable or disable clock to DAC
diff --git a/firmware/microblaze/lib/compiler.h b/firmware/microblaze/lib/compiler.h
new file mode 100644
index 000000000..4fa9b49f8
--- /dev/null
+++ b/firmware/microblaze/lib/compiler.h
@@ -0,0 +1,25 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_COMPILER_H
+#define INCLUDED_COMPILER_H
+
+// FIXME gcc specific.
+#define _AL4   __attribute__((aligned (4)))
+
+
+#endif /* INCLUDED_COMPILER_H */
diff --git a/firmware/microblaze/lib/eth_mac.c b/firmware/microblaze/lib/eth_mac.c
index 375d3f4d4..034a4d494 100644
--- a/firmware/microblaze/lib/eth_mac.c
+++ b/firmware/microblaze/lib/eth_mac.c
@@ -83,14 +83,6 @@ eth_mac_read_rmon(int addr)
 int
 eth_mac_miim_read(int addr)
 {
-  if (hwconfig_simulation_p()){
-    switch(addr){
-    case PHY_LINK_AN:
-      return LANSR_MASTER | LANSR_LINK_GOOD | LANSR_SPEED_1000;
-    default:
-      return 0;
-    }
-  }
 
   int phy_addr = PHY_ADDR;
   eth_mac->miiaddress = ((addr & 0x1f) << 8) | phy_addr;
@@ -112,7 +104,7 @@ eth_mac_miim_write(int addr, int value)
   eth_mac->miitx_data = value;
   eth_mac->miicommand = MIIC_WCTRLDATA;
 
-  //printf("MIIM-WRITE ADDR 0x%x VAL 0x%x\n",addr,value);
+//  printf("MIIM-WRITE ADDR 0x%x VAL 0x%x\n",addr,value);
   while((eth_mac->miistatus & MIIS_BUSY) != 0)
     ;
 }
diff --git a/firmware/microblaze/lib/eth_phy.h b/firmware/microblaze/lib/eth_phy.h
deleted file mode 100644
index 6c16f97b7..000000000
--- a/firmware/microblaze/lib/eth_phy.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Much of this was extracted from the Linux e1000_hw.h file */
-
-#ifndef INCLUDED_ETH_PHY_H
-#define INCLUDED_ETH_PHY_H
-
-/* PHY 1000 MII Register/Bit Definitions */
-/* PHY Registers defined by IEEE */
-
-#define PHY_CTRL         0x00 /* Control Register */
-#define PHY_STATUS       0x01 /* Status Regiser */
-#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
-#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
-#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
-#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
-#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
-
-/* PHY 1000 MII Register additions in DP83856 */
-/* The part implements 0x00 thru 0x1f; we use these. */
-
-#define	PHY_LINK_AN	 0x11 /* Link and Auto Negotiation Status Reg */
-#define PHY_INT_STATUS	 0x14 /* Interupt Status Reg (RO) */
-#define PHY_INT_MASK	 0x15 /* Interrupt Mask Reg  (RW) */
-#define PHY_INT_CLEAR    0x17 /* Interrupt Clear Reg (RW) */
-
-
-/* Bit definitions for some of the registers above */
-
-/* PHY Control Register (PHY_CTRL) */
-#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
-#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
-#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN       0x0800  /* Power down */
-#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
-
-/* PHY Status Register (PHY_STATUS) */
-#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
-#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
-
-/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */
-#define NWAY_AR_SELECTOR_FIELD 0x0001   /* indicates IEEE 802.3 CSMA/CD */
-#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS  0x0080   /* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS  0x0100   /* 100TX Full Duplex Capable */
-#define NWAY_AR_100T4_CAPS     0x0200   /* 100T4 Capable */
-#define NWAY_AR_PAUSE          0x0400   /* Pause operation desired */
-#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction bit */
-#define NWAY_AR_REMOTE_FAULT   0x2000   /* Remote Fault detected */
-#define NWAY_AR_NEXT_PAGE      0x8000   /* Next Page ability supported */
-
-/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */
-#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
-#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
-#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
-#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
-#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
-#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
-#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
-#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
-#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
-#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
-
-/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */
-#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
-#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
-#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
-#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
-#define NWAY_ER_PAR_DETECT_FAULT  0x0010 /* LP is 100TX Full Duplex Capable */
-
-/* Next Page TX Register (PHY_NEXT_PAGE_TX) */
-#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define NPTX_TOGGLE         0x0800 /* Toggles between exchanges
-                                    * of different NP
-                                    */
-#define NPTX_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
-                                    * 0 = cannot comply with msg
-                                    */
-#define NPTX_MSG_PAGE       0x2000 /* formatted(1)/unformatted(0) pg */
-#define NPTX_NEXT_PAGE      0x8000 /* 1 = addition NP will follow
-                                    * 0 = sending last NP
-                                    */
-
-/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */
-#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define LP_RNPR_TOGGLE         0x0800 /* Toggles between exchanges
-                                       * of different NP
-                                       */
-#define LP_RNPR_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
-                                       * 0 = cannot comply with msg
-                                       */
-#define LP_RNPR_MSG_PAGE       0x2000  /* formatted(1)/unformatted(0) pg */
-#define LP_RNPR_ACKNOWLDGE     0x4000  /* 1 = ACK / 0 = NO ACK */
-#define LP_RNPR_NEXT_PAGE      0x8000  /* 1 = addition NP will follow
-                                        * 0 = sending last NP
-                                        */
-
-/* 1000BASE-T Control Register (PHY_1000T_CTRL) */
-#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
-#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
-#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
-                                        /* 0=DTE device */
-#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
-                                        /* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
-                                        /* 0=Automatic Master/Slave config */
-#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
-#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
-#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
-#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
-#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
-
-/* 1000BASE-T Status Register (PHY_1000T_STATUS) */
-#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
-#define SR_1000T_ASYM_PAUSE_DIR   0x0100 /* LP asymmetric pause direction bit */
-#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
-#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
-#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
-#define SR_1000T_REMOTE_RX_STATUS_SHIFT          12
-#define SR_1000T_LOCAL_RX_STATUS_SHIFT           13
-#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT    5
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_20            20
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_100           100
-
-/* Extended Status Register (PHY_EXT_STATUS) */
-#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
-#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
-#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
-#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
-
-#define PHY_TX_POLARITY_MASK   0x0100 /* register 10h bit 8 (polarity bit) */
-#define PHY_TX_NORMAL_POLARITY 0      /* register 10h bit 8 (normal polarity) */
-
-#define AUTO_POLARITY_DISABLE  0x0010 /* register 11h bit 4 */
-                                      /* (0=enable, 1=disable) */
-
-/* Link and Auto Negotiation Status Reg (PHY_LINK_AN) [READ-ONLY] */
-#define	LANSR_MASTER           0x0001 /* 1=PHY is currently in master mode */
-#define	LANSR_FULL_DUPLEX      0x0002 /* 1=PHY is currently full duplex */
-#define LANSR_LINK_GOOD        0x0004 /* 1=a good link is established */
-#define LANSR_SPEED_MASK       0x0018
-#define	  LANSR_SPEED_10       0x0000 /*   10Mb/s */
-#define	  LANSR_SPEED_100      0x0008 /*  100Mb/s */
-#define	  LANSR_SPEED_1000     0x0010 /* 1000Mb/s */
-#define	  LANSR_SPEED_RSRVD    0x0018 /* reserved */
-#define LANSR_NON_COMP_MODE    0x0020 /* 1=detects only in non-compliant mode */
-#define	LANSR_DEEP_LOOPBACK    0x0040 /* 1=the PHY operates in deep loopback mode */
-#define	LANSR_SHALLOW_LOOPBACK 0x0080 /* 1=the PHY operates in shallow loopback mode */
-#define LANSR_RSRVD_8	       0x0100 /* reserved */
-#define LANSR_FIFO_ERR	       0x0200 /* 1=FIFO error occurred */
-#define	LANSR_MDIX_XOVER       0x0400 /* 1=PHY's MDI is in cross-over mode */
-#define	LANSR_RSRVD_11	       0x0800 /* resevered */
-#define	LANSR_TP_POLARITY_REV  0xf000 /* Twisted pair polarity status A:D([15:12]) 1=reversed */
-
-/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */
-#define	PHY_INT_RSRVD_0	       0x0001 /* reserved */
-#define	PHY_INT_RSRVD_1	       0x0002 /* reserved */
-#define	PHY_INT_RSRVD_2	       0x0004 /* reserved */
-#define	PHY_INT_REM_FLT_CNG    0x0008 /* Remote Fault Changed */
-#define	PHY_INT_AN_CMPL	       0x0010 /* Auto-negotiation completion */
-#define	PHY_INT_NXT_PG_RCVD    0x0020 /* Next Page Received */
-#define PHY_INT_JABBER_CNG     0x0040 /* Jabber Changed */
-#define PHY_INT_NO_LINK	       0x0080 /* No link after auto-negotiation */
-#define PHY_INT_NO_HCD	       0x0100 /* AN couldn't determine highest common denominator */
-#define PHY_INT_MAS_SLA_ERR    0x0200 /* Master / Slave Error: couldn't resolve */
-#define PHY_INT_PRL_DET_FLT    0x0400 /* Parallel detection fault */
-#define PHY_INT_POL_CNG	       0x0800 /* Polarity of any channel changed */
-#define	PHY_INT_MDIX_CNG       0x1000 /* MDIX changed.  A pair swap occurred. */
-#define PHY_INT_DPLX_CNG       0x2000 /* Duplex changed */
-#define PHY_INT_LNK_CNG	       0x4000 /* Link changed (asserted when a link is established or broken) */
-#define PHY_INT_SPD_CNG	       0x8000 /* Speed changed */
-
-#endif /* INCLUDED_ETH_PHY_H */
diff --git a/firmware/microblaze/lib/ethernet.c b/firmware/microblaze/lib/ethernet.c
deleted file mode 100644
index 34a3ad7c1..000000000
--- a/firmware/microblaze/lib/ethernet.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ethernet.h"
-#include "memory_map.h"
-#include "eth_phy.h"
-#include "eth_mac.h"
-#include "eth_mac_regs.h"
-#include "pic.h"
-#include "hal_io.h"
-#include "nonstdio.h"
-#include <stdbool.h>
-#include "i2c.h"
-#include "usrp2_i2c_addr.h"
-
-
-#define VERBOSE 0
-
-static ethernet_t ed_state;
-static ethernet_link_changed_callback_t ed_callback = 0;
-
-void 
-ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback)
-{
-  ed_callback = new_callback;
-}
-
-
-static void
-ed_set_mac_speed(int speed)
-{
-  printf("Speed set to %d\n",speed);
-  /*
-  switch(speed){
-  case 10:
-    eth_mac->speed = 1;
-    break;
-  case 100:
-    eth_mac->speed = 2;
-    break;
-  case 1000:
-    eth_mac->speed = 4;
-    break;
-  default:
-    break;
-  }
-  */
-}
-
-static void
-ed_link_up(int speed)
-{
-  // putstr("ed_link_up: "); puthex16_nl(speed);
-
-  ed_set_mac_speed(speed);
-
-  if (ed_callback)		// fire link changed callback
-    (*ed_callback)(speed);
-}
-
-static void
-ed_link_down(void)
-{
-  // putstr("ed_link_down\n");
-
-  if (ed_callback)		// fire link changed callback
-    (*ed_callback)(0);
-}
-
-
-static void
-ed_link_speed_change(int speed)
-{
-  ed_link_down();
-  ed_link_up(speed);
-}
-
-static void
-print_flow_control(int flow_control)
-{
-  static const char *flow_control_msg[4] = {
-    "NONE", "WE_TX", "WE_RX", "SYMMETRIC"
-  };
-  putstr("ethernet flow control: ");
-  puts(flow_control_msg[flow_control & 0x3]);
-}
-
-static void
-check_flow_control_resolution(void)
-{
-  static const unsigned char table[16] = {
-    // index = {local_asm, local_pause, partner_asm, partner_pause}
-    FC_NONE,  FC_NONE,  FC_NONE,  FC_NONE,
-    FC_NONE,  FC_SYMM,  FC_NONE,  FC_SYMM,
-    FC_NONE,  FC_NONE,  FC_NONE,  FC_WE_TX,
-    FC_NONE,  FC_SYMM,  FC_WE_RX, FC_SYMM
-  };
-
-  int us = eth_mac_miim_read(PHY_AUTONEG_ADV);
-  int lp = eth_mac_miim_read(PHY_LP_ABILITY);
-  int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3);
-  ed_state.flow_control = table[index];
-
-  if (1)
-    print_flow_control(ed_state.flow_control);
-}
-
-/*
- * Read the PHY state register to determine link state and speed
- */
-static void
-ed_check_phy_state(void)
-{
-  int lansr = eth_mac_miim_read(PHY_LINK_AN);
-  eth_link_state_t new_state = LS_UNKNOWN;
-  int new_speed = S_UNKNOWN;
-
-  if (VERBOSE){
-    putstr("LANSR: ");
-    puthex16_nl(lansr);
-  }
-
-  if (lansr & LANSR_LINK_GOOD){		// link's up
-    if (VERBOSE)
-      puts("  LINK_GOOD");
-
-    new_state = LS_UP;
-    switch (lansr & LANSR_SPEED_MASK){
-    case LANSR_SPEED_10:
-      new_speed = 10;
-      break;
-      
-    case LANSR_SPEED_100:
-      new_speed = 100;
-      break;
-      
-    case LANSR_SPEED_1000:
-      new_speed = 1000;
-      break;
-
-    default:
-      new_speed = S_UNKNOWN;
-      break;
-    }
-
-    check_flow_control_resolution();
-  }
-  else {				// link's down
-    if (VERBOSE)
-      puts("  NOT LINK_GOOD");
-    
-    new_state = LS_DOWN;
-    new_speed = S_UNKNOWN;
-  }
-
-  if (new_state != ed_state.link_state){
-    ed_state.link_state = new_state;		// remember new state
-    if (new_state == LS_UP)
-      ed_link_up(new_speed);
-    else if (new_state == LS_DOWN)
-      ed_link_down();
-  }
-  else if (new_state == LS_UP && new_speed != ed_state.link_speed){
-    ed_state.link_speed = new_speed;		// remember new speed
-    ed_link_speed_change(new_speed);
-  }
-}
-
-/*
- * This is fired when the ethernet PHY state changes
- */
-static void
-eth_phy_irq_handler(unsigned irq)
-{
-  ed_check_phy_state();
-  eth_mac_miim_write(PHY_INT_CLEAR, ~0);	// clear all ints
-}
-
-void
-ethernet_init(void)
-{
-  eth_mac_init(ethernet_mac_addr());
-
-  ed_state.link_state = LS_UNKNOWN;
-  ed_state.link_speed = S_UNKNOWN;
-
-  // initialize MAC registers
-  //  eth_mac->tx_hwmark = 0x1e;
-  //eth_mac->tx_lwmark = 0x19;
-
-  //eth_mac->crc_chk_en = 1;
-  //eth_mac->rx_max_length = 2048;
-
-  // configure PAUSE frame stuff
-  //eth_mac->tx_pause_en = 1;		// pay attn to pause frames sent to us
-
-  //eth_mac->pause_quanta_set = 38;	// a bit more than 1 max frame 16kb/512 + fudge
-  //eth_mac->pause_frame_send_en = 1;	// enable sending pause frames
-
-
-  // setup PHY to interrupt on changes
-
-  unsigned mask =
-    (PHY_INT_AN_CMPL		// auto-neg completed
-     | PHY_INT_NO_LINK		// no link after auto-neg
-     | PHY_INT_NO_HCD		// no highest common denominator
-     | PHY_INT_MAS_SLA_ERR	// couldn't resolve master/slave 
-     | PHY_INT_PRL_DET_FLT	// parallel detection fault
-     | PHY_INT_LNK_CNG		// link established or broken
-     | PHY_INT_SPD_CNG		// speed changed
-     );
-
-  eth_mac_miim_write(PHY_INT_CLEAR, ~0);	// clear all pending interrupts
-  eth_mac_miim_write(PHY_INT_MASK, mask);	// enable the ones we want
-
-  pic_register_handler(IRQ_PHY, eth_phy_irq_handler);
-
-  // Advertise our flow control configuation.
-  //
-  // We and the link partner each specify two bits in the base page
-  // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR.
-  // The bits say what a device is "willing" to do, not what may actually
-  // happen as a result of the negotiation.  There are 4 cases:
-  //
-  // PAUSE  ASM_DIR
-  //
-  //  0        0        I have no flow control capability.
-  //
-  //  1        0        I both assert and respond to flow control.
-  //
-  //  0        1        I assert flow control, but cannot respond.  That is,
-  //                    I want to be able to send PAUSE frames, but will ignore any
-  //		 	you send to me.  (This is our configuration.)
-  //
-  //  1        1        I can both assert and respond to flow control AND I am willing
-  //                    to operate symmetrically OR asymmetrically in EITHER direction.
-  //                    (We hope the link partner advertises this, otherwise we don't
-  //			get what we want.)
-
-  int t = eth_mac_miim_read(PHY_AUTONEG_ADV);
-  t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR);
-  t |= NWAY_AR_ASM_DIR;
-
-  // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex
-  t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS);
-
-  eth_mac_miim_write(PHY_AUTONEG_ADV, t);
-  int r = eth_mac_miim_read(PHY_AUTONEG_ADV);  		// DEBUG, read back
-  if (t != r){
-    printf("PHY_AUTONEG_ADV: wrote 0x%x, got 0x%x\n", t, r);
-  }
-
-  // Restart autonegotation.  
-  // We want to ensure that we're advertising our PAUSE capabilities.
-  t = eth_mac_miim_read(PHY_CTRL);
-  eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG);
-}
-
-static bool 
-unprogrammed(const void *t, size_t len)
-{
-  int i;
-  uint8_t *p = (uint8_t *)t;
-  bool all_zeros = true;
-  bool all_ones =  true;
-  for (i = 0; i < len; i++){
-    all_zeros &= p[i] == 0x00;
-    all_ones  &= p[i] == 0xff;
-  }
-  return all_ones | all_zeros;
-}
-
-//////////////////// MAC Addr Stuff ///////////////////////
-
-static int8_t src_mac_addr_initialized = false;
-static eth_mac_addr_t src_mac_addr = {{
-    0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff
-  }};
-
-const eth_mac_addr_t *
-ethernet_mac_addr(void)
-{
-  if (!src_mac_addr_initialized){    // fetch from eeprom
-    src_mac_addr_initialized = true;
-
-    // if we're simulating, don't read the EEPROM model, it's REALLY slow
-    if (hwconfig_simulation_p())
-      return &src_mac_addr;
-    
-    eth_mac_addr_t tmp;
-    bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, &tmp, sizeof(tmp));
-    if (!ok || unprogrammed(&tmp, sizeof(tmp))){
-      // use the default
-    }
-    else
-      src_mac_addr = tmp;
-  }
-
-  return &src_mac_addr;
-}
-
-bool
-ethernet_set_mac_addr(const eth_mac_addr_t *t)
-{
-  bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t));
-  if (ok){
-    src_mac_addr = *t;
-    src_mac_addr_initialized = true;
-    //eth_mac_set_addr(t); //this breaks the link
-  }
-
-  return ok;
-}
-
-//////////////////// IP Addr Stuff ///////////////////////
-
-static int8_t src_ip_addr_initialized = false;
-static struct ip_addr src_ip_addr = {
-    (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)
-};
-
-
-const struct ip_addr *get_ip_addr(void)
-{
-  if (!src_ip_addr_initialized){    // fetch from eeprom
-    src_ip_addr_initialized = true;
-
-    // if we're simulating, don't read the EEPROM model, it's REALLY slow
-    if (hwconfig_simulation_p())
-      return &src_ip_addr;
-    
-    struct ip_addr tmp;
-    bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, &tmp, sizeof(tmp));
-    if (!ok || unprogrammed(&tmp, sizeof(tmp))){
-      // use the default
-    }
-    else
-      src_ip_addr = tmp;
-  }
-
-  return &src_ip_addr;
-}
-
-bool set_ip_addr(const struct ip_addr *t){
-  bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, t, sizeof(struct ip_addr));
-  if (ok){
-    src_ip_addr = *t;
-    src_ip_addr_initialized = true;
-  }
-
-  return ok;
-}
-
-int
-ethernet_check_errors(void)
-{
-  // these registers are reset when read
-  
-  int	r = 0;
-  /*
-  if (eth_mac_read_rmon(0x05) != 0)
-    r |= RME_RX_CRC;
-  if (eth_mac_read_rmon(0x06) != 0)
-    r |= RME_RX_FIFO_FULL;
-  if (eth_mac_read_rmon(0x07) != 0)
-    r |= RME_RX_2SHORT_2LONG;
-  
-  if (eth_mac_read_rmon(0x25) != 0)
-    r |= RME_TX_JAM_DROP;
-  if (eth_mac_read_rmon(0x26) != 0)
-    r |= RME_TX_FIFO_UNDER;
-  if (eth_mac_read_rmon(0x27) != 0)
-    r |= RME_TX_FIFO_OVER;
-  */
-  return r;
-}
diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c
index 0afd6a2cc..58b1e681e 100644
--- a/firmware/microblaze/lib/hal_io.c
+++ b/firmware/microblaze/lib/hal_io.c
@@ -193,3 +193,13 @@ puts(const char *s)
   putchar('\n');
   return 0;
 }
+
+char *
+gets(char * const s)
+{
+	char *x = s;
+	while((*x=(char)hal_uart_getc()) != '\n') x++;
+	*x = 0;
+	return s;
+}
+
diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h
index d8967f063..c67d96c62 100644
--- a/firmware/microblaze/lib/hal_io.h
+++ b/firmware/microblaze/lib/hal_io.h
@@ -23,6 +23,7 @@
 
 void hal_io_init(void);
 void hal_finish();
+char *gets(char * const s);
 
 /*
  * ------------------------------------------------------------------------
diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c
index 75b12b432..fe3b7515a 100644
--- a/firmware/microblaze/lib/hal_uart.c
+++ b/firmware/microblaze/lib/hal_uart.c
@@ -39,16 +39,25 @@ divisor_table[MAX_WB_DIV+1][NSPEEDS] = {
 
 #define u uart_regs
 
+static char uart_mode = UART_MODE_ONLCR;
+
+void
+hal_uart_set_mode(int mode)
+{
+  uart_mode = mode;
+}
+
 void
 hal_uart_init(void)
 {
+	hal_uart_set_mode(UART_MODE_ONLCR);
   u->clkdiv = 217;  // 230400 bps
 }
 
 void
 hal_uart_putc(int ch)
 {
-  if (ch == '\n')		// FIXME for now map \n -> \r\n
+  if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR))		//map \n->\r\n if necessary
     hal_uart_putc('\r');
 
   while (u->txlevel == 0)	 // wait for fifo to have space
@@ -60,7 +69,7 @@ hal_uart_putc(int ch)
 void
 hal_uart_putc_nowait(int ch)
 {
-  if (ch == '\n')		// FIXME for now map \n -> \r\n
+  if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR))		//map \n->\r\n if necessary
     hal_uart_putc('\r');
 
   if(u->txlevel)   // If fifo has space
diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h
index 2ddfa6259..dfd73c323 100644
--- a/firmware/microblaze/lib/hal_uart.h
+++ b/firmware/microblaze/lib/hal_uart.h
@@ -19,6 +19,16 @@
 #ifndef INCLUDED_HAL_UART_H
 #define INCLUDED_HAL_UART_H
 
+/*!
+ * \brief uart mode flags
+ */
+#define	UART_MODE_RAW		0x0000	// no mapping on input or output
+#define	UART_MODE_ONLCR	0x0001	// map \n to \r\n on output (default)
+
+/*
+ * \brief Set uart mode
+ */
+void hal_uart_set_mode(int flags);
 
 /*!
  * \brief one-time call to init
diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h
deleted file mode 100644
index cdf3dd338..000000000
--- a/firmware/microblaze/lib/memory_map.h
+++ /dev/null
@@ -1,792 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Overall Memory Map
- *   0000-7FFF  32K   RAM space (16K on 1500, 24K on 2000, 32K on DSP)
- *   8000-BFFF  16K   Buffer Pool
- *   C000-FFFF  16K   Peripherals
- */
-
-
-#ifndef INCLUDED_MEMORY_MAP_H
-#define INCLUDED_MEMORY_MAP_H
-
-#include <stdint.h>
-
-
-#define MASTER_CLK_RATE        100000000		// 100 MHz
-
-
-////////////////////////////////////////////////////////////////
-//
-//         Memory map for embedded wishbone bus
-//
-////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////
-// Main RAM, Slave 0
-
-#define RAM_BASE 0x0000
-
-////////////////////////////////////////////////////////////////
-// Buffer Pool RAM, Slave 1
-//
-// The buffers themselves are located in Slave 1, Buffer Pool RAM.
-// The status registers are in Slave 5, Buffer Pool Status.
-// The control register is in Slave 7, Settings Bus.
-
-#define BUFFER_POOL_RAM_BASE 0x8000
-
-#define	NBUFFERS                8
-#define BP_NLINES	   0x0200	// number of 32-bit lines in a buffer
-#define BP_LAST_LINE	(BP_NLINES - 1)	// last line in a buffer
-
-#define buffer_pool_ram \
-  ((uint32_t *) BUFFER_POOL_RAM_BASE)
-
-#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES])
-
-
-/////////////////////////////////////////////////////
-// SPI Core, Slave 2.  See core docs for more info
-#define SPI_BASE 0xC000   // Base address (16-bit)
-
-typedef struct {
-  volatile uint32_t	txrx0;
-  volatile uint32_t	txrx1;
-  volatile uint32_t	txrx2;
-  volatile uint32_t	txrx3;
-  volatile uint32_t	ctrl;
-  volatile uint32_t	div;
-  volatile uint32_t	ss;
-} spi_regs_t;
-
-#define spi_regs ((spi_regs_t *) SPI_BASE)
-
-
-// Masks for controlling different peripherals
-#define SPI_SS_AD9510    1
-#define SPI_SS_AD9777    2
-#define SPI_SS_RX_DAC    4
-#define SPI_SS_RX_ADC    8
-#define SPI_SS_RX_DB    16
-#define SPI_SS_TX_DAC   32
-#define SPI_SS_TX_ADC   64
-#define SPI_SS_TX_DB   128
-
-// Masks for different parts of CTRL reg
-#define SPI_CTRL_ASS      (1<<13)
-#define SPI_CTRL_IE       (1<<12)
-#define SPI_CTRL_LSB      (1<<11)
-#define SPI_CTRL_TXNEG    (1<<10)
-#define SPI_CTRL_RXNEG    (1<< 9)
-#define SPI_CTRL_GO_BSY   (1<< 8)
-#define SPI_CTRL_CHAR_LEN_MASK 0x7F
-
-////////////////////////////////////////////////
-// I2C, Slave 3
-// See Wishbone I2C-Master Core Specification.
-
-#define I2C_BASE 0xC400
-
-typedef struct {
-  volatile uint32_t  prescaler_lo;	// r/w
-  volatile uint32_t  prescaler_hi;	// r/w
-  volatile uint32_t  ctrl;		// r/w
-  volatile uint32_t  data;		// wr = transmit reg; rd = receive reg
-  volatile uint32_t  cmd_status;	// wr = command reg;  rd = status reg
-} i2c_regs_t;
-
-#define i2c_regs ((i2c_regs_t *) I2C_BASE)
-
-#define	I2C_CTRL_EN	(1 << 7)	// core enable
-#define	I2C_CTRL_IE	(1 << 6)	// interrupt enable
-
-//
-// STA, STO, RD, WR, and IACK bits are cleared automatically
-//
-#define	I2C_CMD_START	(1 << 7)	// generate (repeated) start condition
-#define I2C_CMD_STOP	(1 << 6)	// generate stop condition
-#define	I2C_CMD_RD	(1 << 5)	// read from slave
-#define I2C_CMD_WR	(1 << 4)	// write to slave
-#define	I2C_CMD_NACK	(1 << 3)	// when a rcvr, send ACK (ACK=0) or NACK (ACK=1)
-#define I2C_CMD_RSVD_2	(1 << 2)	// reserved
-#define	I2C_CMD_RSVD_1	(1 << 1)	// reserved
-#define I2C_CMD_IACK	(1 << 0)	// set to clear pending interrupt
-
-#define I2C_ST_RXACK	(1 << 7)	// Received acknowledgement from slave (1 = NAK, 0 = ACK)
-#define	I2C_ST_BUSY	(1 << 6)	// 1 after START signal detected; 0 after STOP signal detected
-#define	I2C_ST_AL	(1 << 5)	// Arbitration lost.  1 when core lost arbitration
-#define	I2C_ST_RSVD_4	(1 << 4)	// reserved
-#define	I2C_ST_RSVD_3	(1 << 3)	// reserved
-#define	I2C_ST_RSVD_2	(1 << 2)	// reserved
-#define I2C_ST_TIP	(1 << 1)	// Transfer-in-progress
-#define	I2C_ST_IP	(1 << 0)	// Interrupt pending
-
-
-////////////////////////////////////////////////
-// GPIO, Slave 4
-//
-// These go to the daughterboard i/o pins
-
-#define GPIO_BASE 0xC800
-
-typedef struct {
-  volatile uint32_t	io;	  // tx data in high 16, rx in low 16
-  volatile uint32_t     ddr;      // 32 bits, 1 means output. tx in high 16, rx in low 16
-  volatile uint32_t	tx_sel;   // 16 2-bit fields select which source goes to TX DB
-  volatile uint32_t	rx_sel;   // 16 2-bit fields select which source goes to RX DB
-} gpio_regs_t;
-
-// each 2-bit sel field is layed out this way
-#define GPIO_SEL_SW	   0 // if pin is an output, set by software in the io reg
-#define	GPIO_SEL_ATR	   1 // if pin is an output, set by ATR logic
-#define	GPIO_SEL_DEBUG_0   2 // if pin is an output, debug lines from FPGA fabric
-#define	GPIO_SEL_DEBUG_1   3 // if pin is an output, debug lines from FPGA fabric
-
-#define gpio_base ((gpio_regs_t *) GPIO_BASE)
-
-///////////////////////////////////////////////////
-// Buffer Pool Status, Slave 5
-//
-// The buffers themselves are located in Slave 1, Buffer Pool RAM.
-// The status registers are in Slave 5, Buffer Pool Status.
-// The control register is in Slave 7, Settings Bus.
-
-#define BUFFER_POOL_STATUS_BASE 0xCC00
-
-typedef struct {
-  volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer
-  volatile uint32_t status;	         // error and done flags
-  volatile uint32_t hw_config;	         // see below
-  volatile uint32_t dummy[3];
-  volatile uint32_t irqs;
-  volatile uint32_t pri_enc_bp_status;
-  volatile uint32_t cycle_count;
-} buffer_pool_status_t;
-
-#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE)
-
-/*
- * Buffer n's xfer is done.
- * Clear this bit by issuing bp_clear_buf(n)
- */
-#define BPS_DONE(n)     (0x00000001 << (n))
-#define BPS_DONE_0	BPS_DONE(0)
-#define BPS_DONE_1	BPS_DONE(1)
-#define BPS_DONE_2	BPS_DONE(2)
-#define BPS_DONE_3	BPS_DONE(3)
-#define BPS_DONE_4	BPS_DONE(4)
-#define BPS_DONE_5	BPS_DONE(5)
-#define BPS_DONE_6	BPS_DONE(6)
-#define BPS_DONE_7	BPS_DONE(7)
-
-/*
- * Buffer n's xfer had an error.
- * Clear this bit by issuing bp_clear_buf(n)
- */
-#define BPS_ERROR(n)	(0x00000100 << (n))
-#define BPS_ERROR_0	BPS_ERROR(0)
-#define BPS_ERROR_1	BPS_ERROR(1)
-#define BPS_ERROR_2	BPS_ERROR(2)
-#define BPS_ERROR_3	BPS_ERROR(3)
-#define BPS_ERROR_4	BPS_ERROR(4)
-#define BPS_ERROR_5	BPS_ERROR(5)
-#define BPS_ERROR_6	BPS_ERROR(6)
-#define BPS_ERROR_7	BPS_ERROR(7)
-
-/*
- * Buffer n is idle.  A buffer is idle if it's not
- * DONE, ERROR, or processing a transaction.  If it's
- * IDLE, it's safe to start a new transaction.
- *
- * Clear this bit by starting a xfer with
- * bp_send_from_buf or bp_receive_to_buf.
- */
-#define BPS_IDLE(n)     (0x00010000 << (n))
-#define BPS_IDLE_0	BPS_IDLE(0)
-#define BPS_IDLE_1	BPS_IDLE(1)
-#define BPS_IDLE_2	BPS_IDLE(2)
-#define BPS_IDLE_3	BPS_IDLE(3)
-#define BPS_IDLE_4	BPS_IDLE(4)
-#define BPS_IDLE_5	BPS_IDLE(5)
-#define BPS_IDLE_6	BPS_IDLE(6)
-#define BPS_IDLE_7	BPS_IDLE(7)
-
-/*
- * Buffer n has a "slow path" packet in it.
- * This bit is orthogonal to the bits above and indicates that
- * the FPGA ethernet rx protocol engine has identified this packet
- * as one requiring firmware intervention.
- */
-#define BPS_SLOWPATH(n) (0x01000000 << (n))
-#define BPS_SLOWPATH_0	BPS_SLOWPATH(0)
-#define BPS_SLOWPATH_1	BPS_SLOWPATH(1)
-#define BPS_SLOWPATH_2	BPS_SLOWPATH(2)
-#define BPS_SLOWPATH_3	BPS_SLOWPATH(3)
-#define BPS_SLOWPATH_4	BPS_SLOWPATH(4)
-#define BPS_SLOWPATH_5	BPS_SLOWPATH(5)
-#define BPS_SLOWPATH_6	BPS_SLOWPATH(6)
-#define BPS_SLOWPATH_7	BPS_SLOWPATH(7)
-
-
-#define BPS_DONE_ALL	  0x000000ff	// mask of all dones
-#define BPS_ERROR_ALL	  0x0000ff00	// mask of all errors
-#define BPS_IDLE_ALL      0x00ff0000	// mask of all idles
-#define BPS_SLOWPATH_ALL  0xff000000	// mask of all slowpaths
-
-// The hw_config register
-
-#define	HWC_SIMULATION		0x80000000
-#define	HWC_WB_CLK_DIV_MASK	0x0000000f
-
-/*!
- * \brief return non-zero if we're running under the simulator
- */
-inline static int
-hwconfig_simulation_p(void)
-{
-  return buffer_pool_status->hw_config & HWC_SIMULATION;
-}
-
-/*!
- * \brief Return Wishbone Clock divisor.
- * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor.
- */
-inline static int
-hwconfig_wishbone_divisor(void)
-{
-  return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK;
-}
-
-///////////////////////////////////////////////////
-// Ethernet Core, Slave 6
-
-#define ETH_BASE 0xD000
-
-#include "eth_mac_regs.h"
-
-#define eth_mac ((eth_mac_regs_t *) ETH_BASE)
-
-////////////////////////////////////////////////////
-// Settings Bus, Slave #7, Not Byte Addressable!
-//
-// Output-only from processor point-of-view.
-// 1KB of address space (== 256 32-bit write-only regs)
-
-
-#define MISC_OUTPUT_BASE        0xD400
-#define	TX_PROTOCOL_ENGINE_BASE 0xD480
-#define	RX_PROTOCOL_ENGINE_BASE 0xD4C0
-#define BUFFER_POOL_CTRL_BASE   0xD500
-#define LAST_SETTING_REG        0xD7FC	// last valid setting register
-
-#define SR_MISC 0
-#define SR_TX_PROT_ENG 32
-#define SR_RX_PROT_ENG 48
-#define SR_BUFFER_POOL_CTRL 64
-#define SR_UDP_SM 96
-#define SR_TX_DSP 208
-#define SR_TX_CTRL 224
-#define SR_RX_DSP 160
-#define SR_RX_CTRL 176
-#define SR_TIME64 192
-#define SR_SIMTIMER 198
-#define SR_LAST 255
-
-#define	_SR_ADDR(sr)	(MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t))
-
-// --- buffer pool control regs ---
-
-typedef struct {
-  volatile uint32_t ctrl;
-} buffer_pool_ctrl_t;
-
-// buffer pool ports
-
-#define	PORT_SERDES	0	// serial/deserializer
-#define	PORT_DSP	1	// DSP tx or rx pipeline
-#define	PORT_ETH	2	// ethernet tx or rx
-#define	PORT_RAM	3	// RAM tx or rx
-
-// the buffer pool ctrl register fields
-
-#define BPC_BUFFER(n) (((n) & 0xf) << 28)
-#define   BPC_BUFFER_MASK      BPC_BUFFER(~0)
-#define   BPC_BUFFER_0	       BPC_BUFFER(0)
-#define   BPC_BUFFER_1	       BPC_BUFFER(1)
-#define   BPC_BUFFER_2	       BPC_BUFFER(2)
-#define   BPC_BUFFER_3	       BPC_BUFFER(3)
-#define   BPC_BUFFER_4	       BPC_BUFFER(4)
-#define   BPC_BUFFER_5	       BPC_BUFFER(5)
-#define   BPC_BUFFER_6	       BPC_BUFFER(6)
-#define   BPC_BUFFER_7	       BPC_BUFFER(7)
-#define	  BPC_BUFFER_NIL       BPC_BUFFER(0x8)	// disable
-
-#define BPC_PORT(n) (((n) & 0x7) << 25)
-#define   BPC_PORT_MASK        BPC_PORT(~0)
-#define   BPC_PORT_SERDES      BPC_PORT(PORT_SERDES)
-#define   BPC_PORT_DSP	       BPC_PORT(PORT_DSP)
-#define   BPC_PORT_ETH         BPC_PORT(PORT_ETH)
-#define   BPC_PORT_RAM         BPC_PORT(PORT_RAM)
-#define   BPC_PORT_NIL	       BPC_PORT(0x4)   	// disable
-
-#define	BPC_CLR	       	       (1 << 24)  // mutually excl commands
-#define	BPC_READ	       (1 << 23)
-#define BPC_WRITE              (1 << 22)
-
-#define BPC_STEP(step) (((step) & 0xf) << 18)
-#define   BPC_STEP_MASK	       BPC_STEP(~0)
-#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9)
-#define   BPC_LAST_LINE_MASK   BPC_LAST_LINE(~0)
-#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0)
-#define   BPC_FIRST_LINE_MASK  BPC_FIRST_LINE(~0)
-
-#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE)
-
-// --- misc outputs ---
-
-typedef struct {
-  volatile uint32_t	clk_ctrl;
-  volatile uint32_t	serdes_ctrl;
-  volatile uint32_t	adc_ctrl;
-  volatile uint32_t	leds;
-  volatile uint32_t	phy_ctrl;	// LSB is reset line to eth phy
-  volatile uint32_t	debug_mux_ctrl;
-  volatile uint32_t     ram_page;       // FIXME should go somewhere else...
-  volatile uint32_t     flush_icache;   // Flush the icache
-  volatile uint32_t     led_src;        // HW or SW control for LEDs
-} output_regs_t;
-
-#define SERDES_ENABLE 8
-#define SERDES_PRBSEN 4
-#define SERDES_LOOPEN 2
-#define SERDES_RXEN   1
-
-#define	ADC_CTRL_ON	0x0F
-#define	ADC_CTRL_OFF	0x00
-
-// crazy order that matches the labels on the case
-
-#define	LED_A		(1 << 4)
-#define	LED_B		(1 << 1)
-#define	LED_C		(1 << 3)
-#define	LED_D		(1 << 0)
-#define	LED_E		(1 << 2)
-//      LED_F		// controlled by CPLD
-#define	LED_RJ45	(1 << 5)
-
-#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE)
-
-// --- udp tx regs ---
-
-typedef struct {
-  // Bits 19:16 are control info; bits 15:0 are data (see below)
-  // First two words are unused.
-  volatile uint32_t _nope[2];
-  //--- ethernet header - 14 bytes---
-  volatile struct{
-    uint32_t mac_dst_0_1; //word 2
-    uint32_t mac_dst_2_3;
-    uint32_t mac_dst_4_5;
-    uint32_t mac_src_0_1;
-    uint32_t mac_src_2_3;
-    uint32_t mac_src_4_5;
-    uint32_t ether_type; //word 8
-  } eth_hdr;
-  //--- ip header - 20 bytes ---
-  volatile struct{
-    uint32_t ver_ihl_tos; //word 9
-    uint32_t total_length;
-    uint32_t identification;
-    uint32_t flags_frag_off;
-    uint32_t ttl_proto;
-    uint32_t checksum;
-    uint32_t src_addr_high;
-    uint32_t src_addr_low;
-    uint32_t dst_addr_high;
-    uint32_t dst_addr_low; //word 18
-  } ip_hdr;
-  //--- udp header - 8 bytes ---
-  volatile struct{
-    uint32_t src_port; //word 19
-    uint32_t dst_port;
-    uint32_t length;
-    uint32_t checksum; //word 22
-  } udp_hdr;
-  volatile uint32_t _pad[32-23];
-} sr_udp_sm_t;
-
-// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive)
-
-// This is the last word of the header
-#define	UDP_SM_LAST_WORD		(1 << 19)
-
-// Insert IP header checksum here.  Data is the xor of 16'hFFFF and
-// the values written into regs 9-13 and 15-18.
-#define	UDP_SM_INS_IP_HDR_CHKSUM	(1 << 18)
-
-// Insert IP Length here (data ignored)
-#define	UDP_SM_INS_IP_LEN		(1 << 17)
-
-// Insert UDP Length here (data ignore)
-#define	UDP_SM_INS_UDP_LEN		(1 << 16)
-
-#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM))
-
-// --- dsp tx regs ---
-
-#define MIN_CIC_INTERP	1
-#define	MAX_CIC_INTERP  128
-
-typedef struct {
-  volatile uint32_t     num_chan;
-  volatile uint32_t     clear_state;	// clears out state machine, fifos,
-} sr_tx_ctrl_t;
-
-#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL))
-
-typedef struct {
-  volatile int32_t	freq;
-  volatile uint32_t	scale_iq;	// {scale_i,scale_q}
-  volatile uint32_t     interp_rate;
-  volatile uint32_t     _padding0;      // padding for the tx_mux
-                                        //   NOT freq, scale, interp
-  /*!
-   * \brief output mux configuration.
-   *
-   * <pre>
-   *     3                   2                   1                       
-   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   *  +-------------------------------+-------+-------+-------+-------+
-   *  |                                               | DAC1  |  DAC0 |
-   *  +-------------------------------+-------+-------+-------+-------+
-   * 
-   *  There are N DUCs (1 now) with complex inputs and outputs.
-   *  There are two DACs.
-   * 
-   *  Each 4-bit DACx field specifies the source for the DAC
-   *  Each subfield is coded like this: 
-   * 
-   *     3 2 1 0
-   *    +-------+
-   *    |   N   |
-   *    +-------+
-   * 
-   *  N specifies which DUC output is connected to this DAC.
-   * 
-   *   N   which interp output
-   *  ---  -------------------
-   *   0   DUC 0 I
-   *   1   DUC 0 Q
-   *   2   DUC 1 I
-   *   3   DUC 1 Q
-   *   F   All Zeros
-   *   
-   * The default value is 0x10
-   * </pre>
-   */
-  volatile uint32_t	tx_mux;
-
-} dsp_tx_regs_t;
-  
-#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP))
-
-// --- VITA RX CTRL regs ---
-typedef struct {
-  // The following 3 are logically a single command register.
-  // They are clocked into the underlying fifo when time_ticks is written.
-  volatile uint32_t	cmd;		// {now, chain, num_samples(30)
-  volatile uint32_t	time_secs;
-  volatile uint32_t	time_ticks;
-
-  volatile uint32_t	clear_overrun;	// write anything to clear overrun
-  volatile uint32_t	vrt_header;	// word 0 of packet.  FPGA fills in packet counter
-  volatile uint32_t	vrt_stream_id;	// word 1 of packet. 
-  volatile uint32_t	vrt_trailer;
-  volatile uint32_t	nsamples_per_pkt;
-  volatile uint32_t     nchannels;      // 1 in basic case, up to 4 for vector sources
-  volatile uint32_t     pad[7];         // Make each structure 16 elements long
-} sr_rx_ctrl_t;
-
-#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL))
-
-// --- dsp rx regs ---
-#define	MIN_CIC_DECIM	1
-#define	MAX_CIC_DECIM   128
-
-typedef struct {
-  volatile int32_t	freq;
-  volatile uint32_t	scale_iq;	// {scale_i,scale_q}
-  volatile uint32_t     decim_rate;
-  volatile uint32_t     dcoffset_i;     // Bit 31 high sets fixed offset mode, using lower 14 bits,
-                                        // otherwise it is automatic 
-  volatile uint32_t     dcoffset_q;     // Bit 31 high sets fixed offset mode, using lower 14 bits
-
-  /*!
-   * \brief input mux configuration.
-   *
-   * This determines which ADC (or constant zero) is connected to 
-   * each DDC input.  There are N DDCs (1 now).  Each has two inputs.
-   *
-   * <pre>
-   * Mux value:
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   * |                                                       |Q0 |I0 |
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   *
-   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
-   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
-   *
-   * The default value is 0x4
-   * </pre>
-   */
-  volatile uint32_t     rx_mux;        // called adc_mux in dsp_core_rx.v
-
-  /*!
-   * \brief Streaming GPIO configuration
-   *
-   * This determines whether the LSBs of I and Q samples come from the DSP
-   * pipeline or from the io_rx GPIO pins.  To stream GPIO, one must first
-   * set the GPIO data direction register to have io_rx[15] and/or io_rx[14]
-   * configured as inputs.  The GPIO pins will be sampled at the time the
-   * remainder of the DSP sample is strobed into the RX sample FIFO.  There
-   * will be a decimation-dependent fixed time offset between the GPIO
-   * sample stream and the associated RF samples.
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   * |                           MBZ                             |Q|I|
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   *
-   * I         0=LSB comes from DSP pipeline (default)
-   *           1=LSB comes from io_rx[15]
-   * 
-   * Q         0=LSB comes from DSP pipeline (default)
-   *           1=LSB comes from io_rx[14]
-   */
-  volatile uint32_t gpio_stream_enable;
-
-} dsp_rx_regs_t;
-  
-#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP))
-
-// ----------------------------------------------------------------
-// VITA49 64 bit time (write only)
-  /*!
-   * \brief Time 64 flags
-   *
-   * <pre>
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-----------------------------------------------------------+-+-+
-   * |                                                           |S|P|
-   * +-----------------------------------------------------------+-+-+
-   *
-   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
-   * S - Source (0=sma, 1=mimo, 0=default)
-   *
-   * </pre>
-   */
-typedef struct {
-  volatile uint32_t	secs;	// value to set absolute secs to on next PPS
-  volatile uint32_t	ticks;	// value to set absolute ticks to on next PPS
-  volatile uint32_t flags;  // flags - see chart above
-  volatile uint32_t imm;    // set immediate (0=latch on next pps, 1=latch immediate, default=0)
-} sr_time64_t;
-
-#define sr_time64 ((sr_time64_t *) _SR_ADDR(SR_TIME64))
-
-
-/* 
- * --- ethernet tx protocol engine regs (write only) ---
- *
- * These registers control the transmit portion of the ethernet
- * protocol engine (out of USRP2).  The protocol engine handles fifo
- * status and sequence number insertion in outgoing packets, and
- * automagically generates status packets when required to inform the
- * host of changes in fifo availability.
- *
- * All outgoing packets have their fifo_status field set to the number
- * of 32-bit lines of fifo available in the ethernet Rx fifo (see
- * usrp2_eth_packet.h).  Seqno's are set if FIXME, else 0.
- *
- * FIXME clean this up once we know how it's supposed to behave.
- */
-
-typedef struct {
-  volatile uint32_t  flags;	     // not yet fully defined (channel?)
-  volatile uint32_t  mac_dst0123;    // 4 bytes of destination mac addr
-  volatile uint32_t  mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
-  volatile uint32_t  mac_src2345;    // 4 bytes of destination mac addr
-  volatile uint32_t  seqno;	     // Write to init seqno.  It autoincs on match
-} tx_proto_engine_regs_t;
-
-#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE)
-
-/*
- * --- ethernet rx protocol engine regs (write only) ---
- *
- * These registers control the receive portion of the ethernet
- * protocol engine (into USRP2).  The protocol engine offloads common
- * packet inspection operations so that firmware has less to do on
- * "fast path" packets.
- *
- * The registers define conditions which must be matched for a packet
- * to be considered a "fast path" packet.  If a received packet
- * matches the src and dst mac address, ethertype, flags field, and
- * expected seqno number it is considered a "fast path" packet, and
- * the expected seqno is updated.  If the packet fails to satisfy any
- * of the above conditions it's a "slow path" packet, and the
- * corresponding SLOWPATH flag will be set buffer_status register.
- */
-
-typedef struct {
-  volatile uint32_t  flags;	     // not yet fully defined (channel?)
-  volatile uint32_t  mac_dst0123;    // 4 bytes of destination mac addr
-  volatile uint32_t  mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
-  volatile uint32_t  mac_src2345;    // 4 bytes of destination mac addr
-  volatile uint32_t  ethertype_pad;  // ethertype in high 16-bits
-} rx_proto_engine_regs_t;
-
-#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE)
-
-
-
-///////////////////////////////////////////////////
-// Simple Programmable Interrupt Controller, Slave 8
-
-#define PIC_BASE  0xD800
-
-// Interrupt request lines
-// Bit numbers (LSB == 0) that correpond to interrupts into PIC
-
-#define	IRQ_BUFFER	0	// buffer manager
-#define	IRQ_ONETIME	1
-#define	IRQ_SPI		2
-#define	IRQ_I2C		3
-#define	IRQ_PHY		4	// ethernet PHY
-#define	IRQ_UNDERRUN	5
-#define	IRQ_OVERRUN	6
-#define	IRQ_PPS		7	// pulse per second
-#define	IRQ_UART_RX	8
-#define	IRQ_UART_TX	9
-#define	IRQ_SERDES	10
-#define	IRQ_CLKSTATUS	11
-#define IRQ_PERIODIC    12
-
-#define IRQ_TO_MASK(x) (1 << (x))
-
-#define PIC_BUFFER_INT    IRQ_TO_MASK(IRQ_BUFFER)
-#define PIC_ONETIME_INT   IRQ_TO_MASK(IRQ_ONETIME)
-#define PIC_SPI_INT       IRQ_TO_MASK(IRQ_SPI)
-#define PIC_I2C_INT       IRQ_TO_MASK(IRQ_I2C)
-#define PIC_PHY_INT       IRQ_TO_MASK(IRQ_PHY)
-#define PIC_UNDERRUN_INT  IRQ_TO_MASK(IRQ_UNDERRUN)
-#define PIC_OVERRUN_INT   IRQ_TO_MASK(IRQ_OVERRUN)
-#define PIC_PPS_INT   	  IRQ_TO_MASK(IRQ_PPS)
-#define PIC_UART_RX_INT   IRQ_TO_MASK(IRQ_UART_RX)
-#define PIC_UART_TX_INT   IRQ_TO_MASK(IRQ_UART_TX)
-#define PIC_SERDES        IRQ_TO_MASK(IRQ_SERDES)
-#define PIC_CLKSTATUS     IRQ_TO_MASK(IRQ_CLKSTATUS)
-
-typedef struct {
-  volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level
-  volatile uint32_t polarity;	 // mask: 1 -> rising edge
-  volatile uint32_t mask;	 // mask: 1 -> disabled
-  volatile uint32_t pending;	 // mask: 1 -> pending; write 1's to clear pending ints
-} pic_regs_t;
-
-#define pic_regs ((pic_regs_t *) PIC_BASE)
-
-// ----------------------------------------------------------------
-// WB_CLK_RATE is the time base for this
-typedef struct {
-  volatile uint32_t	onetime;   // Number of wb clk cycles till the onetime interrupt
-  volatile uint32_t	periodic;  // Repeat rate of periodic interrupt
-} sr_simple_timer_t;
-
-#define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER))
-
-///////////////////////////////////////////////////
-// UART, Slave 10
-
-#define UART_BASE  0xE000
-
-typedef struct {
-  //  All elements are 8 bits except for clkdiv (16), but we use uint32 to make 
-  //    the hardware for decoding easier
-  volatile uint32_t clkdiv;  // Set to 50e6 divided by baud rate (no x16 factor)
-  volatile uint32_t txlevel; // Number of spaces in the FIFO for writes
-  volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads
-  volatile uint32_t txchar;  // Write characters to be sent here
-  volatile uint32_t rxchar;  // Read received characters here
-} uart_regs_t;
-
-#define uart_regs ((uart_regs_t *) UART_BASE)
-
-///////////////////////////////////////////////////
-// ATR Controller, Slave 11
-
-#define ATR_BASE  0xE400
-
-typedef struct {
-  volatile uint32_t	v[16];
-} atr_regs_t;
-
-#define	ATR_IDLE	0x0	// indicies into v
-#define ATR_TX		0x1
-#define	ATR_RX		0x2
-#define	ATR_FULL	0x3
-
-#define atr_regs ((atr_regs_t *) ATR_BASE)
-
-///////////////////////////////////////////////////
-// SD Card SPI interface, Slave 13
-//   All regs are 8 bits wide, but are accessed as if they are 32 bits
-
-#define SDSPI_BASE  0xEC00
-
-typedef struct {
-  volatile uint32_t status;  // Write a 1 or 0 for controlling CS
-  volatile uint32_t clkdiv;
-  volatile uint32_t send_dat;
-  volatile uint32_t receive_dat;
-} sdspi_regs_t;
-
-#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE)
-
-///////////////////////////////////////////////////
-// External RAM interface, Slave 14
-//   Pages are 1K.  Page is 10 bits, set by a control register
-//    output_regs->ram_page
-
-#define EXTRAM_BASE 0xF000
-#define extram ((volatile uint32_t *) EXTRAM_BASE)
-
-
-///////////////////////////////////////////////////
-
-#endif
-
diff --git a/firmware/microblaze/lib/net/.gitignore b/firmware/microblaze/lib/net/.gitignore
new file mode 100644
index 000000000..282522db0
--- /dev/null
+++ b/firmware/microblaze/lib/net/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/firmware/microblaze/lib/net/eth_mac_addr.h b/firmware/microblaze/lib/net/eth_mac_addr.h
new file mode 100644
index 000000000..b44fb68f7
--- /dev/null
+++ b/firmware/microblaze/lib/net/eth_mac_addr.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_ETH_MAC_ADDR_H
+#define INCLUDED_ETH_MAC_ADDR_H
+
+#include <stdint.h>
+
+// Ethernet MAC address
+
+typedef struct {
+  uint8_t	addr[6];
+} eth_mac_addr_t;
+
+#endif /* INCLUDED_ETH_MAC_ADDR_H */
diff --git a/firmware/microblaze/lib/net/padded_eth_hdr.h b/firmware/microblaze/lib/net/padded_eth_hdr.h
new file mode 100644
index 000000000..df816734f
--- /dev/null
+++ b/firmware/microblaze/lib/net/padded_eth_hdr.h
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_PADDED_ETH_HDR_H
+#define INCLUDED_PADDED_ETH_HDR_H
+
+#include <compiler.h>
+#include <net/eth_mac_addr.h>
+
+/*!
+ * \brief Standard 14-byte ethernet header plus two leading bytes of padding.
+ *
+ * This is what a buffer contains in line 1 when using the "slow mode"
+ */
+typedef struct {
+  uint16_t	 pad;
+  eth_mac_addr_t dst;
+  eth_mac_addr_t src;
+  uint16_t 	 ethertype;
+} _AL4 padded_eth_hdr_t;
+
+
+#endif /* INCLUDED_PADDED_ETH_HDR_H */
diff --git a/firmware/microblaze/lib/net/socket_address.h b/firmware/microblaze/lib/net/socket_address.h
new file mode 100644
index 000000000..336f30a0c
--- /dev/null
+++ b/firmware/microblaze/lib/net/socket_address.h
@@ -0,0 +1,41 @@
+/* -*- c -*- */
+/*
+ * Copyright 2010 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef INCLUDED_SOCKET_ADDRESS_H
+#define INCLUDED_SOCKET_ADDRESS_H
+
+#include <lwip/ip_addr.h>
+
+// port and address are in network byte order
+
+typedef struct socket_address {
+  unsigned short   port;
+  struct ip_addr   addr;
+} socket_address_t;
+
+static inline struct socket_address 
+make_socket_address(struct ip_addr addr, int port)
+{
+  struct socket_address r;
+  r.port = port;
+  r.addr = addr;
+  return r;
+}
+
+
+
+#endif /* INCLUDED_SOCKET_ADDRESS_H */
diff --git a/firmware/microblaze/lib/nonstdio.c b/firmware/microblaze/lib/nonstdio.c
index 1c991afee..4b5fa4123 100644
--- a/firmware/microblaze/lib/nonstdio.c
+++ b/firmware/microblaze/lib/nonstdio.c
@@ -78,3 +78,46 @@ puthex32_nl(unsigned long x)
   puthex32(x);
   newline();
 }
+/*
+void reverse(char s[])
+{
+    int c, i, j;
+
+    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
+        c = s[i];
+        s[i] = s[j];
+        s[j] = c;
+    }
+}
+
+int abs(signed long value) {
+	return (value >= 0) ? value : 0-value;
+}
+
+//we'll keep the puthex functions above because they're way more lightweight. but sometimes you just want to print in decimal, you know?
+char *itoa(signed long value, char *result, int base)
+{
+	// check that the base if valid
+	if (base < 2 || base > 16) { *result = 0; return result; }
+
+	char* out = result;
+	signed long quotient = value;
+
+	do {
+		*out = hex[ abs(quotient % base) ];
+		++out;
+		quotient /= base;
+	} while ( quotient );
+
+	// Only apply negative sign for base 10
+	if ( value < 0 && base == 10) *out++ = '-';
+
+	*out = 0;
+	reverse( result );
+
+	return result;
+
+}
+*/
+
+
diff --git a/firmware/microblaze/lib/nonstdio.h b/firmware/microblaze/lib/nonstdio.h
index 3fd9e39bb..62ebfa46d 100644
--- a/firmware/microblaze/lib/nonstdio.h
+++ b/firmware/microblaze/lib/nonstdio.h
@@ -1,4 +1,6 @@
-/* -*- c -*- */
+//
+// Copyright 2010 Ettus Research LLC
+//
 /*
  * Copyright 2007 Free Software Foundation, Inc.
  *
@@ -20,7 +22,7 @@
 #define INCLUDED_NONSTDIO_H
 
 #include <stdio.h>
-#include <usrp2_types.h>
+#include <stdint.h>
 #include <stddef.h>
 
 void putstr(const char *s);		// cf puts, no added newline
@@ -37,10 +39,10 @@ void puthex32_nl(unsigned long x);
 void newline();				// putchar('\n')
 
 void print_mac_addr(const unsigned char addr[6]);
-void print_fxpt_freq(u2_fxpt_freq_t v);
-void print_fxpt_gain(u2_fxpt_gain_t v);
 void print_uint64(uint64_t v);
 
 void print_buffer(uint32_t *buf, size_t n);
+//char *itoa(signed long value, char *result, int base);
+//void reverse(char s[]);
 
 #endif /* INCLUDED_NONSTDIO_H */
diff --git a/firmware/microblaze/lib/pic.c b/firmware/microblaze/lib/pic.c
index 4575bd775..e89d2b755 100644
--- a/firmware/microblaze/lib/pic.c
+++ b/firmware/microblaze/lib/pic.c
@@ -44,7 +44,7 @@ pic_init(void)
   // uP is level triggered
 
   pic_regs->mask = ~0;				       // mask all interrupts
-  pic_regs->edge_enable = PIC_ONETIME_INT | PIC_PHY_INT;
+  pic_regs->edge_enable = PIC_ONETIME_INT;
   pic_regs->polarity = ~0 & ~PIC_PHY_INT;	       // rising edge
   pic_regs->pending = ~0;			       // clear all pending ints
 }
diff --git a/firmware/microblaze/lib/sd.c b/firmware/microblaze/lib/sd.c
deleted file mode 100644
index d000b28ae..000000000
--- a/firmware/microblaze/lib/sd.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2008 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sd.h"
-#include "memory_map.h"
-#include "stdint.h"
-#include "stdio.h"
-
-static inline void
-sd_packarg(unsigned char *argument,unsigned int value)
-{
-  argument[3] = (unsigned char)(value >> 24);
-  argument[2] = (unsigned char)(value >> 16);
-  argument[1] = (unsigned char)(value >> 8);
-  argument[0] = (unsigned char)(value);
-}
-
-int
-sd_init(void)
-{
-  unsigned char response[5];
-  unsigned char argument[4];
-  int i,j;
-
-  for(i=0;i<4;i++)
-    argument[i] = 0;
-
-  // Set clock to less than 400 kHz to start out
-  sdspi_regs->clkdiv = 128;
-
-  // Delay at least 74 cycles
-  sd_assert_cs();
-  for(i = 0; i < 100; i++)
-    sd_send_byte(SD_IDLE);
-  sd_deassert_cs();
-  
-  // Initialization Sequence -- CMD0 CMD55 ACMD41 CMD58
-  // Put card in idle state
-  if(sd_send_command(SD_CMD0,SD_CMD0_R,response,argument)==0)
-    return 0;  // Something went wrong in command
-
-  j = 0;
-  do {
-    j++;
-    if(sd_send_command(SD_CMD55,SD_CMD55_R,response,argument)==1)
-      sd_send_command(SD_ACMD41,SD_ACMD41_R,response,argument);
-    else
-      j = SD_IDLE_WAIT_MAX;
-  }
-  while(((response[0] & SD_MSK_IDLE) == SD_MSK_IDLE) && (j < SD_IDLE_WAIT_MAX));
-
-  if(j>= SD_IDLE_WAIT_MAX)  // IDLE timeout exceeded, card asleep
-    return 0;
-  
-  // CMD58 reads the SD card capabilities
-  if(sd_send_command(SD_CMD58,SD_CMD58_R,response,argument)==0)
-    return 0;  // CMD58 FAIL
-
-  if((response[2] & SD_MSK_OCR_33) != SD_MSK_OCR_33)
-    return 0;  // Card doesn't do 3.3V
-
-  //printf("OCR = %x %x %x %x\n",response[0],response[1],response[2],response[3]);
-
-  // Set blocklen here
-  sd_packarg(argument,SD_BLOCKLEN);
-  if(sd_send_command(SD_CMD16,SD_CMD16_R,response,argument)==0)
-    return 0;    // Set Blocklen failed
-  
-  // Reset back to high speed
-  sdspi_regs->clkdiv = 4;
-  //puts("finished init\n");
-  return 1;
-}
-
-int sd_send_command(unsigned char cmd,unsigned char response_type,
-		    unsigned char *response,unsigned char *argument)
-{
-  int i;
-  char response_length;
-  unsigned char tmp;
-
-  sd_assert_cs();
-  sd_send_byte((cmd & 0x3F) | 0x40);
-  for(i=3;i>=0;i--)
-    sd_send_byte(argument[i]);
-  sd_send_byte(SD_CRC);   // Always the same
-
-  response_length = 0;
-  switch(response_type)
-    {
-    case SD_R1:
-    case SD_R1B:
-      response_length = 1;
-      break;
-    case SD_R2:
-      response_length = 2;
-      break;
-    case SD_R3:
-      response_length = 5;
-      break;
-    default:
-      break;
-    }
-
-  // Wait for a response, which will have a 0 start bit
-  i = 0;
-  do
-    {
-      tmp = sd_rcv_byte();
-      i++;
-    }
-  while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT);
-
-  if(i>= SD_CMD_TIMEOUT)
-    {
-      sd_deassert_cs();
-      //puts("cmd send timeout\n");
-      return 0;
-    }
-
-  for(i=response_length-1; i>=0; i--)
-    {
-      response[i] = tmp;
-      tmp = sd_rcv_byte();
-    }
-  i = 0;
-  if(response_type == SD_R1B)
-    {
-      do
-	{
-	  i++;
-	  tmp = sd_rcv_byte();
-	}
-      while(tmp != SD_IDLE);
-      sd_send_byte(SD_IDLE);
-    }
-  
-  //puts("send cmd success\n");
-  sd_deassert_cs();
-  return 1;
-}
-
-int
-sd_read_block (unsigned int blockaddr, unsigned char *buf)
-{
-  unsigned char response[5];
-  unsigned char argument[4];
-  unsigned int i = 0;
-  unsigned char tmp;
-
-  blockaddr <<= SD_BLOCKLEN_NBITS;
-  sd_packarg(argument,blockaddr);
-  if(sd_send_command(SD_CMD17,SD_CMD17_R,response,argument)==0)
-    return 0;    //Failed READ;
-  if(response[0] != 0)
-    return 0;    //Misaligned READ
-
-  sd_assert_cs();
-  i = 0;
-  do
-    {
-      tmp = sd_rcv_byte();
-      i++;
-    }
-  while((tmp == 0xFF) && (i < SD_RD_TIMEOUT));
-  if((i>= SD_RD_TIMEOUT) ||((tmp & SD_MSK_TOK_DATAERROR) == 0))
-    {
-      sd_send_byte(SD_IDLE);  // Send a dummy before quitting
-      return 0;   // Data ERROR
-    }
-  for(i=0;i<SD_BLOCKLEN;i++)
-    buf[i] = sd_rcv_byte();
-  return 1;
-
-}
-
-int
-sd_write_block(unsigned int blockaddr, const unsigned char *buf)
-{
-  // FIXME not implemented yet
-  return 0;
-}
diff --git a/firmware/microblaze/lib/sd.h b/firmware/microblaze/lib/sd.h
deleted file mode 100644
index e2d0ae38e..000000000
--- a/firmware/microblaze/lib/sd.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2008 Ettus Research LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_SD_H
-#define INCLUDED_SD_H
-
-#include "memory_map.h"
-
-#define SD_READY 1
-#define SD_IDLE_WAIT_MAX 100
-#define SD_CMD_TIMEOUT 100
-#define SD_RD_TIMEOUT 1000
-
-#define SD_CMD0 0
-#define SD_CMD1 1
-#define SD_CMD9 9
-#define SD_CMD10 10
-#define SD_CMD12 12
-#define SD_CMD13 13
-#define SD_CMD16 16
-#define SD_CMD17 17 
-#define SD_CMD18 18
-#define SD_CMD24 24
-#define SD_CMD25 25
-#define SD_CMD27 27
-#define SD_CMD28 28
-#define SD_CMD29 29
-#define SD_CMD30 30
-#define SD_CMD32 32
-#define SD_CMD33 33
-#define SD_CMD38 38
-#define SD_CMD55 55
-#define SD_CMD58 58
-#define SD_CMD59 59
-#define SD_ACMD41 41
-#define SD_IDLE 0xFF
-#define SD_CRC 0x95
-
-#define SD_R1 1
-#define SD_R1B 2
-#define SD_R2 3
-#define SD_R3 4
-
-#define SD_CMD0_R SD_R1
-#define SD_CMD16_R SD_R1
-#define SD_CMD17_R SD_R1
-#define SD_CMD55_R SD_R1
-#define SD_ACMD41_R SD_R1
-#define SD_CMD58_R SD_R3
-
-#define SD_BLOCKLEN 512
-#define SD_BLOCKLEN_NBITS 9
-
-#define SD_MSK_IDLE 0x01
-#define SD_MSK_OCR_33 0xC0
-#define SD_MSK_TOK_DATAERROR 0xE0
-
-
-int sd_init(void);
-
-static inline void
-sd_assert_cs(void)
-{
-  // Wait for idle before doing anything
-  while(sdspi_regs->status != SD_READY)
-    ;
-  sdspi_regs->status = 1;
-}
-
-static inline void
-sd_deassert_cs(void)
-{
-  // Wait for idle before doing anything
-  while(sdspi_regs->status != SD_READY)
-    ;
-  sdspi_regs->status = 0;
-}
-
-static inline char
-sd_rcv_byte(void)
-{
-  // Wait for idle before doing anything
-  while(sdspi_regs->status != SD_READY)
-    ;
-  sdspi_regs->send_dat = SD_IDLE;
-  while(sdspi_regs->status != SD_READY)
-    ;
-  return sdspi_regs-> receive_dat;
-}
-
-static inline void
-sd_send_byte(char dat)
-{
-  // Wait for idle before doing anything
-  while(sdspi_regs->status != SD_READY)
-    ;      // Wait for status = 1 (ready)
-  sdspi_regs->send_dat = dat;
-}
-
-
-int sd_send_command(unsigned char cmd,unsigned char response_type,
-		    unsigned char *response,unsigned char *argument);
-
-int sd_read_block (unsigned int blockaddr, unsigned char *buf);
-int sd_write_block(unsigned int blockaddr, const unsigned char *buf);
-
-#endif /* INCLUDED_SD_H */
diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c
index 937397df6..bef808e57 100644
--- a/firmware/microblaze/lib/spi.c
+++ b/firmware/microblaze/lib/spi.c
@@ -43,7 +43,7 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags
   spi_wait();
 
   // Tell it which SPI slave device to access
-  spi_regs->ss = slave & 0xff;
+  spi_regs->ss = slave & 0xffff;
 
   // Data we will send
   spi_regs->txrx0 = data;
diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h
index f5b69b270..01e4d26fd 100644
--- a/firmware/microblaze/lib/spi.h
+++ b/firmware/microblaze/lib/spi.h
@@ -48,5 +48,23 @@ void spi_wait(void);
 uint32_t
 spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags);
 
+// ----------------------------------------------------------------
+// Routines that manipulate the FLASH SPI BUS
+// ----------------------------------------------------------------
+
+/*!
+ * \brief One time call to initialize SPI
+ */
+void spif_init(void);
+
+/*! 
+ * \brief Wait for last SPI transaction to complete.
+ * Unless you need to know it completed, it's not necessary to call this.
+ */
+void spif_wait(void);
+
+uint32_t
+spif_transact(bool readback_, int slave, uint32_t data, int length, uint32_t flags);
+
 
 #endif /* INCLUDED_SPI_H */
diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c
index 6809101c0..75bc40859 100644
--- a/firmware/microblaze/lib/u2_init.c
+++ b/firmware/microblaze/lib/u2_init.c
@@ -25,9 +25,8 @@
 #include "i2c.h"
 #include "mdelay.h"
 #include "clocks.h"
-#include "usrp2_i2c_addr.h"
-
-//#include "nonstdio.h"
+#include "usrp2/fw_common.h"
+#include "nonstdio.h"
 
 unsigned char u2_hw_rev_major;
 unsigned char u2_hw_rev_minor;
@@ -35,8 +34,8 @@ unsigned char u2_hw_rev_minor;
 static inline void
 get_hw_rev(void)
 {
-  bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &u2_hw_rev_minor, 1);
-  ok &= eeprom_read(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &u2_hw_rev_major, 1);
+  bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, &u2_hw_rev_minor, 1);
+  ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, &u2_hw_rev_major, 1);
 }
 
 /*
@@ -68,7 +67,7 @@ u2_init(void)
   mdelay(100);
   hal_set_leds(0x1f, 0x1f);
   mdelay(100);
-  hal_set_leds(0x1, 0x1f);  // Leave the first one on
+  hal_set_leds(LED_D, 0x1f);  // Leave one on
 
 #if 0
   // test register readback
diff --git a/firmware/microblaze/usrp2/.gitignore b/firmware/microblaze/usrp2/.gitignore
new file mode 100644
index 000000000..18f715618
--- /dev/null
+++ b/firmware/microblaze/usrp2/.gitignore
@@ -0,0 +1,9 @@
+/Makefile
+/Makefile.in
+/*.a
+/*.bin
+/*.dump
+/*.ihx
+/*.elf
+/*.rom
+/*.map
diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am
new file mode 100644
index 000000000..8da013980
--- /dev/null
+++ b/firmware/microblaze/usrp2/Makefile.am
@@ -0,0 +1,43 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+include $(top_srcdir)/Makefile.common
+
+AM_CFLAGS = \
+	$(COMMON_CFLAGS)
+
+AM_LDFLAGS = \
+	$(COMMON_LFLAGS) \
+	libusrp2.a \
+	-Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \
+	-Wl,-defsym -Wl,_STACK_SIZE=3072
+
+########################################################################
+# USRP2 specific library and programs
+########################################################################
+noinst_LIBRARIES = libusrp2.a
+
+libusrp2_a_SOURCES = \
+	$(COMMON_SRCS) \
+	sd.c \
+	ethernet.c
+
+noinst_PROGRAMS = \
+	usrp2_txrx_uhd.elf
+
+usrp2_txrx_uhd_elf_SOURCES = \
+	$(top_srcdir)/apps/txrx_uhd.c
diff --git a/firmware/microblaze/usrp2/eth_phy.h b/firmware/microblaze/usrp2/eth_phy.h
new file mode 100644
index 000000000..6c16f97b7
--- /dev/null
+++ b/firmware/microblaze/usrp2/eth_phy.h
@@ -0,0 +1,219 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Much of this was extracted from the Linux e1000_hw.h file */
+
+#ifndef INCLUDED_ETH_PHY_H
+#define INCLUDED_ETH_PHY_H
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+
+#define PHY_CTRL         0x00 /* Control Register */
+#define PHY_STATUS       0x01 /* Status Regiser */
+#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
+
+/* PHY 1000 MII Register additions in DP83856 */
+/* The part implements 0x00 thru 0x1f; we use these. */
+
+#define	PHY_LINK_AN	 0x11 /* Link and Auto Negotiation Status Reg */
+#define PHY_INT_STATUS	 0x14 /* Interupt Status Reg (RO) */
+#define PHY_INT_MASK	 0x15 /* Interrupt Mask Reg  (RW) */
+#define PHY_INT_CLEAR    0x17 /* Interrupt Clear Reg (RW) */
+
+
+/* Bit definitions for some of the registers above */
+
+/* PHY Control Register (PHY_CTRL) */
+#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN       0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
+
+/* PHY Status Register (PHY_STATUS) */
+#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */
+#define NWAY_AR_SELECTOR_FIELD 0x0001   /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS  0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS  0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS     0x0200   /* 100T4 Capable */
+#define NWAY_AR_PAUSE          0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT   0x2000   /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE      0x8000   /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */
+#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT  0x0010 /* LP is 100TX Full Duplex Capable */
+
+/* Next Page TX Register (PHY_NEXT_PAGE_TX) */
+#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define NPTX_TOGGLE         0x0800 /* Toggles between exchanges
+                                    * of different NP
+                                    */
+#define NPTX_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
+                                    * 0 = cannot comply with msg
+                                    */
+#define NPTX_MSG_PAGE       0x2000 /* formatted(1)/unformatted(0) pg */
+#define NPTX_NEXT_PAGE      0x8000 /* 1 = addition NP will follow
+                                    * 0 = sending last NP
+                                    */
+
+/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */
+#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define LP_RNPR_TOGGLE         0x0800 /* Toggles between exchanges
+                                       * of different NP
+                                       */
+#define LP_RNPR_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
+                                       * 0 = cannot comply with msg
+                                       */
+#define LP_RNPR_MSG_PAGE       0x2000  /* formatted(1)/unformatted(0) pg */
+#define LP_RNPR_ACKNOWLDGE     0x4000  /* 1 = ACK / 0 = NO ACK */
+#define LP_RNPR_NEXT_PAGE      0x8000  /* 1 = addition NP will follow
+                                        * 0 = sending last NP
+                                        */
+
+/* 1000BASE-T Control Register (PHY_1000T_CTRL) */
+#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
+#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
+                                        /* 0=DTE device */
+#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
+                                        /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
+                                        /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register (PHY_1000T_STATUS) */
+#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR   0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
+#define SR_1000T_REMOTE_RX_STATUS_SHIFT          12
+#define SR_1000T_LOCAL_RX_STATUS_SHIFT           13
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT    5
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_20            20
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_100           100
+
+/* Extended Status Register (PHY_EXT_STATUS) */
+#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+#define PHY_TX_POLARITY_MASK   0x0100 /* register 10h bit 8 (polarity bit) */
+#define PHY_TX_NORMAL_POLARITY 0      /* register 10h bit 8 (normal polarity) */
+
+#define AUTO_POLARITY_DISABLE  0x0010 /* register 11h bit 4 */
+                                      /* (0=enable, 1=disable) */
+
+/* Link and Auto Negotiation Status Reg (PHY_LINK_AN) [READ-ONLY] */
+#define	LANSR_MASTER           0x0001 /* 1=PHY is currently in master mode */
+#define	LANSR_FULL_DUPLEX      0x0002 /* 1=PHY is currently full duplex */
+#define LANSR_LINK_GOOD        0x0004 /* 1=a good link is established */
+#define LANSR_SPEED_MASK       0x0018
+#define	  LANSR_SPEED_10       0x0000 /*   10Mb/s */
+#define	  LANSR_SPEED_100      0x0008 /*  100Mb/s */
+#define	  LANSR_SPEED_1000     0x0010 /* 1000Mb/s */
+#define	  LANSR_SPEED_RSRVD    0x0018 /* reserved */
+#define LANSR_NON_COMP_MODE    0x0020 /* 1=detects only in non-compliant mode */
+#define	LANSR_DEEP_LOOPBACK    0x0040 /* 1=the PHY operates in deep loopback mode */
+#define	LANSR_SHALLOW_LOOPBACK 0x0080 /* 1=the PHY operates in shallow loopback mode */
+#define LANSR_RSRVD_8	       0x0100 /* reserved */
+#define LANSR_FIFO_ERR	       0x0200 /* 1=FIFO error occurred */
+#define	LANSR_MDIX_XOVER       0x0400 /* 1=PHY's MDI is in cross-over mode */
+#define	LANSR_RSRVD_11	       0x0800 /* resevered */
+#define	LANSR_TP_POLARITY_REV  0xf000 /* Twisted pair polarity status A:D([15:12]) 1=reversed */
+
+/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */
+#define	PHY_INT_RSRVD_0	       0x0001 /* reserved */
+#define	PHY_INT_RSRVD_1	       0x0002 /* reserved */
+#define	PHY_INT_RSRVD_2	       0x0004 /* reserved */
+#define	PHY_INT_REM_FLT_CNG    0x0008 /* Remote Fault Changed */
+#define	PHY_INT_AN_CMPL	       0x0010 /* Auto-negotiation completion */
+#define	PHY_INT_NXT_PG_RCVD    0x0020 /* Next Page Received */
+#define PHY_INT_JABBER_CNG     0x0040 /* Jabber Changed */
+#define PHY_INT_NO_LINK	       0x0080 /* No link after auto-negotiation */
+#define PHY_INT_NO_HCD	       0x0100 /* AN couldn't determine highest common denominator */
+#define PHY_INT_MAS_SLA_ERR    0x0200 /* Master / Slave Error: couldn't resolve */
+#define PHY_INT_PRL_DET_FLT    0x0400 /* Parallel detection fault */
+#define PHY_INT_POL_CNG	       0x0800 /* Polarity of any channel changed */
+#define	PHY_INT_MDIX_CNG       0x1000 /* MDIX changed.  A pair swap occurred. */
+#define PHY_INT_DPLX_CNG       0x2000 /* Duplex changed */
+#define PHY_INT_LNK_CNG	       0x4000 /* Link changed (asserted when a link is established or broken) */
+#define PHY_INT_SPD_CNG	       0x8000 /* Speed changed */
+
+#endif /* INCLUDED_ETH_PHY_H */
diff --git a/firmware/microblaze/usrp2/ethernet.c b/firmware/microblaze/usrp2/ethernet.c
new file mode 100644
index 000000000..d60d7dc4c
--- /dev/null
+++ b/firmware/microblaze/usrp2/ethernet.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ethernet.h"
+#include "memory_map.h"
+#include "eth_phy.h"
+#include "eth_mac.h"
+#include "eth_mac_regs.h"
+#include "pic.h"
+#include "hal_io.h"
+#include "nonstdio.h"
+#include <stdbool.h>
+#include "i2c.h"
+#include "usrp2/fw_common.h"
+
+#define VERBOSE 1
+
+static ethernet_t ed_state;
+static ethernet_link_changed_callback_t ed_callback = 0;
+
+void 
+ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback)
+{
+  ed_callback = new_callback;
+}
+
+
+static void
+ed_set_mac_speed(int speed)
+{
+  printf("Speed set to %d\n",speed);
+  /*
+  switch(speed){
+  case 10:
+    eth_mac->speed = 1;
+    break;
+  case 100:
+    eth_mac->speed = 2;
+    break;
+  case 1000:
+    eth_mac->speed = 4;
+    break;
+  default:
+    break;
+  }
+  */
+}
+
+static void
+ed_link_up(int speed)
+{
+  // putstr("ed_link_up: "); puthex16_nl(speed);
+
+  ed_set_mac_speed(speed);
+
+  if (ed_callback)		// fire link changed callback
+    (*ed_callback)(speed);
+}
+
+static void
+ed_link_down(void)
+{
+  // putstr("ed_link_down\n");
+
+  if (ed_callback)		// fire link changed callback
+    (*ed_callback)(0);
+}
+
+
+static void
+ed_link_speed_change(int speed)
+{
+  ed_link_down();
+  ed_link_up(speed);
+}
+
+static void
+print_flow_control(int flow_control)
+{
+  static const char *flow_control_msg[4] = {
+    "NONE", "WE_TX", "WE_RX", "SYMMETRIC"
+  };
+  putstr("ethernet flow control: ");
+  puts(flow_control_msg[flow_control & 0x3]);
+}
+
+static void
+check_flow_control_resolution(void)
+{
+  static const unsigned char table[16] = {
+    // index = {local_asm, local_pause, partner_asm, partner_pause}
+    FC_NONE,  FC_NONE,  FC_NONE,  FC_NONE,
+    FC_NONE,  FC_SYMM,  FC_NONE,  FC_SYMM,
+    FC_NONE,  FC_NONE,  FC_NONE,  FC_WE_TX,
+    FC_NONE,  FC_SYMM,  FC_WE_RX, FC_SYMM
+  };
+
+  int us = eth_mac_miim_read(PHY_AUTONEG_ADV);
+  int lp = eth_mac_miim_read(PHY_LP_ABILITY);
+  int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3);
+  ed_state.flow_control = table[index];
+
+  if (1)
+    print_flow_control(ed_state.flow_control);
+}
+
+/*
+ * Read the PHY state register to determine link state and speed
+ */
+static void
+ed_check_phy_state(void)
+{
+  int lansr = eth_mac_miim_read(PHY_LINK_AN);
+  eth_link_state_t new_state = LS_UNKNOWN;
+  int new_speed = S_UNKNOWN;
+
+  if (VERBOSE){
+    putstr("LANSR: ");
+    puthex16_nl(lansr);
+  }
+
+  if (lansr & LANSR_LINK_GOOD){		// link's up
+    if (VERBOSE)
+      puts("  LINK_GOOD");
+
+    new_state = LS_UP;
+    switch (lansr & LANSR_SPEED_MASK){
+    case LANSR_SPEED_10:
+      new_speed = 10;
+      break;
+      
+    case LANSR_SPEED_100:
+      new_speed = 100;
+      break;
+      
+    case LANSR_SPEED_1000:
+      new_speed = 1000;
+      break;
+
+    default:
+      new_speed = S_UNKNOWN;
+      break;
+    }
+
+    check_flow_control_resolution();
+  }
+  else {				// link's down
+    if (VERBOSE)
+      puts("  NOT LINK_GOOD");
+    
+    new_state = LS_DOWN;
+    new_speed = S_UNKNOWN;
+  }
+
+  if (new_state != ed_state.link_state){
+    ed_state.link_state = new_state;		// remember new state
+    if (new_state == LS_UP)
+      ed_link_up(new_speed);
+    else if (new_state == LS_DOWN)
+      ed_link_down();
+  }
+  else if (new_state == LS_UP && new_speed != ed_state.link_speed){
+    ed_state.link_speed = new_speed;		// remember new speed
+    ed_link_speed_change(new_speed);
+  }
+}
+
+/*
+ * This is fired when the ethernet PHY state changes
+ */
+static void
+eth_phy_irq_handler(unsigned irq)
+{
+  ed_check_phy_state();
+  eth_mac_miim_write(PHY_INT_CLEAR, ~0);	// clear all ints
+}
+
+void
+ethernet_init(void)
+{
+  eth_mac_init(ethernet_mac_addr());
+
+  ed_state.link_state = LS_UNKNOWN;
+  ed_state.link_speed = S_UNKNOWN;
+
+  // initialize MAC registers
+  //  eth_mac->tx_hwmark = 0x1e;
+  //eth_mac->tx_lwmark = 0x19;
+
+  //eth_mac->crc_chk_en = 1;
+  //eth_mac->rx_max_length = 2048;
+
+  // configure PAUSE frame stuff
+  //eth_mac->tx_pause_en = 1;		// pay attn to pause frames sent to us
+
+  //eth_mac->pause_quanta_set = 38;	// a bit more than 1 max frame 16kb/512 + fudge
+  //eth_mac->pause_frame_send_en = 1;	// enable sending pause frames
+
+
+  // setup PHY to interrupt on changes
+
+  unsigned mask =
+    (PHY_INT_AN_CMPL		// auto-neg completed
+     | PHY_INT_NO_LINK		// no link after auto-neg
+     | PHY_INT_NO_HCD		// no highest common denominator
+     | PHY_INT_MAS_SLA_ERR	// couldn't resolve master/slave 
+     | PHY_INT_PRL_DET_FLT	// parallel detection fault
+     | PHY_INT_LNK_CNG		// link established or broken
+     | PHY_INT_SPD_CNG		// speed changed
+     );
+
+  eth_mac_miim_write(PHY_INT_CLEAR, ~0);	// clear all pending interrupts
+  eth_mac_miim_write(PHY_INT_MASK, mask);	// enable the ones we want
+
+  pic_register_handler(IRQ_PHY, eth_phy_irq_handler);
+
+  // Advertise our flow control configuation.
+  //
+  // We and the link partner each specify two bits in the base page
+  // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR.
+  // The bits say what a device is "willing" to do, not what may actually
+  // happen as a result of the negotiation.  There are 4 cases:
+  //
+  // PAUSE  ASM_DIR
+  //
+  //  0        0        I have no flow control capability.
+  //
+  //  1        0        I both assert and respond to flow control.
+  //
+  //  0        1        I assert flow control, but cannot respond.  That is,
+  //                    I want to be able to send PAUSE frames, but will ignore any
+  //		 	you send to me.  (This is our configuration.)
+  //
+  //  1        1        I can both assert and respond to flow control AND I am willing
+  //                    to operate symmetrically OR asymmetrically in EITHER direction.
+  //                    (We hope the link partner advertises this, otherwise we don't
+  //			get what we want.)
+
+  int t = eth_mac_miim_read(PHY_AUTONEG_ADV);
+  t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR);
+  t |= NWAY_AR_ASM_DIR;
+
+  // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex
+  t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS);
+
+  eth_mac_miim_write(PHY_AUTONEG_ADV, t);
+  int r = eth_mac_miim_read(PHY_AUTONEG_ADV);  		// DEBUG, read back
+  if (t != r){
+    printf("PHY_AUTONEG_ADV: wrote 0x%x, got 0x%x\n", t, r);
+  }
+
+  // Restart autonegotation.  
+  // We want to ensure that we're advertising our PAUSE capabilities.
+  t = eth_mac_miim_read(PHY_CTRL);
+  eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG);
+}
+
+static bool 
+unprogrammed(const void *t, size_t len)
+{
+  int i;
+  uint8_t *p = (uint8_t *)t;
+  bool all_zeros = true;
+  bool all_ones =  true;
+  for (i = 0; i < len; i++){
+    all_zeros &= p[i] == 0x00;
+    all_ones  &= p[i] == 0xff;
+  }
+  return all_ones | all_zeros;
+}
+
+//////////////////// MAC Addr Stuff ///////////////////////
+
+static int8_t src_mac_addr_initialized = false;
+static eth_mac_addr_t src_mac_addr = {{
+    0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff
+  }};
+
+const eth_mac_addr_t *
+ethernet_mac_addr(void)
+{
+  if (!src_mac_addr_initialized){    // fetch from eeprom
+    src_mac_addr_initialized = true;
+
+    // if we're simulating, don't read the EEPROM model, it's REALLY slow
+    if (hwconfig_simulation_p())
+      return &src_mac_addr;
+    
+    eth_mac_addr_t tmp;
+    bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp));
+    if (!ok || unprogrammed(&tmp, sizeof(tmp))){
+      // use the default
+    }
+    else
+      src_mac_addr = tmp;
+  }
+
+  return &src_mac_addr;
+}
+
+bool
+ethernet_set_mac_addr(const eth_mac_addr_t *t)
+{
+  bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t));
+  if (ok){
+    src_mac_addr = *t;
+    src_mac_addr_initialized = true;
+    //eth_mac_set_addr(t); //this breaks the link
+  }
+
+  return ok;
+}
+
+//////////////////// IP Addr Stuff ///////////////////////
+
+static int8_t src_ip_addr_initialized = false;
+static struct ip_addr src_ip_addr = {
+    (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0)
+};
+
+
+const struct ip_addr *get_ip_addr(void)
+{
+  if (!src_ip_addr_initialized){    // fetch from eeprom
+    src_ip_addr_initialized = true;
+
+    // if we're simulating, don't read the EEPROM model, it's REALLY slow
+    if (hwconfig_simulation_p())
+      return &src_ip_addr;
+    
+    struct ip_addr tmp;
+    bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp));
+    if (!ok || unprogrammed(&tmp, sizeof(tmp))){
+      // use the default
+    }
+    else
+      src_ip_addr = tmp;
+  }
+
+  return &src_ip_addr;
+}
+
+bool set_ip_addr(const struct ip_addr *t){
+  bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr));
+  if (ok){
+    src_ip_addr = *t;
+    src_ip_addr_initialized = true;
+  }
+
+  return ok;
+}
+
+int
+ethernet_check_errors(void)
+{
+  // these registers are reset when read
+  
+  int	r = 0;
+  /*
+  if (eth_mac_read_rmon(0x05) != 0)
+    r |= RME_RX_CRC;
+  if (eth_mac_read_rmon(0x06) != 0)
+    r |= RME_RX_FIFO_FULL;
+  if (eth_mac_read_rmon(0x07) != 0)
+    r |= RME_RX_2SHORT_2LONG;
+  
+  if (eth_mac_read_rmon(0x25) != 0)
+    r |= RME_TX_JAM_DROP;
+  if (eth_mac_read_rmon(0x26) != 0)
+    r |= RME_TX_FIFO_UNDER;
+  if (eth_mac_read_rmon(0x27) != 0)
+    r |= RME_TX_FIFO_OVER;
+  */
+  return r;
+}
diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h
new file mode 100644
index 000000000..41a2820bc
--- /dev/null
+++ b/firmware/microblaze/usrp2/memory_map.h
@@ -0,0 +1,797 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Overall Memory Map
+ *   0000-7FFF  32K   RAM space (16K on 1500, 24K on 2000, 32K on DSP)
+ *   8000-BFFF  16K   Buffer Pool
+ *   C000-FFFF  16K   Peripherals
+ */
+
+
+#ifndef INCLUDED_MEMORY_MAP_H
+#define INCLUDED_MEMORY_MAP_H
+
+#include <stdint.h>
+
+
+#define MASTER_CLK_RATE        100000000		// 100 MHz
+
+
+////////////////////////////////////////////////////////////////
+//
+//         Memory map for embedded wishbone bus
+//
+////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////
+// Main RAM, Slave 0
+
+#define RAM_BASE 0x0000
+
+////////////////////////////////////////////////////////////////
+// Buffer Pool RAM, Slave 1
+//
+// The buffers themselves are located in Slave 1, Buffer Pool RAM.
+// The status registers are in Slave 5, Buffer Pool Status.
+// The control register is in Slave 7, Settings Bus.
+
+#define BUFFER_POOL_RAM_BASE 0x8000
+
+#define	NBUFFERS                8
+#define BP_NLINES	   0x0200	// number of 32-bit lines in a buffer
+#define BP_LAST_LINE	(BP_NLINES - 1)	// last line in a buffer
+
+#define buffer_pool_ram \
+  ((uint32_t *) BUFFER_POOL_RAM_BASE)
+
+#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES])
+
+
+/////////////////////////////////////////////////////
+// SPI Core, Slave 2.  See core docs for more info
+#define SPI_BASE 0xC000   // Base address (16-bit)
+
+typedef struct {
+  volatile uint32_t	txrx0;
+  volatile uint32_t	txrx1;
+  volatile uint32_t	txrx2;
+  volatile uint32_t	txrx3;
+  volatile uint32_t	ctrl;
+  volatile uint32_t	div;
+  volatile uint32_t	ss;
+} spi_regs_t;
+
+#define spi_regs ((spi_regs_t *) SPI_BASE)
+
+
+// Masks for controlling different peripherals
+#define SPI_SS_AD9510    1
+#define SPI_SS_AD9777    2
+#define SPI_SS_RX_DAC    4
+#define SPI_SS_RX_ADC    8
+#define SPI_SS_RX_DB    16
+#define SPI_SS_TX_DAC   32
+#define SPI_SS_TX_ADC   64
+#define SPI_SS_TX_DB   128
+#define SPI_SS_ADS64P44 256
+
+// Masks for different parts of CTRL reg
+#define SPI_CTRL_ASS      (1<<13)
+#define SPI_CTRL_IE       (1<<12)
+#define SPI_CTRL_LSB      (1<<11)
+#define SPI_CTRL_TXNEG    (1<<10)
+#define SPI_CTRL_RXNEG    (1<< 9)
+#define SPI_CTRL_GO_BSY   (1<< 8)
+#define SPI_CTRL_CHAR_LEN_MASK 0x7F
+
+////////////////////////////////////////////////
+// I2C, Slave 3
+// See Wishbone I2C-Master Core Specification.
+
+#define I2C_BASE 0xC400
+
+typedef struct {
+  volatile uint32_t  prescaler_lo;	// r/w
+  volatile uint32_t  prescaler_hi;	// r/w
+  volatile uint32_t  ctrl;		// r/w
+  volatile uint32_t  data;		// wr = transmit reg; rd = receive reg
+  volatile uint32_t  cmd_status;	// wr = command reg;  rd = status reg
+} i2c_regs_t;
+
+#define i2c_regs ((i2c_regs_t *) I2C_BASE)
+
+#define	I2C_CTRL_EN	(1 << 7)	// core enable
+#define	I2C_CTRL_IE	(1 << 6)	// interrupt enable
+
+//
+// STA, STO, RD, WR, and IACK bits are cleared automatically
+//
+#define	I2C_CMD_START	(1 << 7)	// generate (repeated) start condition
+#define I2C_CMD_STOP	(1 << 6)	// generate stop condition
+#define	I2C_CMD_RD	(1 << 5)	// read from slave
+#define I2C_CMD_WR	(1 << 4)	// write to slave
+#define	I2C_CMD_NACK	(1 << 3)	// when a rcvr, send ACK (ACK=0) or NACK (ACK=1)
+#define I2C_CMD_RSVD_2	(1 << 2)	// reserved
+#define	I2C_CMD_RSVD_1	(1 << 1)	// reserved
+#define I2C_CMD_IACK	(1 << 0)	// set to clear pending interrupt
+
+#define I2C_ST_RXACK	(1 << 7)	// Received acknowledgement from slave (1 = NAK, 0 = ACK)
+#define	I2C_ST_BUSY	(1 << 6)	// 1 after START signal detected; 0 after STOP signal detected
+#define	I2C_ST_AL	(1 << 5)	// Arbitration lost.  1 when core lost arbitration
+#define	I2C_ST_RSVD_4	(1 << 4)	// reserved
+#define	I2C_ST_RSVD_3	(1 << 3)	// reserved
+#define	I2C_ST_RSVD_2	(1 << 2)	// reserved
+#define I2C_ST_TIP	(1 << 1)	// Transfer-in-progress
+#define	I2C_ST_IP	(1 << 0)	// Interrupt pending
+
+
+////////////////////////////////////////////////
+// GPIO, Slave 4
+//
+// These go to the daughterboard i/o pins
+
+#define GPIO_BASE 0xC800
+
+typedef struct {
+  volatile uint32_t	io;	  // tx data in high 16, rx in low 16
+  volatile uint32_t     ddr;      // 32 bits, 1 means output. tx in high 16, rx in low 16
+  volatile uint32_t	tx_sel;   // 16 2-bit fields select which source goes to TX DB
+  volatile uint32_t	rx_sel;   // 16 2-bit fields select which source goes to RX DB
+} gpio_regs_t;
+
+// each 2-bit sel field is layed out this way
+#define GPIO_SEL_SW	   0 // if pin is an output, set by software in the io reg
+#define	GPIO_SEL_ATR	   1 // if pin is an output, set by ATR logic
+#define	GPIO_SEL_DEBUG_0   2 // if pin is an output, debug lines from FPGA fabric
+#define	GPIO_SEL_DEBUG_1   3 // if pin is an output, debug lines from FPGA fabric
+
+#define gpio_base ((gpio_regs_t *) GPIO_BASE)
+
+///////////////////////////////////////////////////
+// Buffer Pool Status, Slave 5
+//
+// The buffers themselves are located in Slave 1, Buffer Pool RAM.
+// The status registers are in Slave 5, Buffer Pool Status.
+// The control register is in Slave 7, Settings Bus.
+
+#define BUFFER_POOL_STATUS_BASE 0xCC00
+
+typedef struct {
+  volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer
+  volatile uint32_t status;	         // error and done flags
+  volatile uint32_t hw_config;	         // see below
+  volatile uint32_t dummy[3];
+  volatile uint32_t irqs;
+  volatile uint32_t pri_enc_bp_status;
+  volatile uint32_t cycle_count;
+} buffer_pool_status_t;
+
+#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE)
+
+/*
+ * Buffer n's xfer is done.
+ * Clear this bit by issuing bp_clear_buf(n)
+ */
+#define BPS_DONE(n)     (0x00000001 << (n))
+#define BPS_DONE_0	BPS_DONE(0)
+#define BPS_DONE_1	BPS_DONE(1)
+#define BPS_DONE_2	BPS_DONE(2)
+#define BPS_DONE_3	BPS_DONE(3)
+#define BPS_DONE_4	BPS_DONE(4)
+#define BPS_DONE_5	BPS_DONE(5)
+#define BPS_DONE_6	BPS_DONE(6)
+#define BPS_DONE_7	BPS_DONE(7)
+
+/*
+ * Buffer n's xfer had an error.
+ * Clear this bit by issuing bp_clear_buf(n)
+ */
+#define BPS_ERROR(n)	(0x00000100 << (n))
+#define BPS_ERROR_0	BPS_ERROR(0)
+#define BPS_ERROR_1	BPS_ERROR(1)
+#define BPS_ERROR_2	BPS_ERROR(2)
+#define BPS_ERROR_3	BPS_ERROR(3)
+#define BPS_ERROR_4	BPS_ERROR(4)
+#define BPS_ERROR_5	BPS_ERROR(5)
+#define BPS_ERROR_6	BPS_ERROR(6)
+#define BPS_ERROR_7	BPS_ERROR(7)
+
+/*
+ * Buffer n is idle.  A buffer is idle if it's not
+ * DONE, ERROR, or processing a transaction.  If it's
+ * IDLE, it's safe to start a new transaction.
+ *
+ * Clear this bit by starting a xfer with
+ * bp_send_from_buf or bp_receive_to_buf.
+ */
+#define BPS_IDLE(n)     (0x00010000 << (n))
+#define BPS_IDLE_0	BPS_IDLE(0)
+#define BPS_IDLE_1	BPS_IDLE(1)
+#define BPS_IDLE_2	BPS_IDLE(2)
+#define BPS_IDLE_3	BPS_IDLE(3)
+#define BPS_IDLE_4	BPS_IDLE(4)
+#define BPS_IDLE_5	BPS_IDLE(5)
+#define BPS_IDLE_6	BPS_IDLE(6)
+#define BPS_IDLE_7	BPS_IDLE(7)
+
+/*
+ * Buffer n has a "slow path" packet in it.
+ * This bit is orthogonal to the bits above and indicates that
+ * the FPGA ethernet rx protocol engine has identified this packet
+ * as one requiring firmware intervention.
+ */
+#define BPS_SLOWPATH(n) (0x01000000 << (n))
+#define BPS_SLOWPATH_0	BPS_SLOWPATH(0)
+#define BPS_SLOWPATH_1	BPS_SLOWPATH(1)
+#define BPS_SLOWPATH_2	BPS_SLOWPATH(2)
+#define BPS_SLOWPATH_3	BPS_SLOWPATH(3)
+#define BPS_SLOWPATH_4	BPS_SLOWPATH(4)
+#define BPS_SLOWPATH_5	BPS_SLOWPATH(5)
+#define BPS_SLOWPATH_6	BPS_SLOWPATH(6)
+#define BPS_SLOWPATH_7	BPS_SLOWPATH(7)
+
+
+#define BPS_DONE_ALL	  0x000000ff	// mask of all dones
+#define BPS_ERROR_ALL	  0x0000ff00	// mask of all errors
+#define BPS_IDLE_ALL      0x00ff0000	// mask of all idles
+#define BPS_SLOWPATH_ALL  0xff000000	// mask of all slowpaths
+
+// The hw_config register
+
+#define	HWC_SIMULATION		0x80000000
+#define	HWC_WB_CLK_DIV_MASK	0x0000000f
+
+/*!
+ * \brief return non-zero if we're running under the simulator
+ */
+inline static int
+hwconfig_simulation_p(void)
+{
+  return buffer_pool_status->hw_config & HWC_SIMULATION;
+}
+
+/*!
+ * \brief Return Wishbone Clock divisor.
+ * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor.
+ */
+inline static int
+hwconfig_wishbone_divisor(void)
+{
+  return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK;
+}
+
+///////////////////////////////////////////////////
+// Ethernet Core, Slave 6
+
+#define ETH_BASE 0xD000
+
+#include "eth_mac_regs.h"
+
+#define eth_mac ((eth_mac_regs_t *) ETH_BASE)
+
+////////////////////////////////////////////////////
+// Settings Bus, Slave #7, Not Byte Addressable!
+//
+// Output-only from processor point-of-view.
+// 1KB of address space (== 256 32-bit write-only regs)
+
+
+#define MISC_OUTPUT_BASE        0xD400
+#define	TX_PROTOCOL_ENGINE_BASE 0xD480
+#define	RX_PROTOCOL_ENGINE_BASE 0xD4C0
+#define BUFFER_POOL_CTRL_BASE   0xD500
+#define LAST_SETTING_REG        0xD7FC	// last valid setting register
+
+#define SR_MISC 0
+#define SR_TX_PROT_ENG 32
+#define SR_RX_PROT_ENG 48
+#define SR_BUFFER_POOL_CTRL 64
+#define SR_UDP_SM 96
+#define SR_TX_DSP 208
+#define SR_TX_CTRL 224
+#define SR_RX_DSP 160
+#define SR_RX_CTRL 176
+#define SR_TIME64 192
+#define SR_SIMTIMER 198
+#define SR_LAST 255
+
+#define	_SR_ADDR(sr)	(MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t))
+
+// --- buffer pool control regs ---
+
+typedef struct {
+  volatile uint32_t ctrl;
+} buffer_pool_ctrl_t;
+
+// buffer pool ports
+
+#define	PORT_SERDES	0	// serial/deserializer
+#define	PORT_DSP	1	// DSP tx or rx pipeline
+#define	PORT_ETH	2	// ethernet tx or rx
+#define	PORT_RAM	3	// RAM tx or rx
+
+// the buffer pool ctrl register fields
+
+#define BPC_BUFFER(n) (((n) & 0xf) << 28)
+#define   BPC_BUFFER_MASK      BPC_BUFFER(~0)
+#define   BPC_BUFFER_0	       BPC_BUFFER(0)
+#define   BPC_BUFFER_1	       BPC_BUFFER(1)
+#define   BPC_BUFFER_2	       BPC_BUFFER(2)
+#define   BPC_BUFFER_3	       BPC_BUFFER(3)
+#define   BPC_BUFFER_4	       BPC_BUFFER(4)
+#define   BPC_BUFFER_5	       BPC_BUFFER(5)
+#define   BPC_BUFFER_6	       BPC_BUFFER(6)
+#define   BPC_BUFFER_7	       BPC_BUFFER(7)
+#define	  BPC_BUFFER_NIL       BPC_BUFFER(0x8)	// disable
+
+#define BPC_PORT(n) (((n) & 0x7) << 25)
+#define   BPC_PORT_MASK        BPC_PORT(~0)
+#define   BPC_PORT_SERDES      BPC_PORT(PORT_SERDES)
+#define   BPC_PORT_DSP	       BPC_PORT(PORT_DSP)
+#define   BPC_PORT_ETH         BPC_PORT(PORT_ETH)
+#define   BPC_PORT_RAM         BPC_PORT(PORT_RAM)
+#define   BPC_PORT_NIL	       BPC_PORT(0x4)   	// disable
+
+#define	BPC_CLR	       	       (1 << 24)  // mutually excl commands
+#define	BPC_READ	       (1 << 23)
+#define BPC_WRITE              (1 << 22)
+
+#define BPC_STEP(step) (((step) & 0xf) << 18)
+#define   BPC_STEP_MASK	       BPC_STEP(~0)
+#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9)
+#define   BPC_LAST_LINE_MASK   BPC_LAST_LINE(~0)
+#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0)
+#define   BPC_FIRST_LINE_MASK  BPC_FIRST_LINE(~0)
+
+#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE)
+
+// --- misc outputs ---
+
+typedef struct {
+  volatile uint32_t	clk_ctrl;
+  volatile uint32_t	serdes_ctrl;
+  volatile uint32_t	adc_ctrl;
+  volatile uint32_t	leds;
+  volatile uint32_t	phy_ctrl;	// LSB is reset line to eth phy
+  volatile uint32_t	debug_mux_ctrl;
+  volatile uint32_t     ram_page;       // FIXME should go somewhere else...
+  volatile uint32_t     flush_icache;   // Flush the icache
+  volatile uint32_t     led_src;        // HW or SW control for LEDs
+} output_regs_t;
+
+#define CLK_RESET  (1<<4)
+#define CLK_ENABLE (1<<3) | (1<<2)
+#define CLK_SEL    (1<<1) | (1<<0)
+
+#define SERDES_ENABLE 8
+#define SERDES_PRBSEN 4
+#define SERDES_LOOPEN 2
+#define SERDES_RXEN   1
+
+#define	ADC_CTRL_ON	0x0F
+#define	ADC_CTRL_OFF	0x00
+
+// crazy order that matches the labels on the case
+
+#define	LED_A		(1 << 4)
+#define	LED_B		(1 << 1)
+#define	LED_C		(1 << 3)
+#define	LED_D		(1 << 0)
+#define	LED_E		(1 << 2)
+//      LED_F		// controlled by CPLD
+#define	LED_RJ45	(1 << 5)
+
+#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE)
+
+// --- udp tx regs ---
+
+typedef struct {
+  // Bits 19:16 are control info; bits 15:0 are data (see below)
+  // First two words are unused.
+  volatile uint32_t _nope[2];
+  //--- ethernet header - 14 bytes---
+  volatile struct{
+    uint32_t mac_dst_0_1; //word 2
+    uint32_t mac_dst_2_3;
+    uint32_t mac_dst_4_5;
+    uint32_t mac_src_0_1;
+    uint32_t mac_src_2_3;
+    uint32_t mac_src_4_5;
+    uint32_t ether_type; //word 8
+  } eth_hdr;
+  //--- ip header - 20 bytes ---
+  volatile struct{
+    uint32_t ver_ihl_tos; //word 9
+    uint32_t total_length;
+    uint32_t identification;
+    uint32_t flags_frag_off;
+    uint32_t ttl_proto;
+    uint32_t checksum;
+    uint32_t src_addr_high;
+    uint32_t src_addr_low;
+    uint32_t dst_addr_high;
+    uint32_t dst_addr_low; //word 18
+  } ip_hdr;
+  //--- udp header - 8 bytes ---
+  volatile struct{
+    uint32_t src_port; //word 19
+    uint32_t dst_port;
+    uint32_t length;
+    uint32_t checksum; //word 22
+  } udp_hdr;
+  volatile uint32_t _pad[32-23];
+} sr_udp_sm_t;
+
+// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive)
+
+// This is the last word of the header
+#define	UDP_SM_LAST_WORD		(1 << 19)
+
+// Insert IP header checksum here.  Data is the xor of 16'hFFFF and
+// the values written into regs 9-13 and 15-18.
+#define	UDP_SM_INS_IP_HDR_CHKSUM	(1 << 18)
+
+// Insert IP Length here (data ignored)
+#define	UDP_SM_INS_IP_LEN		(1 << 17)
+
+// Insert UDP Length here (data ignore)
+#define	UDP_SM_INS_UDP_LEN		(1 << 16)
+
+#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM))
+
+// --- dsp tx regs ---
+
+#define MIN_CIC_INTERP	1
+#define	MAX_CIC_INTERP  128
+
+typedef struct {
+  volatile uint32_t     num_chan;
+  volatile uint32_t     clear_state;	// clears out state machine, fifos,
+} sr_tx_ctrl_t;
+
+#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL))
+
+typedef struct {
+  volatile int32_t	freq;
+  volatile uint32_t	scale_iq;	// {scale_i,scale_q}
+  volatile uint32_t     interp_rate;
+  volatile uint32_t     _padding0;      // padding for the tx_mux
+                                        //   NOT freq, scale, interp
+  /*!
+   * \brief output mux configuration.
+   *
+   * <pre>
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                                               | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are N DUCs (1 now) with complex inputs and outputs.
+   *  There are two DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC
+   *  Each subfield is coded like this: 
+   * 
+   *     3 2 1 0
+   *    +-------+
+   *    |   N   |
+   *    +-------+
+   * 
+   *  N specifies which DUC output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   DUC 0 I
+   *   1   DUC 0 Q
+   *   2   DUC 1 I
+   *   3   DUC 1 Q
+   *   F   All Zeros
+   *   
+   * The default value is 0x10
+   * </pre>
+   */
+  volatile uint32_t	tx_mux;
+
+} dsp_tx_regs_t;
+  
+#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP))
+
+// --- VITA RX CTRL regs ---
+typedef struct {
+  // The following 3 are logically a single command register.
+  // They are clocked into the underlying fifo when time_ticks is written.
+  volatile uint32_t	cmd;		// {now, chain, num_samples(30)
+  volatile uint32_t	time_secs;
+  volatile uint32_t	time_ticks;
+
+  volatile uint32_t	clear_overrun;	// write anything to clear overrun
+  volatile uint32_t	vrt_header;	// word 0 of packet.  FPGA fills in packet counter
+  volatile uint32_t	vrt_stream_id;	// word 1 of packet. 
+  volatile uint32_t	vrt_trailer;
+  volatile uint32_t	nsamples_per_pkt;
+  volatile uint32_t     nchannels;      // 1 in basic case, up to 4 for vector sources
+  volatile uint32_t     pad[7];         // Make each structure 16 elements long
+} sr_rx_ctrl_t;
+
+#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL))
+
+// --- dsp rx regs ---
+#define	MIN_CIC_DECIM	1
+#define	MAX_CIC_DECIM   128
+
+typedef struct {
+  volatile int32_t	freq;
+  volatile uint32_t	scale_iq;	// {scale_i,scale_q}
+  volatile uint32_t     decim_rate;
+  volatile uint32_t     dcoffset_i;     // Bit 31 high sets fixed offset mode, using lower 14 bits,
+                                        // otherwise it is automatic 
+  volatile uint32_t     dcoffset_q;     // Bit 31 high sets fixed offset mode, using lower 14 bits
+
+  /*!
+   * \brief input mux configuration.
+   *
+   * This determines which ADC (or constant zero) is connected to 
+   * each DDC input.  There are N DDCs (1 now).  Each has two inputs.
+   *
+   * <pre>
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |                                                       |Q0 |I0 |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   *
+   * The default value is 0x4
+   * </pre>
+   */
+  volatile uint32_t     rx_mux;        // called adc_mux in dsp_core_rx.v
+
+  /*!
+   * \brief Streaming GPIO configuration
+   *
+   * This determines whether the LSBs of I and Q samples come from the DSP
+   * pipeline or from the io_rx GPIO pins.  To stream GPIO, one must first
+   * set the GPIO data direction register to have io_rx[15] and/or io_rx[14]
+   * configured as inputs.  The GPIO pins will be sampled at the time the
+   * remainder of the DSP sample is strobed into the RX sample FIFO.  There
+   * will be a decimation-dependent fixed time offset between the GPIO
+   * sample stream and the associated RF samples.
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |                           MBZ                             |Q|I|
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * I         0=LSB comes from DSP pipeline (default)
+   *           1=LSB comes from io_rx[15]
+   * 
+   * Q         0=LSB comes from DSP pipeline (default)
+   *           1=LSB comes from io_rx[14]
+   */
+  volatile uint32_t gpio_stream_enable;
+
+} dsp_rx_regs_t;
+  
+#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP))
+
+// ----------------------------------------------------------------
+// VITA49 64 bit time (write only)
+  /*!
+   * \brief Time 64 flags
+   *
+   * <pre>
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * </pre>
+   */
+typedef struct {
+  volatile uint32_t	secs;	// value to set absolute secs to on next PPS
+  volatile uint32_t	ticks;	// value to set absolute ticks to on next PPS
+  volatile uint32_t flags;  // flags - see chart above
+  volatile uint32_t imm;    // set immediate (0=latch on next pps, 1=latch immediate, default=0)
+} sr_time64_t;
+
+#define sr_time64 ((sr_time64_t *) _SR_ADDR(SR_TIME64))
+
+
+/* 
+ * --- ethernet tx protocol engine regs (write only) ---
+ *
+ * These registers control the transmit portion of the ethernet
+ * protocol engine (out of USRP2).  The protocol engine handles fifo
+ * status and sequence number insertion in outgoing packets, and
+ * automagically generates status packets when required to inform the
+ * host of changes in fifo availability.
+ *
+ * All outgoing packets have their fifo_status field set to the number
+ * of 32-bit lines of fifo available in the ethernet Rx fifo (see
+ * usrp2_eth_packet.h).  Seqno's are set if FIXME, else 0.
+ *
+ * FIXME clean this up once we know how it's supposed to behave.
+ */
+
+typedef struct {
+  volatile uint32_t  flags;	     // not yet fully defined (channel?)
+  volatile uint32_t  mac_dst0123;    // 4 bytes of destination mac addr
+  volatile uint32_t  mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
+  volatile uint32_t  mac_src2345;    // 4 bytes of destination mac addr
+  volatile uint32_t  seqno;	     // Write to init seqno.  It autoincs on match
+} tx_proto_engine_regs_t;
+
+#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE)
+
+/*
+ * --- ethernet rx protocol engine regs (write only) ---
+ *
+ * These registers control the receive portion of the ethernet
+ * protocol engine (into USRP2).  The protocol engine offloads common
+ * packet inspection operations so that firmware has less to do on
+ * "fast path" packets.
+ *
+ * The registers define conditions which must be matched for a packet
+ * to be considered a "fast path" packet.  If a received packet
+ * matches the src and dst mac address, ethertype, flags field, and
+ * expected seqno number it is considered a "fast path" packet, and
+ * the expected seqno is updated.  If the packet fails to satisfy any
+ * of the above conditions it's a "slow path" packet, and the
+ * corresponding SLOWPATH flag will be set buffer_status register.
+ */
+
+typedef struct {
+  volatile uint32_t  flags;	     // not yet fully defined (channel?)
+  volatile uint32_t  mac_dst0123;    // 4 bytes of destination mac addr
+  volatile uint32_t  mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr
+  volatile uint32_t  mac_src2345;    // 4 bytes of destination mac addr
+  volatile uint32_t  ethertype_pad;  // ethertype in high 16-bits
+} rx_proto_engine_regs_t;
+
+#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE)
+
+
+
+///////////////////////////////////////////////////
+// Simple Programmable Interrupt Controller, Slave 8
+
+#define PIC_BASE  0xD800
+
+// Interrupt request lines
+// Bit numbers (LSB == 0) that correpond to interrupts into PIC
+
+#define	IRQ_BUFFER	0	// buffer manager
+#define	IRQ_ONETIME	1
+#define	IRQ_SPI		2
+#define	IRQ_I2C		3
+#define	IRQ_PHY		4	// ethernet PHY
+#define	IRQ_UNDERRUN	5
+#define	IRQ_OVERRUN	6
+#define	IRQ_PPS		7	// pulse per second
+#define	IRQ_UART_RX	8
+#define	IRQ_UART_TX	9
+#define	IRQ_SERDES	10
+#define	IRQ_CLKSTATUS	11
+#define IRQ_PERIODIC    12
+
+#define IRQ_TO_MASK(x) (1 << (x))
+
+#define PIC_BUFFER_INT    IRQ_TO_MASK(IRQ_BUFFER)
+#define PIC_ONETIME_INT   IRQ_TO_MASK(IRQ_ONETIME)
+#define PIC_SPI_INT       IRQ_TO_MASK(IRQ_SPI)
+#define PIC_I2C_INT       IRQ_TO_MASK(IRQ_I2C)
+#define PIC_PHY_INT       IRQ_TO_MASK(IRQ_PHY)
+#define PIC_UNDERRUN_INT  IRQ_TO_MASK(IRQ_UNDERRUN)
+#define PIC_OVERRUN_INT   IRQ_TO_MASK(IRQ_OVERRUN)
+#define PIC_PPS_INT   	  IRQ_TO_MASK(IRQ_PPS)
+#define PIC_UART_RX_INT   IRQ_TO_MASK(IRQ_UART_RX)
+#define PIC_UART_TX_INT   IRQ_TO_MASK(IRQ_UART_TX)
+#define PIC_SERDES        IRQ_TO_MASK(IRQ_SERDES)
+#define PIC_CLKSTATUS     IRQ_TO_MASK(IRQ_CLKSTATUS)
+
+typedef struct {
+  volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level
+  volatile uint32_t polarity;	 // mask: 1 -> rising edge
+  volatile uint32_t mask;	 // mask: 1 -> disabled
+  volatile uint32_t pending;	 // mask: 1 -> pending; write 1's to clear pending ints
+} pic_regs_t;
+
+#define pic_regs ((pic_regs_t *) PIC_BASE)
+
+// ----------------------------------------------------------------
+// WB_CLK_RATE is the time base for this
+typedef struct {
+  volatile uint32_t	onetime;   // Number of wb clk cycles till the onetime interrupt
+  volatile uint32_t	periodic;  // Repeat rate of periodic interrupt
+} sr_simple_timer_t;
+
+#define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER))
+
+///////////////////////////////////////////////////
+// UART, Slave 10
+
+#define UART_BASE  0xE000
+
+typedef struct {
+  //  All elements are 8 bits except for clkdiv (16), but we use uint32 to make 
+  //    the hardware for decoding easier
+  volatile uint32_t clkdiv;  // Set to 50e6 divided by baud rate (no x16 factor)
+  volatile uint32_t txlevel; // Number of spaces in the FIFO for writes
+  volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads
+  volatile uint32_t txchar;  // Write characters to be sent here
+  volatile uint32_t rxchar;  // Read received characters here
+} uart_regs_t;
+
+#define uart_regs ((uart_regs_t *) UART_BASE)
+
+///////////////////////////////////////////////////
+// ATR Controller, Slave 11
+
+#define ATR_BASE  0xE400
+
+typedef struct {
+  volatile uint32_t	v[16];
+} atr_regs_t;
+
+#define	ATR_IDLE	0x0	// indicies into v
+#define ATR_TX		0x1
+#define	ATR_RX		0x2
+#define	ATR_FULL	0x3
+
+#define atr_regs ((atr_regs_t *) ATR_BASE)
+
+///////////////////////////////////////////////////
+// SD Card SPI interface, Slave 13
+//   All regs are 8 bits wide, but are accessed as if they are 32 bits
+
+#define SDSPI_BASE  0xEC00
+
+typedef struct {
+  volatile uint32_t status;  // Write a 1 or 0 for controlling CS
+  volatile uint32_t clkdiv;
+  volatile uint32_t send_dat;
+  volatile uint32_t receive_dat;
+} sdspi_regs_t;
+
+#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE)
+
+///////////////////////////////////////////////////
+// External RAM interface, Slave 14
+//   Pages are 1K.  Page is 10 bits, set by a control register
+//    output_regs->ram_page
+
+#define EXTRAM_BASE 0xF000
+#define extram ((volatile uint32_t *) EXTRAM_BASE)
+
+
+///////////////////////////////////////////////////
+
+#endif
+
diff --git a/firmware/microblaze/usrp2/sd.c b/firmware/microblaze/usrp2/sd.c
new file mode 100644
index 000000000..d000b28ae
--- /dev/null
+++ b/firmware/microblaze/usrp2/sd.c
@@ -0,0 +1,197 @@
+/* -*- c -*- */
+/*
+ * Copyright 2008 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sd.h"
+#include "memory_map.h"
+#include "stdint.h"
+#include "stdio.h"
+
+static inline void
+sd_packarg(unsigned char *argument,unsigned int value)
+{
+  argument[3] = (unsigned char)(value >> 24);
+  argument[2] = (unsigned char)(value >> 16);
+  argument[1] = (unsigned char)(value >> 8);
+  argument[0] = (unsigned char)(value);
+}
+
+int
+sd_init(void)
+{
+  unsigned char response[5];
+  unsigned char argument[4];
+  int i,j;
+
+  for(i=0;i<4;i++)
+    argument[i] = 0;
+
+  // Set clock to less than 400 kHz to start out
+  sdspi_regs->clkdiv = 128;
+
+  // Delay at least 74 cycles
+  sd_assert_cs();
+  for(i = 0; i < 100; i++)
+    sd_send_byte(SD_IDLE);
+  sd_deassert_cs();
+  
+  // Initialization Sequence -- CMD0 CMD55 ACMD41 CMD58
+  // Put card in idle state
+  if(sd_send_command(SD_CMD0,SD_CMD0_R,response,argument)==0)
+    return 0;  // Something went wrong in command
+
+  j = 0;
+  do {
+    j++;
+    if(sd_send_command(SD_CMD55,SD_CMD55_R,response,argument)==1)
+      sd_send_command(SD_ACMD41,SD_ACMD41_R,response,argument);
+    else
+      j = SD_IDLE_WAIT_MAX;
+  }
+  while(((response[0] & SD_MSK_IDLE) == SD_MSK_IDLE) && (j < SD_IDLE_WAIT_MAX));
+
+  if(j>= SD_IDLE_WAIT_MAX)  // IDLE timeout exceeded, card asleep
+    return 0;
+  
+  // CMD58 reads the SD card capabilities
+  if(sd_send_command(SD_CMD58,SD_CMD58_R,response,argument)==0)
+    return 0;  // CMD58 FAIL
+
+  if((response[2] & SD_MSK_OCR_33) != SD_MSK_OCR_33)
+    return 0;  // Card doesn't do 3.3V
+
+  //printf("OCR = %x %x %x %x\n",response[0],response[1],response[2],response[3]);
+
+  // Set blocklen here
+  sd_packarg(argument,SD_BLOCKLEN);
+  if(sd_send_command(SD_CMD16,SD_CMD16_R,response,argument)==0)
+    return 0;    // Set Blocklen failed
+  
+  // Reset back to high speed
+  sdspi_regs->clkdiv = 4;
+  //puts("finished init\n");
+  return 1;
+}
+
+int sd_send_command(unsigned char cmd,unsigned char response_type,
+		    unsigned char *response,unsigned char *argument)
+{
+  int i;
+  char response_length;
+  unsigned char tmp;
+
+  sd_assert_cs();
+  sd_send_byte((cmd & 0x3F) | 0x40);
+  for(i=3;i>=0;i--)
+    sd_send_byte(argument[i]);
+  sd_send_byte(SD_CRC);   // Always the same
+
+  response_length = 0;
+  switch(response_type)
+    {
+    case SD_R1:
+    case SD_R1B:
+      response_length = 1;
+      break;
+    case SD_R2:
+      response_length = 2;
+      break;
+    case SD_R3:
+      response_length = 5;
+      break;
+    default:
+      break;
+    }
+
+  // Wait for a response, which will have a 0 start bit
+  i = 0;
+  do
+    {
+      tmp = sd_rcv_byte();
+      i++;
+    }
+  while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT);
+
+  if(i>= SD_CMD_TIMEOUT)
+    {
+      sd_deassert_cs();
+      //puts("cmd send timeout\n");
+      return 0;
+    }
+
+  for(i=response_length-1; i>=0; i--)
+    {
+      response[i] = tmp;
+      tmp = sd_rcv_byte();
+    }
+  i = 0;
+  if(response_type == SD_R1B)
+    {
+      do
+	{
+	  i++;
+	  tmp = sd_rcv_byte();
+	}
+      while(tmp != SD_IDLE);
+      sd_send_byte(SD_IDLE);
+    }
+  
+  //puts("send cmd success\n");
+  sd_deassert_cs();
+  return 1;
+}
+
+int
+sd_read_block (unsigned int blockaddr, unsigned char *buf)
+{
+  unsigned char response[5];
+  unsigned char argument[4];
+  unsigned int i = 0;
+  unsigned char tmp;
+
+  blockaddr <<= SD_BLOCKLEN_NBITS;
+  sd_packarg(argument,blockaddr);
+  if(sd_send_command(SD_CMD17,SD_CMD17_R,response,argument)==0)
+    return 0;    //Failed READ;
+  if(response[0] != 0)
+    return 0;    //Misaligned READ
+
+  sd_assert_cs();
+  i = 0;
+  do
+    {
+      tmp = sd_rcv_byte();
+      i++;
+    }
+  while((tmp == 0xFF) && (i < SD_RD_TIMEOUT));
+  if((i>= SD_RD_TIMEOUT) ||((tmp & SD_MSK_TOK_DATAERROR) == 0))
+    {
+      sd_send_byte(SD_IDLE);  // Send a dummy before quitting
+      return 0;   // Data ERROR
+    }
+  for(i=0;i<SD_BLOCKLEN;i++)
+    buf[i] = sd_rcv_byte();
+  return 1;
+
+}
+
+int
+sd_write_block(unsigned int blockaddr, const unsigned char *buf)
+{
+  // FIXME not implemented yet
+  return 0;
+}
diff --git a/firmware/microblaze/usrp2/sd.h b/firmware/microblaze/usrp2/sd.h
new file mode 100644
index 000000000..e2d0ae38e
--- /dev/null
+++ b/firmware/microblaze/usrp2/sd.h
@@ -0,0 +1,122 @@
+/* -*- c -*- */
+/*
+ * Copyright 2008 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_SD_H
+#define INCLUDED_SD_H
+
+#include "memory_map.h"
+
+#define SD_READY 1
+#define SD_IDLE_WAIT_MAX 100
+#define SD_CMD_TIMEOUT 100
+#define SD_RD_TIMEOUT 1000
+
+#define SD_CMD0 0
+#define SD_CMD1 1
+#define SD_CMD9 9
+#define SD_CMD10 10
+#define SD_CMD12 12
+#define SD_CMD13 13
+#define SD_CMD16 16
+#define SD_CMD17 17 
+#define SD_CMD18 18
+#define SD_CMD24 24
+#define SD_CMD25 25
+#define SD_CMD27 27
+#define SD_CMD28 28
+#define SD_CMD29 29
+#define SD_CMD30 30
+#define SD_CMD32 32
+#define SD_CMD33 33
+#define SD_CMD38 38
+#define SD_CMD55 55
+#define SD_CMD58 58
+#define SD_CMD59 59
+#define SD_ACMD41 41
+#define SD_IDLE 0xFF
+#define SD_CRC 0x95
+
+#define SD_R1 1
+#define SD_R1B 2
+#define SD_R2 3
+#define SD_R3 4
+
+#define SD_CMD0_R SD_R1
+#define SD_CMD16_R SD_R1
+#define SD_CMD17_R SD_R1
+#define SD_CMD55_R SD_R1
+#define SD_ACMD41_R SD_R1
+#define SD_CMD58_R SD_R3
+
+#define SD_BLOCKLEN 512
+#define SD_BLOCKLEN_NBITS 9
+
+#define SD_MSK_IDLE 0x01
+#define SD_MSK_OCR_33 0xC0
+#define SD_MSK_TOK_DATAERROR 0xE0
+
+
+int sd_init(void);
+
+static inline void
+sd_assert_cs(void)
+{
+  // Wait for idle before doing anything
+  while(sdspi_regs->status != SD_READY)
+    ;
+  sdspi_regs->status = 1;
+}
+
+static inline void
+sd_deassert_cs(void)
+{
+  // Wait for idle before doing anything
+  while(sdspi_regs->status != SD_READY)
+    ;
+  sdspi_regs->status = 0;
+}
+
+static inline char
+sd_rcv_byte(void)
+{
+  // Wait for idle before doing anything
+  while(sdspi_regs->status != SD_READY)
+    ;
+  sdspi_regs->send_dat = SD_IDLE;
+  while(sdspi_regs->status != SD_READY)
+    ;
+  return sdspi_regs-> receive_dat;
+}
+
+static inline void
+sd_send_byte(char dat)
+{
+  // Wait for idle before doing anything
+  while(sdspi_regs->status != SD_READY)
+    ;      // Wait for status = 1 (ready)
+  sdspi_regs->send_dat = dat;
+}
+
+
+int sd_send_command(unsigned char cmd,unsigned char response_type,
+		    unsigned char *response,unsigned char *argument);
+
+int sd_read_block (unsigned int blockaddr, unsigned char *buf);
+int sd_write_block(unsigned int blockaddr, const unsigned char *buf);
+
+#endif /* INCLUDED_SD_H */
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index 76b27fd31..7951e00d6 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -38,7 +38,7 @@ Run the following commands:
     ./configure --host=mb
     make
 
-*The image file will be ./apps/txrx_uhd.bin*
+*The image file will be ./usrp2/usrp2_txrx_uhd.bin*
 
 ------------------------------------------------------------------------
 Load the images onto the SD card
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 8942f9d31..0aeb0ec1a 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -35,8 +35,8 @@ using namespace uhd::usrp;
  **********************************************************************/
 void usrp2_mboard_impl::dboard_init(void){
     //read the dboard eeprom to extract the dboard ids
-    _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));
-    _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));
+    _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(USRP2_I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));
+    _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(USRP2_I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));
 
     //create a new dboard interface and manager
     _dboard_iface = make_usrp2_dboard_iface(_iface, _clock_ctrl);
@@ -111,7 +111,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
 
     case DBOARD_PROP_DBOARD_ID:
         _rx_db_eeprom.id = val.as<dboard_id_t>();
-        _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes());
+        _iface->write_eeprom(USRP2_I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes());
         return;
 
     default: UHD_THROW_PROP_SET_ERROR();
@@ -170,7 +170,7 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){
 
     case DBOARD_PROP_DBOARD_ID:
         _tx_db_eeprom.id = val.as<dboard_id_t>();
-        _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());
+        _iface->write_eeprom(USRP2_I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes());
         return;
 
     default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index fd728e393..c4dabf5bc 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -44,6 +44,22 @@ extern "C" {
 #define USRP2_UDP_CTRL_PORT 49152
 #define USRP2_UDP_DATA_PORT 49153
 
+////////////////////////////////////////////////////////////////////////
+// I2C addresses
+////////////////////////////////////////////////////////////////////////
+#define USRP2_I2C_DEV_EEPROM  0x50 // 24LC02[45]:  7-bits 1010xxx
+#define	USRP2_I2C_ADDR_MBOARD (USRP2_I2C_DEV_EEPROM | 0x0)
+#define	USRP2_I2C_ADDR_TX_DB  (USRP2_I2C_DEV_EEPROM | 0x4)
+#define	USRP2_I2C_ADDR_RX_DB  (USRP2_I2C_DEV_EEPROM | 0x5)
+
+////////////////////////////////////////////////////////////////////////
+// EEPROM Layout
+////////////////////////////////////////////////////////////////////////
+#define USRP2_EE_MBOARD_REV_LSB  0x00 //1 byte
+#define USRP2_EE_MBOARD_REV_MSB  0x01 //1 byte
+#define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes
+#define USRP2_EE_MBOARD_IP_ADDR  0x0C //uint32, big-endian
+
 typedef enum{
     USRP2_CTRL_ID_HUH_WHAT = ' ',
     //USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 3d103c940..7694a164d 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -45,8 +45,8 @@ usrp2_mboard_impl::usrp2_mboard_impl(
     _iface = usrp2_iface::make(ctrl_transport);
 
     //extract the mboard rev numbers
-    _rev_lo = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_REV_LSB, 1).at(0);
-    _rev_hi = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_REV_MSB, 1).at(0);
+    _rev_lo = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, 1).at(0);
+    _rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0);
 
     //contruct the interfaces to mboard perifs
     _clock_ctrl = usrp2_clock_ctrl::make(_iface);
@@ -185,14 +185,14 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
     //handle the other props
     if (key.type() == typeid(std::string)){
         if (key.as<std::string>() == "mac-addr"){
-            byte_vector_t bytes = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, 6);
+            byte_vector_t bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, 6);
             val = mac_addr_t::from_bytes(bytes).to_string();
             return;
         }
 
         if (key.as<std::string>() == "ip-addr"){
             boost::asio::ip::address_v4::bytes_type bytes;
-            std::copy(_iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, 4), bytes);
+            std::copy(_iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, 4), bytes);
             val = boost::asio::ip::address_v4(bytes).to_string();
             return;
         }
@@ -275,14 +275,14 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
     if (key.type() == typeid(std::string)){
         if (key.as<std::string>() == "mac-addr"){
             byte_vector_t bytes = mac_addr_t::from_string(val.as<std::string>()).to_bytes();
-            _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, bytes);
+            _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, bytes);
             return;
         }
 
         if (key.as<std::string>() == "ip-addr"){
             byte_vector_t bytes(4);
             std::copy(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_bytes(), bytes);
-            _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, bytes);
+            _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, bytes);
             return;
         }
     }
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index 9cc32104e..12fd4730a 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -26,22 +26,6 @@
 #include <utility>
 #include "fw_common.h"
 
-////////////////////////////////////////////////////////////////////////
-// I2C addresses
-////////////////////////////////////////////////////////////////////////
-#define I2C_DEV_EEPROM  0x50 // 24LC02[45]:  7-bits 1010xxx
-#define	I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0)
-#define	I2C_ADDR_TX_DB  (I2C_DEV_EEPROM | 0x4)
-#define	I2C_ADDR_RX_DB  (I2C_DEV_EEPROM | 0x5)
-
-////////////////////////////////////////////////////////////////////////
-// EEPROM Layout
-////////////////////////////////////////////////////////////////////////
-#define EE_MBOARD_REV_LSB  0x00 //1 byte
-#define EE_MBOARD_REV_MSB  0x01 //1 byte
-#define EE_MBOARD_MAC_ADDR 0x02 //6 bytes
-#define EE_MBOARD_IP_ADDR  0x0C //uint32, big-endian
-
 /*!
  * The usrp2 interface class:
  * Provides a set of functions to implementation layer.
-- 
cgit v1.2.3


From 4220097f99c37632d06de436fdd20772aad46fda Mon Sep 17 00:00:00 2001
From: Jason Abele <jason@ettus.com>
Date: Thu, 29 Jul 2010 13:38:29 -0700
Subject: Fixes gain range for rfx400 vs other rfx

---
 host/lib/usrp/dboard/db_rfx.cpp | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 914ca5e19..664b406d9 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -43,6 +43,7 @@
 #include <uhd/utils/assert.hpp>
 #include <uhd/utils/static.hpp>
 #include <uhd/utils/algorithm.hpp>
+#include <uhd/usrp/dboard_id.hpp>
 #include <uhd/usrp/dboard_base.hpp>
 #include <uhd/usrp/dboard_manager.hpp>
 #include <boost/assign/list_of.hpp>
@@ -65,6 +66,10 @@ static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2");
 static const uhd::dict<std::string, gain_range_t> rfx_tx_gain_ranges; //empty
 
 static const uhd::dict<std::string, gain_range_t> rfx_rx_gain_ranges = map_list_of
+    ("PGA0", gain_range_t(0, 70, float(0.022)))
+;
+
+static const uhd::dict<std::string, gain_range_t> rfx400_rx_gain_ranges = map_list_of
     ("PGA0", gain_range_t(0, 45, float(0.022)))
 ;
 
@@ -88,6 +93,7 @@ public:
 
 private:
     freq_range_t _freq_range;
+    uhd::dict<std::string, gain_range_t> _rx_gain_ranges;
     uhd::dict<dboard_iface::unit_t, bool> _div2;
     double       _rx_lo_freq, _tx_lo_freq;
     std::string  _rx_ant;
@@ -166,6 +172,14 @@ rfx_xcvr::rfx_xcvr(
     _div2[dboard_iface::UNIT_RX] = rx_div2;
     _div2[dboard_iface::UNIT_TX] = tx_div2;
 
+    if(this->get_rx_id() == 0x0024) { //RFX400
+        _rx_gain_ranges = rfx400_rx_gain_ranges;
+    }
+    else {
+        _rx_gain_ranges = rfx_rx_gain_ranges;
+    }
+
+
     //enable the clocks that we need
     this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
     this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
@@ -193,8 +207,8 @@ rfx_xcvr::rfx_xcvr(
     set_tx_lo_freq((_freq_range.min + _freq_range.max)/2.0);
     set_rx_ant("RX2");
 
-    BOOST_FOREACH(const std::string &name, rfx_rx_gain_ranges.keys()){
-        set_rx_gain(rfx_rx_gain_ranges[name].min, name);
+    BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){
+        set_rx_gain(_rx_gain_ranges[name].min, name);
     }
 }
 
@@ -247,7 +261,7 @@ void rfx_xcvr::set_tx_gain(float, const std::string &name){
 }
 
 void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
-    assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name");
+    assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
     if(name == "PGA0"){
         float dac_volts = rx_pga0_gain_to_dac_volts(gain);
         _rx_gains[name] = gain;
@@ -402,12 +416,12 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
         return;
 
     case SUBDEV_PROP_GAIN_RANGE:
-        assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name");
-        val = rfx_rx_gain_ranges[name];
+        assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
+        val = _rx_gain_ranges[name];
         return;
 
     case SUBDEV_PROP_GAIN_NAMES:
-        val = prop_names_t(rfx_rx_gain_ranges.keys());
+        val = prop_names_t(_rx_gain_ranges.keys());
         return;
 
     case SUBDEV_PROP_FREQ:
-- 
cgit v1.2.3


From 94e7cec66a2d3efe6be5f12455644c4547b61a9c Mon Sep 17 00:00:00 2001
From: Jason Abele <jason@ettus.com>
Date: Mon, 2 Aug 2010 17:40:30 -0700
Subject: Propogate gain range into RX pga0 helper for RFX boards

---
 host/lib/usrp/dboard/db_rfx.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 664b406d9..b6b44199a 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -241,10 +241,10 @@ void rfx_xcvr::set_tx_ant(const std::string &ant){
 /***********************************************************************
  * Gain Handling
  **********************************************************************/
-static float rx_pga0_gain_to_dac_volts(float &gain){
+static float rx_pga0_gain_to_dac_volts(float &gain, float range){
     //voltage level constants (negative slope)
     static const float max_volts = float(.2), min_volts = float(1.2);
-    static const float slope = (max_volts-min_volts)/45;
+    static const float slope = (max_volts-min_volts)/(range);
 
     //calculate the voltage for the aux dac
     float dac_volts = std::clip<float>(gain*slope + min_volts, max_volts, min_volts);
@@ -263,7 +263,8 @@ void rfx_xcvr::set_tx_gain(float, const std::string &name){
 void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
     assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
     if(name == "PGA0"){
-        float dac_volts = rx_pga0_gain_to_dac_volts(gain);
+        float dac_volts = rx_pga0_gain_to_dac_volts(gain, 
+                              (_rx_gain_ranges["PGA0"].max - _rx_gain_ranges["PGA0"].min));
         _rx_gains[name] = gain;
 
         //write the new voltage to the aux dac
-- 
cgit v1.2.3


From fc66ef454c1b79cceb2b161c669bcf6fdfe87ee7 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 4 Aug 2010 12:28:58 -0700
Subject: usrp2: added mboard name call to dboard iface

---
 host/include/uhd/usrp/dboard_iface.hpp | 7 +++++++
 host/lib/usrp/usrp2/dboard_iface.cpp   | 2 ++
 2 files changed, 9 insertions(+)

(limited to 'host/lib')

diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp
index caf1e6ee6..fc7ea3052 100644
--- a/host/include/uhd/usrp/dboard_iface.hpp
+++ b/host/include/uhd/usrp/dboard_iface.hpp
@@ -22,6 +22,7 @@
 #include <uhd/types/serial.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/cstdint.hpp>
+#include <string>
 #include <vector>
 
 namespace uhd{ namespace usrp{
@@ -64,6 +65,12 @@ public:
         AUX_ADC_B = 'b'
     };
 
+    /*!
+     * Get the motherboard name of the form: usrp1, usrp2...
+     * \return string representing the motherboard name
+     */
+    virtual std::string get_mboard_name(void) = 0;
+
     /*!
      * Write to an aux dac.
      *
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 6f2fb9396..1b9a4bb97 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -37,6 +37,8 @@ public:
     usrp2_dboard_iface(usrp2_iface::sptr iface, usrp2_clock_ctrl::sptr clock_ctrl);
     ~usrp2_dboard_iface(void);
 
+    std::string get_mboard_name(void){return "usrp2";}
+
     void write_aux_dac(unit_t, aux_dac_t, float);
     float read_aux_adc(unit_t, aux_adc_t);
 
-- 
cgit v1.2.3


From 70abdef8f6c6d24a99caf8d3668f32094b159903 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Wed, 4 Aug 2010 14:50:35 -0700
Subject: uhd: moved utils cpp files into lib/utils directory

---
 host/lib/CMakeLists.txt            |   7 +-
 host/lib/gain_handler.cpp          | 177 -------------------------------------
 host/lib/load_modules.cpp          | 146 ------------------------------
 host/lib/thread_priority.cpp       |  98 --------------------
 host/lib/usrp/CMakeLists.txt       |   3 +
 host/lib/utils.cpp                 |  53 -----------
 host/lib/utils/CMakeLists.txt      |  26 ++++++
 host/lib/utils/assert.cpp          |  24 +++++
 host/lib/utils/gain_handler.cpp    | 177 +++++++++++++++++++++++++++++++++++++
 host/lib/utils/load_modules.cpp    | 146 ++++++++++++++++++++++++++++++
 host/lib/utils/props.cpp           |  43 +++++++++
 host/lib/utils/thread_priority.cpp |  98 ++++++++++++++++++++
 12 files changed, 518 insertions(+), 480 deletions(-)
 delete mode 100644 host/lib/gain_handler.cpp
 delete mode 100644 host/lib/load_modules.cpp
 delete mode 100644 host/lib/thread_priority.cpp
 delete mode 100644 host/lib/utils.cpp
 create mode 100644 host/lib/utils/CMakeLists.txt
 create mode 100644 host/lib/utils/assert.cpp
 create mode 100644 host/lib/utils/gain_handler.cpp
 create mode 100644 host/lib/utils/load_modules.cpp
 create mode 100644 host/lib/utils/props.cpp
 create mode 100644 host/lib/utils/thread_priority.cpp

(limited to 'host/lib')

diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 767029dc4..c93884d67 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -44,8 +44,7 @@ ENDMACRO(LIBUHD_PYTHON_GEN_SOURCE)
 INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/CMakeLists.txt)
 INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/transport/CMakeLists.txt)
 INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/CMakeLists.txt)
-INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/dboard/CMakeLists.txt)
-INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp2/CMakeLists.txt)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/utils/CMakeLists.txt)
 
 ########################################################################
 # Setup defines for process scheduling
@@ -112,11 +111,7 @@ CONFIGURE_FILE(
 
 LIBUHD_APPEND_SOURCES(
     ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/gain_handler.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
     ${CMAKE_CURRENT_BINARY_DIR}/version.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp
 )
diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp
deleted file mode 100644
index 36e2e8ed3..000000000
--- a/host/lib/gain_handler.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/gain_handler.hpp>
-#include <uhd/utils/assert.hpp>
-#include <uhd/types/ranges.hpp>
-#include <uhd/utils/props.hpp>
-#include <boost/assign/list_of.hpp>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include <cmath>
-#include <vector>
-
-using namespace uhd;
-
-/***********************************************************************
- * gain handler implementation interface
- **********************************************************************/
-class gain_handler_impl : public gain_handler{
-public:
-    gain_handler_impl(
-        const wax::obj &link,
-        const props_t &props,
-        is_equal_t is_equal
-    );
-    ~gain_handler_impl(void);
-    bool intercept_get(const wax::obj &key, wax::obj &val);
-    bool intercept_set(const wax::obj &key, const wax::obj &val);
-
-private:
-    wax::obj     _link;
-    props_t _props;
-    is_equal_t   _is_equal;
-
-    prop_names_t get_gain_names(void);
-    float get_overall_gain_val(void);
-    gain_range_t get_overall_gain_range(void);
-    template <class T> T get_named_prop(const wax::obj &prop, const std::string &name){
-        return _link[named_prop_t(prop, name)].as<T>();
-    }
-};
-
-/***********************************************************************
- * the make function
- **********************************************************************/
-gain_handler::sptr gain_handler::make(
-    const wax::obj &link,
-    const props_t &props,
-    is_equal_t is_equal
-){
-    return sptr(new gain_handler_impl(link, props, is_equal));
-}
-
-/***********************************************************************
- * gain handler implementation methods
- **********************************************************************/
-gain_handler::props_t::props_t(void){
-    /* NOP */
-}
-
-gain_handler_impl::gain_handler_impl(
-    const wax::obj &link,
-    const props_t &props,
-    is_equal_t is_equal
-){
-    _link = link;
-    _props = props;
-    _is_equal = is_equal;
-}
-
-gain_handler_impl::~gain_handler_impl(void){
-    /* NOP */
-}
-
-prop_names_t gain_handler_impl::get_gain_names(void){
-    return _link[_props.names].as<prop_names_t>();
-}
-
-float gain_handler_impl::get_overall_gain_val(void){
-    float gain_val = 0;
-    BOOST_FOREACH(std::string name, get_gain_names()){
-        gain_val += get_named_prop<float>(_props.value, name);
-    }
-    return gain_val;
-}
-
-gain_range_t gain_handler_impl::get_overall_gain_range(void){
-    float gain_min = 0, gain_max = 0, gain_step = 0;
-    BOOST_FOREACH(std::string name, get_gain_names()){
-        gain_range_t floatmp = get_named_prop<gain_range_t>(_props.range, name);
-        gain_min += floatmp.min;
-        gain_max += floatmp.max;
-        gain_step = std::max(gain_step, floatmp.step);
-    }
-    return gain_range_t(gain_min, gain_max, gain_step);
-}
-
-/***********************************************************************
- * gain handler implementation get method
- **********************************************************************/
-bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){
-    wax::obj key; std::string name;
-    boost::tie(key, name) = extract_named_prop(key_);
-
-    //not a wildcard... dont handle (but check name)
-    if (name != ""){
-        assert_has(get_gain_names(), name, "gain name");
-        return false;
-    }
-
-    if (_is_equal(key, _props.value)){
-        val = get_overall_gain_val();
-        return true;
-    }
-
-    if (_is_equal(key, _props.range)){
-        val = get_overall_gain_range();
-        return true;
-    }
-
-    return false; //not handled
-}
-
-/***********************************************************************
- * gain handler implementation set method
- **********************************************************************/
-bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val){
-    wax::obj key; std::string name;
-    boost::tie(key, name) = extract_named_prop(key_);
-
-    //not a gain value key... dont handle
-    if (not _is_equal(key, _props.value)) return false;
-
-    float gain_val = val.as<float>();
-
-    //not a wildcard... dont handle (but check name and range)
-    if (name != ""){
-        assert_has(get_gain_names(), name, "gain name");
-        gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
-        if (gain_val > gain.max or gain_val < gain.min) throw std::range_error(str(
-            boost::format("A value of %f for gain %s is out of range of (%f, %f)")
-            % gain_val % name % gain.min % gain.max
-        ));
-        return false;
-    }
-
-    //set the overall gain
-    BOOST_FOREACH(std::string name, get_gain_names()){
-        //get the min, max, step for this gain name
-        gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
-
-        //clip g to be within the allowed range
-        float g = std::min(std::max(gain_val, gain.min), gain.max);
-        //set g to be a multiple of the step size
-        g -= std::fmod(g, gain.step);
-        //set g to be the new gain
-        _link[named_prop_t(_props.value, name)] = g;
-        //subtract g out of the total gain left to apply
-        gain_val -= g;
-    }
-
-    return true;
-}
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
deleted file mode 100644
index dbb8d0695..000000000
--- a/host/lib/load_modules.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/static.hpp>
-#include <boost/format.hpp>
-#include <boost/foreach.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/program_options.hpp>
-#include <iostream>
-#include <stdexcept>
-
-namespace po = boost::program_options;
-namespace fs = boost::filesystem;
-
-/***********************************************************************
- * Module Load Function
- **********************************************************************/
-#if defined(HAVE_DLFCN_H)
-#include <dlfcn.h>
-static const std::string env_path_sep = ":";
-
-static void load_module(const std::string &file_name){
-    if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){
-        throw std::runtime_error(str(
-            boost::format("dlopen failed to load \"%s\"") % file_name
-        ));
-    }
-}
-
-#elif defined(HAVE_WINDOWS_H)
-#include <windows.h>
-static const std::string env_path_sep = ";";
-
-static void load_module(const std::string &file_name){
-    if (LoadLibrary(file_name.c_str()) == NULL){
-        throw std::runtime_error(str(
-            boost::format("LoadLibrary failed to load \"%s\"") % file_name
-        ));
-    }
-}
-
-#else
-static const std::string env_path_sep = ":";
-
-static void load_module(const std::string &file_name){
-    throw std::runtime_error(str(
-        boost::format("Module loading not supported: Cannot load \"%s\"") % file_name
-    ));
-}
-
-#endif
-
-/***********************************************************************
- * Load Modules
- **********************************************************************/
-/*!
- * Load all modules in a given path.
- * This will recurse into sub-directories.
- * Does not throw, prints to std error.
- * \param path the filesystem path
- */
-static void load_path(const fs::path &path){
-    if (not fs::exists(path)){
-        std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl;
-        return;
-    }
-
-    //try to load the files in this path
-    if (fs::is_directory(path)){
-        for(
-            fs::directory_iterator dir_itr(path);
-            dir_itr != fs::directory_iterator();
-            ++dir_itr
-        ){
-            load_path(dir_itr->path());
-        }
-        return;
-    }
-
-    //its not a directory, try to load it
-    try{
-        load_module(path.file_string());
-    }
-    catch(const std::exception &err){
-        std::cerr << boost::format("Error: %s") % err.what() << std::endl;
-    }
-}
-
-//! The string constant for the module path environment variable
-static const std::string MODULE_PATH_KEY = "UHD_MODULE_PATH";
-
-/*!
- * Name mapper function for the environment variable parser.
- * Map environment variable names (that we use) to option names.
- * \param the variable name
- * \return the option name or blank string
- */
-static std::string name_mapper(const std::string &var_name){
-    if (var_name == MODULE_PATH_KEY) return var_name;
-    return "";
-}
-
-/*!
- * Load all the modules given by the module path enviroment variable.
- * The path variable may be several paths split by path separators.
- */
-UHD_STATIC_BLOCK(load_modules){
-    //register the options
-    std::string env_module_path;
-    po::options_description desc("UHD Module Options");
-    desc.add_options()
-        (MODULE_PATH_KEY.c_str(), po::value<std::string>(&env_module_path)->default_value(""))
-    ;
-
-    //parse environment variables
-    po::variables_map vm;
-    po::store(po::parse_environment(desc, &name_mapper), vm);
-    po::notify(vm);
-
-    if (env_module_path == "") return;
-    //std::cout << "env_module_path: " << env_module_path << std::endl;
-
-    //split the path at the path separators
-    std::vector<std::string> module_paths;
-    boost::split(module_paths, env_module_path, boost::is_any_of(env_path_sep));
-
-    //load modules in each path
-    BOOST_FOREACH(const std::string &module_path, module_paths){
-        load_path(fs::system_complete(fs::path(module_path)));
-    }
-}
diff --git a/host/lib/thread_priority.cpp b/host/lib/thread_priority.cpp
deleted file mode 100644
index c35e5fcb1..000000000
--- a/host/lib/thread_priority.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/thread_priority.hpp>
-#include <stdexcept>
-#include <iostream>
-
-bool uhd::set_thread_priority_safe(float priority, bool realtime){
-    try{
-        set_thread_priority(priority, realtime);
-        return true;
-    }catch(const std::exception &e){
-        std::cerr << "set_thread_priority: " << e.what() << std::endl;
-        return false;
-    }
-}
-
-static void check_priority_range(float priority){
-    if (priority > +1.0 or priority < -1.0)
-        throw std::range_error("priority out of range [-1.0, +1.0]");
-}
-
-/***********************************************************************
- * Pthread API to set priority
- **********************************************************************/
-#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
-    #include <pthread.h>
-
-    void uhd::set_thread_priority(float priority, bool realtime){
-        check_priority_range(priority);
-
-        //when realtime is not enabled, use sched other
-        int policy = (realtime)? SCHED_RR : SCHED_OTHER;
-
-        //we cannot have below normal priority, set to zero
-        if (priority < 0) priority = 0;
-
-        //get the priority bounds for the selected policy
-        int min_pri = sched_get_priority_min(policy);
-        int max_pri = sched_get_priority_max(policy);
-        if (min_pri == -1 or max_pri == -1) throw std::runtime_error("error in sched_get_priority_min/max");
-
-        //set the new priority and policy
-        sched_param sp;
-        sp.sched_priority = int(priority*(max_pri - min_pri)) + min_pri;
-        int ret = pthread_setschedparam(pthread_self(), policy, &sp);
-        if (ret != 0) throw std::runtime_error("error in pthread_setschedparam");
-    }
-
-/***********************************************************************
- * Windows API to set priority
- **********************************************************************/
-#elif defined(HAVE_WIN_SETTHREADPRIORITY)
-    #include <windows.h>
-
-    void uhd::set_thread_priority(float priority, bool realtime){
-        check_priority_range(priority);
-
-        //set the priority class on the process
-        int pri_class = (realtime)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
-        if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0)
-            throw std::runtime_error("error in SetPriorityClass");
-
-        //scale the priority value to the constants
-        int priorities[] = {
-            THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL,
-            THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
-        };
-        size_t pri_index = size_t((priority+1.0)*6/2.0); // -1 -> 0, +1 -> 6
-
-        //set the thread priority on the thread
-        if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0)
-            throw std::runtime_error("error in SetThreadPriority");
-    }
-
-/***********************************************************************
- * Unimplemented API to set priority
- **********************************************************************/
-#else
-    void uhd::set_thread_priority(float, bool){
-        throw std::runtime_error("set thread priority not implemented");
-    }
-
-#endif /* HAVE_PTHREAD_SETSCHEDPARAM */
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index 814affdd0..80ac537ee 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -27,3 +27,6 @@ LIBUHD_APPEND_SOURCES(
     ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp
     ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp
 )
+
+INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt)
+INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt)
diff --git a/host/lib/utils.cpp b/host/lib/utils.cpp
deleted file mode 100644
index d2f4dfc6e..000000000
--- a/host/lib/utils.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/assert.hpp>
-#include <uhd/utils/props.hpp>
-#include <stdexcept>
-
-using namespace uhd;
-
-/***********************************************************************
- * Assert
- **********************************************************************/
-assert_error::assert_error(const std::string &what) : std::runtime_error(what){
-    /* NOP */
-}
-
-/***********************************************************************
- * Props
- **********************************************************************/
-named_prop_t::named_prop_t(
-    const wax::obj &key_,
-    const std::string &name_
-){
-    key = key_;
-    name = name_;
-}
-
-typedef boost::tuple<wax::obj, std::string> named_prop_tuple;
-
-named_prop_tuple uhd::extract_named_prop(
-    const wax::obj &key,
-    const std::string &name
-){
-    if (key.type() == typeid(named_prop_t)){
-        named_prop_t np = key.as<named_prop_t>();
-        return named_prop_tuple(np.key, np.name);
-    }
-    return named_prop_tuple(key, name);
-}
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
new file mode 100644
index 000000000..450112462
--- /dev/null
+++ b/host/lib/utils/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+LIBUHD_APPEND_SOURCES(
+    ${CMAKE_SOURCE_DIR}/lib/utils/assert.cpp
+    ${CMAKE_SOURCE_DIR}/lib/utils/gain_handler.cpp
+    ${CMAKE_SOURCE_DIR}/lib/utils/load_modules.cpp
+    ${CMAKE_SOURCE_DIR}/lib/utils/props.cpp
+    ${CMAKE_SOURCE_DIR}/lib/utils/thread_priority.cpp
+)
diff --git a/host/lib/utils/assert.cpp b/host/lib/utils/assert.cpp
new file mode 100644
index 000000000..7ace9024c
--- /dev/null
+++ b/host/lib/utils/assert.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/assert.hpp>
+
+using namespace uhd;
+
+assert_error::assert_error(const std::string &what) : std::runtime_error(what){
+    /* NOP */
+}
diff --git a/host/lib/utils/gain_handler.cpp b/host/lib/utils/gain_handler.cpp
new file mode 100644
index 000000000..36e2e8ed3
--- /dev/null
+++ b/host/lib/utils/gain_handler.cpp
@@ -0,0 +1,177 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/gain_handler.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/props.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <cmath>
+#include <vector>
+
+using namespace uhd;
+
+/***********************************************************************
+ * gain handler implementation interface
+ **********************************************************************/
+class gain_handler_impl : public gain_handler{
+public:
+    gain_handler_impl(
+        const wax::obj &link,
+        const props_t &props,
+        is_equal_t is_equal
+    );
+    ~gain_handler_impl(void);
+    bool intercept_get(const wax::obj &key, wax::obj &val);
+    bool intercept_set(const wax::obj &key, const wax::obj &val);
+
+private:
+    wax::obj     _link;
+    props_t _props;
+    is_equal_t   _is_equal;
+
+    prop_names_t get_gain_names(void);
+    float get_overall_gain_val(void);
+    gain_range_t get_overall_gain_range(void);
+    template <class T> T get_named_prop(const wax::obj &prop, const std::string &name){
+        return _link[named_prop_t(prop, name)].as<T>();
+    }
+};
+
+/***********************************************************************
+ * the make function
+ **********************************************************************/
+gain_handler::sptr gain_handler::make(
+    const wax::obj &link,
+    const props_t &props,
+    is_equal_t is_equal
+){
+    return sptr(new gain_handler_impl(link, props, is_equal));
+}
+
+/***********************************************************************
+ * gain handler implementation methods
+ **********************************************************************/
+gain_handler::props_t::props_t(void){
+    /* NOP */
+}
+
+gain_handler_impl::gain_handler_impl(
+    const wax::obj &link,
+    const props_t &props,
+    is_equal_t is_equal
+){
+    _link = link;
+    _props = props;
+    _is_equal = is_equal;
+}
+
+gain_handler_impl::~gain_handler_impl(void){
+    /* NOP */
+}
+
+prop_names_t gain_handler_impl::get_gain_names(void){
+    return _link[_props.names].as<prop_names_t>();
+}
+
+float gain_handler_impl::get_overall_gain_val(void){
+    float gain_val = 0;
+    BOOST_FOREACH(std::string name, get_gain_names()){
+        gain_val += get_named_prop<float>(_props.value, name);
+    }
+    return gain_val;
+}
+
+gain_range_t gain_handler_impl::get_overall_gain_range(void){
+    float gain_min = 0, gain_max = 0, gain_step = 0;
+    BOOST_FOREACH(std::string name, get_gain_names()){
+        gain_range_t floatmp = get_named_prop<gain_range_t>(_props.range, name);
+        gain_min += floatmp.min;
+        gain_max += floatmp.max;
+        gain_step = std::max(gain_step, floatmp.step);
+    }
+    return gain_range_t(gain_min, gain_max, gain_step);
+}
+
+/***********************************************************************
+ * gain handler implementation get method
+ **********************************************************************/
+bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){
+    wax::obj key; std::string name;
+    boost::tie(key, name) = extract_named_prop(key_);
+
+    //not a wildcard... dont handle (but check name)
+    if (name != ""){
+        assert_has(get_gain_names(), name, "gain name");
+        return false;
+    }
+
+    if (_is_equal(key, _props.value)){
+        val = get_overall_gain_val();
+        return true;
+    }
+
+    if (_is_equal(key, _props.range)){
+        val = get_overall_gain_range();
+        return true;
+    }
+
+    return false; //not handled
+}
+
+/***********************************************************************
+ * gain handler implementation set method
+ **********************************************************************/
+bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val){
+    wax::obj key; std::string name;
+    boost::tie(key, name) = extract_named_prop(key_);
+
+    //not a gain value key... dont handle
+    if (not _is_equal(key, _props.value)) return false;
+
+    float gain_val = val.as<float>();
+
+    //not a wildcard... dont handle (but check name and range)
+    if (name != ""){
+        assert_has(get_gain_names(), name, "gain name");
+        gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
+        if (gain_val > gain.max or gain_val < gain.min) throw std::range_error(str(
+            boost::format("A value of %f for gain %s is out of range of (%f, %f)")
+            % gain_val % name % gain.min % gain.max
+        ));
+        return false;
+    }
+
+    //set the overall gain
+    BOOST_FOREACH(std::string name, get_gain_names()){
+        //get the min, max, step for this gain name
+        gain_range_t gain = get_named_prop<gain_range_t>(_props.range, name);
+
+        //clip g to be within the allowed range
+        float g = std::min(std::max(gain_val, gain.min), gain.max);
+        //set g to be a multiple of the step size
+        g -= std::fmod(g, gain.step);
+        //set g to be the new gain
+        _link[named_prop_t(_props.value, name)] = g;
+        //subtract g out of the total gain left to apply
+        gain_val -= g;
+    }
+
+    return true;
+}
diff --git a/host/lib/utils/load_modules.cpp b/host/lib/utils/load_modules.cpp
new file mode 100644
index 000000000..dbb8d0695
--- /dev/null
+++ b/host/lib/utils/load_modules.cpp
@@ -0,0 +1,146 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/static.hpp>
+#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+#include <iostream>
+#include <stdexcept>
+
+namespace po = boost::program_options;
+namespace fs = boost::filesystem;
+
+/***********************************************************************
+ * Module Load Function
+ **********************************************************************/
+#if defined(HAVE_DLFCN_H)
+#include <dlfcn.h>
+static const std::string env_path_sep = ":";
+
+static void load_module(const std::string &file_name){
+    if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){
+        throw std::runtime_error(str(
+            boost::format("dlopen failed to load \"%s\"") % file_name
+        ));
+    }
+}
+
+#elif defined(HAVE_WINDOWS_H)
+#include <windows.h>
+static const std::string env_path_sep = ";";
+
+static void load_module(const std::string &file_name){
+    if (LoadLibrary(file_name.c_str()) == NULL){
+        throw std::runtime_error(str(
+            boost::format("LoadLibrary failed to load \"%s\"") % file_name
+        ));
+    }
+}
+
+#else
+static const std::string env_path_sep = ":";
+
+static void load_module(const std::string &file_name){
+    throw std::runtime_error(str(
+        boost::format("Module loading not supported: Cannot load \"%s\"") % file_name
+    ));
+}
+
+#endif
+
+/***********************************************************************
+ * Load Modules
+ **********************************************************************/
+/*!
+ * Load all modules in a given path.
+ * This will recurse into sub-directories.
+ * Does not throw, prints to std error.
+ * \param path the filesystem path
+ */
+static void load_path(const fs::path &path){
+    if (not fs::exists(path)){
+        std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl;
+        return;
+    }
+
+    //try to load the files in this path
+    if (fs::is_directory(path)){
+        for(
+            fs::directory_iterator dir_itr(path);
+            dir_itr != fs::directory_iterator();
+            ++dir_itr
+        ){
+            load_path(dir_itr->path());
+        }
+        return;
+    }
+
+    //its not a directory, try to load it
+    try{
+        load_module(path.file_string());
+    }
+    catch(const std::exception &err){
+        std::cerr << boost::format("Error: %s") % err.what() << std::endl;
+    }
+}
+
+//! The string constant for the module path environment variable
+static const std::string MODULE_PATH_KEY = "UHD_MODULE_PATH";
+
+/*!
+ * Name mapper function for the environment variable parser.
+ * Map environment variable names (that we use) to option names.
+ * \param the variable name
+ * \return the option name or blank string
+ */
+static std::string name_mapper(const std::string &var_name){
+    if (var_name == MODULE_PATH_KEY) return var_name;
+    return "";
+}
+
+/*!
+ * Load all the modules given by the module path enviroment variable.
+ * The path variable may be several paths split by path separators.
+ */
+UHD_STATIC_BLOCK(load_modules){
+    //register the options
+    std::string env_module_path;
+    po::options_description desc("UHD Module Options");
+    desc.add_options()
+        (MODULE_PATH_KEY.c_str(), po::value<std::string>(&env_module_path)->default_value(""))
+    ;
+
+    //parse environment variables
+    po::variables_map vm;
+    po::store(po::parse_environment(desc, &name_mapper), vm);
+    po::notify(vm);
+
+    if (env_module_path == "") return;
+    //std::cout << "env_module_path: " << env_module_path << std::endl;
+
+    //split the path at the path separators
+    std::vector<std::string> module_paths;
+    boost::split(module_paths, env_module_path, boost::is_any_of(env_path_sep));
+
+    //load modules in each path
+    BOOST_FOREACH(const std::string &module_path, module_paths){
+        load_path(fs::system_complete(fs::path(module_path)));
+    }
+}
diff --git a/host/lib/utils/props.cpp b/host/lib/utils/props.cpp
new file mode 100644
index 000000000..fac5fe24f
--- /dev/null
+++ b/host/lib/utils/props.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/props.hpp>
+
+using namespace uhd;
+
+named_prop_t::named_prop_t(
+    const wax::obj &key,
+    const std::string &name
+):
+    key(key),
+    name(name)
+{
+    /* NOP */
+}
+
+typedef boost::tuple<wax::obj, std::string> named_prop_tuple;
+
+named_prop_tuple uhd::extract_named_prop(
+    const wax::obj &key,
+    const std::string &name
+){
+    if (key.type() == typeid(named_prop_t)){
+        named_prop_t np = key.as<named_prop_t>();
+        return named_prop_tuple(np.key, np.name);
+    }
+    return named_prop_tuple(key, name);
+}
diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp
new file mode 100644
index 000000000..c35e5fcb1
--- /dev/null
+++ b/host/lib/utils/thread_priority.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <stdexcept>
+#include <iostream>
+
+bool uhd::set_thread_priority_safe(float priority, bool realtime){
+    try{
+        set_thread_priority(priority, realtime);
+        return true;
+    }catch(const std::exception &e){
+        std::cerr << "set_thread_priority: " << e.what() << std::endl;
+        return false;
+    }
+}
+
+static void check_priority_range(float priority){
+    if (priority > +1.0 or priority < -1.0)
+        throw std::range_error("priority out of range [-1.0, +1.0]");
+}
+
+/***********************************************************************
+ * Pthread API to set priority
+ **********************************************************************/
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
+    #include <pthread.h>
+
+    void uhd::set_thread_priority(float priority, bool realtime){
+        check_priority_range(priority);
+
+        //when realtime is not enabled, use sched other
+        int policy = (realtime)? SCHED_RR : SCHED_OTHER;
+
+        //we cannot have below normal priority, set to zero
+        if (priority < 0) priority = 0;
+
+        //get the priority bounds for the selected policy
+        int min_pri = sched_get_priority_min(policy);
+        int max_pri = sched_get_priority_max(policy);
+        if (min_pri == -1 or max_pri == -1) throw std::runtime_error("error in sched_get_priority_min/max");
+
+        //set the new priority and policy
+        sched_param sp;
+        sp.sched_priority = int(priority*(max_pri - min_pri)) + min_pri;
+        int ret = pthread_setschedparam(pthread_self(), policy, &sp);
+        if (ret != 0) throw std::runtime_error("error in pthread_setschedparam");
+    }
+
+/***********************************************************************
+ * Windows API to set priority
+ **********************************************************************/
+#elif defined(HAVE_WIN_SETTHREADPRIORITY)
+    #include <windows.h>
+
+    void uhd::set_thread_priority(float priority, bool realtime){
+        check_priority_range(priority);
+
+        //set the priority class on the process
+        int pri_class = (realtime)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
+        if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0)
+            throw std::runtime_error("error in SetPriorityClass");
+
+        //scale the priority value to the constants
+        int priorities[] = {
+            THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL,
+            THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
+        };
+        size_t pri_index = size_t((priority+1.0)*6/2.0); // -1 -> 0, +1 -> 6
+
+        //set the thread priority on the thread
+        if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0)
+            throw std::runtime_error("error in SetThreadPriority");
+    }
+
+/***********************************************************************
+ * Unimplemented API to set priority
+ **********************************************************************/
+#else
+    void uhd::set_thread_priority(float, bool){
+        throw std::runtime_error("set thread priority not implemented");
+    }
+
+#endif /* HAVE_PTHREAD_SETSCHEDPARAM */
-- 
cgit v1.2.3