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/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 +-
 83 files changed, 6452 insertions(+), 6623 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

(limited to 'firmware/microblaze/apps')

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){
-- 
cgit v1.2.3