diff --git a/api/Makefile b/api/Makefile
index e0cf62c646219bbf70d034addd1c58081ee61d3e..aa405dafcfd43ee9d2d74448fba6c6a2528f299b 100644
--- a/api/Makefile
+++ b/api/Makefile
@@ -1,6 +1,9 @@
-BUILD = lm32
+# The installation prefix default to /usr/local, but can be set on the cmdline
+PREFIX ?= /usr/local
+
+#BUILD = lm32
 #BUILD = win32
-#BUILD = unix
+BUILD = unix
 
 ifeq ($(BUILD), lm32)
 TARGET	= lm32-elf-
@@ -13,7 +16,7 @@ EXTRA   = libetherbone.dll.a
 endif
 ifeq ($(BUILD), unix)
 FLAGS   = -fPIC
-LIBS    = -Wl,-rpath,/usr/local/lib
+LIBS    = -Wl,-rpath,$(PREFIX)/lib
 LIBRARY = libetherbone.so
 EXTRA   = libetherbone.so.*
 endif
@@ -40,7 +43,7 @@ ARCHIVE = etherbone.a
 
 FLAGS	:= $(FLAGS) -Wall -O2
 #FLAGS	:= $(FLAGS) -DEB_USE_DYNAMIC    # deterministic untill table overflow (default)
-FLAGS	:= $(FLAGS) -DEB_USE_STATIC=200 # fully deterministic
+#FLAGS	:= $(FLAGS) -DEB_USE_STATIC=200 # fully deterministic
 #FLAGS	:= $(FLAGS) -DEB_USE_MALLOC     # non-deterministic
 #FLAGS	:= $(FLAGS) -DDISABLE_SLAVE
 #FLAGS	:= $(FLAGS) -DDISABLE_MASTER
@@ -72,9 +75,10 @@ SOURCES	= memory/static.c		\
 all:	glue/version.h $(TOOLS) $(TESTS) $(ARCHIVE) $(LIBRARY)
 
 install: all
-	cp -a $(LIBRARY) $(EXTRA) $(ARCHIVE) /usr/local/lib
-	cp -a etherbone.h /usr/local/include
-	cp -a $(TOOLS) /usr/local/bin
+	mkdir -p $(PREFIX)/bin $(PREFIX)/include $(PREFIX)/lib
+	cp -a $(LIBRARY) $(EXTRA) $(ARCHIVE) $(PREFIX)/lib
+	cp -a etherbone.h $(PREFIX)/include
+	cp -a $(TOOLS) $(PREFIX)/bin
 
 glue/version.h::
 	git log -n1 --pretty="format:%H" . > git.version_full
diff --git a/api/etherbone.h b/api/etherbone.h
index 18913f37cab86f13583278e6429f801080f939b7..ebf5e66621539066ebf08e19272ae1dac5fd6ea8 100644
--- a/api/etherbone.h
+++ b/api/etherbone.h
@@ -29,8 +29,6 @@
 #ifndef ETHERBONE_H
 #define ETHERBONE_H
 
-#define DEBUG_EB 		1
-
 #define EB_PROTOCOL_VERSION	1
 #define EB_ABI_VERSION		0x02	/* incremented on incompatible changes */
 
@@ -267,11 +265,6 @@ extern "C" {
 /*                                 C99 API                                  */
 /****************************************************************************/
 
-extern int mprintf(char const *format, ...);
-
-#define dbgprint(fmt, ...) \
-            do { if (DEBUG_EB) mprintf(fmt, ##__VA_ARGS__); } while (0)
-
 /* Convert status to a human-readable printable string */
 EB_PUBLIC
 const char* eb_status(eb_status_t code);
@@ -613,7 +606,7 @@ class Socket {
     status_t attach(sdb_device_t device, Handler* handler);
     status_t detach(sdb_device_t device);
     
-    int run(int timeout_us);
+    int run(int timeout_us = -1);
     
     /* These can be used to implement your own 'block': */
     uint32_t timeout() const;
@@ -640,15 +633,24 @@ class Device {
     
     width_t width() const;
     
+    template <typename T>
+    status_t sdb_scan_bus (sdb_bridge_t bridge, T* user, sdb_callback_t);
+    template <typename T>
+    status_t sdb_scan_root(T* user, sdb_callback_t);
+    
   protected:
     Device(eb_device_t device);
     eb_device_t device;
   
   friend class Cycle;
   template <typename T, void (T::*cb)(Device, Operation, status_t)>
-  friend void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status);
-  template <typename T, void (*cb)(Device, Operation, status_t)>
-  friend void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status);
+  friend void wrap_member_callback(eb_user_data_t object, eb_device_t dev, eb_operation_t op, eb_status_t status);
+  template <typename T, void (*cb)(T*, Device, Operation, status_t)>
+  friend void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status);
+  template <typename T, void (T::*cb)(Device, sdb_t, status_t)>
+  friend void sdb_wrap_member_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status);
+  template <typename T, void (*cb)(T* user, Device, sdb_t, status_t)>
+  friend void sdb_wrap_function_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status);
 };
 
 class Cycle {
@@ -657,7 +659,7 @@ class Cycle {
     
     // Start a cycle on the target device.
     template <typename T>
-    status_t open(Device device, T* user, void (*cb)(T*, eb_device_t, eb_operation_t, eb_status_t));
+    status_t open(Device device, T* user, eb_callback_t);
     status_t open(Device device);
     
     void abort();
@@ -700,19 +702,29 @@ class Operation {
     eb_operation_t operation;
 
   template <typename T, void (T::*cb)(Device, Operation, status_t)>
-  friend void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status);
-  template <typename T, void (*cb)(Device, Operation, status_t)>
-  friend void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status);
+  friend void wrap_member_callback(eb_user_data_t object, eb_device_t dev, eb_operation_t op, eb_status_t status);
+  template <typename T, void (*cb)(T*, Device, Operation, status_t)>
+  friend void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status);
 };
 
 /* Convenience templates to convert member functions into callback type */
 template <typename T, void (T::*cb)(Device, Operation, status_t)>
-void wrap_member_callback(T* object, eb_device_t dev, eb_operation_t op, eb_status_t status) {
-  return (object->*cb)(Device(dev), Operation(op), status);
+void wrap_member_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status) {
+  return (reinterpret_cast<T*>(user)->*cb)(Device(dev), Operation(op), status);
 }
 template <typename T, void (*cb)(T* user, Device, Operation, status_t)>
-void wrap_function_callback(T* user, eb_device_t dev, eb_operation_t op, eb_status_t status) {
-  return (*cb)(user, Device(dev), Operation(op), status);
+void wrap_function_callback(eb_user_data_t user, eb_device_t dev, eb_operation_t op, eb_status_t status) {
+  return (*cb)(reinterpret_cast<T*>(user), Device(dev), Operation(op), status);
+}
+
+template <typename T, void (T::*cb)(Device, sdb_t, status_t)>
+void sdb_wrap_member_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) {
+  return (reinterpret_cast<T*>(user)->*cb)(Device(dev), sdb, status);
+}
+
+template <typename T, void (*cb)(T* user, Device, sdb_t, status_t)>
+void sdb_wrap_function_callback(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) {
+  return (*cb)(reinterpret_cast<T*>(user), Device(dev), sdb, status);
 }
 
 /****************************************************************************/
@@ -808,13 +820,23 @@ inline status_t Device::flush() {
   return eb_device_flush(device);
 }
 
+template <typename T>
+inline eb_status_t Device::sdb_scan_bus(sdb_bridge_t bridge, T* user, sdb_callback_t cb) {
+  return eb_sdb_scan_bus(device, bridge, user, cb);
+}
+
+template <typename T>
+inline eb_status_t Device::sdb_scan_root(T* user, sdb_callback_t cb) {
+  return eb_sdb_scan_root(device, user, cb);
+}
+
 inline Cycle::Cycle()
  : cycle(EB_NULL) {
 }
 
 template <typename T>
-inline eb_status_t Cycle::open(Device device, T* user, void (*cb)(T*, eb_device_t, eb_operation_t, status_t)) {
-  return eb_cycle_open(device.device, user, reinterpret_cast<eb_callback_t>(cb), &cycle);
+inline eb_status_t Cycle::open(Device device, T* user, eb_callback_t cb) {
+  return eb_cycle_open(device.device, user, cb, &cycle);
 }
 
 inline eb_status_t Cycle::open(Device device) {
diff --git a/api/format/master.c b/api/format/master.c
index 8a5bae3c0634e3e56270cf820435c04b17e395db..9ead282df338c47f0578fd303ba0a92d441a2f65 100644
--- a/api/format/master.c
+++ b/api/format/master.c
@@ -31,9 +31,7 @@
 #define EB_NEED_BIGENDIAN_64 1
 
 #include <string.h>
-#include <unistd.h>
 
-#include "../etherbone.h"
 #include "../glue/operation.h"
 #include "../glue/cycle.h"
 #include "../glue/device.h"
@@ -57,9 +55,6 @@ static void EB_mWRITE(uint8_t* wptr, eb_data_t val, int alignment) {
  * Thus, the EB_<TYPE>(x) conversions appear late and near their use.
  */
 eb_status_t eb_device_flush(eb_device_t devicep) {
-  
-  dbgprint("Entering eb_device_flush\n");
-
   struct eb_socket* socket;
   struct eb_socket_aux* aux;
   struct eb_device* device;
@@ -74,14 +69,13 @@ eb_status_t eb_device_flush(eb_device_t devicep) {
   eb_format_t format, size, endian;
   eb_address_t address_mask;
   uint8_t buffer[sizeof(eb_max_align_t)*(255+255+1+1)+8]; /* big enough for worst-case record */
-  dbgprint("Allocated 520 byte record buffer\n");
   uint8_t * wptr, * cptr, * eob;
   int alignment, record_alignment, header_alignment, stride, mtu, readback, has_reads;
   
   device = EB_DEVICE(devicep);
   transport = EB_TRANSPORT(device->transport);
   width = device->widths;
-   dbgprint("Device and Transport created.\n");
+  
   if (device->link == EB_NULL) return EB_FAIL;
   
   /*
@@ -104,13 +98,11 @@ eb_status_t eb_device_flush(eb_device_t devicep) {
   /* Determine alignment and masking sets */
   address_mask = ~(eb_address_t)0;
   address_mask >>= (sizeof(eb_address_t) - addr) << 3;
- dbgprint("Alignment and mask calculated.\n");
-
+  
   /* Begin buffering */
   tops = &eb_transports[transport->link_type];
   link = EB_LINK(device->link);
   tops->send_buffer(transport, link, 1);
-  dbgprint("Begun buffering ...\n");
   
   /* Non-streaming sockets need a header */
   mtu = tops->mtu;
@@ -126,28 +118,16 @@ eb_status_t eb_device_flush(eb_device_t devicep) {
     cptr = wptr = &buffer[0];
     eob = &buffer[sizeof(buffer)];
   }
-    dbgprint("Header...\n");
-  dbgprint("EB_NULL: %d\n", EB_NULL);
-
+  
   /* Invert the list of cycles */
   prevp = EB_NULL;
   for (cyclep = device->un_link.ready; cyclep != EB_NULL; cyclep = nextp) {
-    dbgprint("Traversing cycle list...\n");
-    dbgprint("Before inversion:\n");
-    dbgprint("CycPtr: %d, PrevP: %d, NextP: %d\n", cyclep, prevp, nextp);
-    
-
     cycle = EB_CYCLE(cyclep);
     nextp = cycle->un_link.next;
     cycle->un_link.next = prevp;
     prevp = cyclep;
-
-   dbgprint("After inversion:\n");
-    dbgprint("CycPtr: %d, PrevP: %d, NextP: %d\n", cyclep, prevp, nextp);
-    usleep(500000);
   }
-  dbgprint("Cycle List inverted.\n");
-
+  
   has_reads = 0;
   for (cyclep = prevp; cyclep != EB_NULL; cyclep = nextp) {
     struct eb_operation* operation;
@@ -161,12 +141,10 @@ eb_status_t eb_device_flush(eb_device_t devicep) {
     
     cycle = EB_CYCLE(cyclep);
     nextp = cycle->un_link.next;
-
-
+    
     /* Record the device which answers */
     cycle->un_link.device = devicep;
-      dbgprint("OOM check\n");
-
+    
     /* Deal with OOM cases */
     if (cycle->un_ops.dead == cyclep) {
       if (cycle->callback)
@@ -181,10 +159,9 @@ eb_status_t eb_device_flush(eb_device_t devicep) {
         (*cycle->callback)(cycle->user_data, cycle->un_link.device, EB_NULL, EB_OK);
       eb_free_cycle(cyclep);
       continue;
-     }
-dbgprint("area 1\n");
+    }
     
- /* Are there out of range widths? */
+    /* Are there out of range widths? */
     reason = EB_OK; /* silence warning */
     for (operationp = cycle->un_ops.first; operationp != EB_NULL; operationp = operation->next) {
       operation = EB_OPERATION(operationp);
@@ -218,8 +195,7 @@ dbgprint("area 1\n");
         reason = EB_ADDRESS;
         break;
       }
-      dbgprint("Area 2\n");
-
+      
       /* Is the address too big for a cfg op? */
       if ((operation->flags & EB_OP_CFG_SPACE) != 0 &&
           (operation->address & (0xFFFFU - (size - 1))) != operation->address) {
@@ -257,7 +233,6 @@ dbgprint("area 1\n");
       eb_free_cycle(cyclep);
       continue;
     }
-dbgprint("Area 3\n");
 
     /* Refresh pointers typically needed per cycle */
     device = EB_DEVICE(devicep);
@@ -275,8 +250,7 @@ dbgprint("Area 3\n");
     } else {
       maxops = -1; 
     }
-      dbgprint("Begin formatting\n");
-
+    
     /* Begin formatting the packet into records */
     ops = 0;
     readback = 0;
@@ -310,8 +284,7 @@ dbgprint("Area 3\n");
         low_addr = bwa & (data-1);
         
         if (wcfg == 0) ++ops;
-        dbgprint("Area 4\n");
-
+        
         /* How many writes can we chain? must be either FIFO or sequential in same address space */
         if (ops >= maxops ||
             scanp == EB_NULL ||
@@ -364,7 +337,6 @@ dbgprint("Area 3\n");
           }
         }
       }
-dbgprint("Area 5\n");
 
       /* Next, how many reads follow? */
       /* First pack writes into a record, if any */
@@ -405,8 +377,7 @@ dbgprint("Area 5\n");
       } else {
         rxcount = rcount;
       }
-      dbgprint("Area 6\n");
-
+      
       /* Compute total request length */
       total = (wcount  > 0) + wcount
             + (rxcount > 0) + rxcount;
@@ -443,8 +414,7 @@ dbgprint("Area 5\n");
             cptr = &buffer[header_alignment];
             wptr = cptr + keep;
           }
-          dbgprint("Area 7\n");
-
+          
           /* Test for cycle overflow of MTU */
           if (length > eob - wptr) {
             /* Blow up in the face of the user */
@@ -488,8 +458,7 @@ dbgprint("Area 5\n");
       wptr[2] = wcount;
       wptr[3] = rxcount;
       wptr += record_alignment;
-      dbgprint("Area 8\n");
-
+      
       /* Fill in the writes */
       if (wcount > 0) {
         operation = EB_OPERATION(operationp);
@@ -537,8 +506,7 @@ dbgprint("Area 5\n");
         }
       }
     }
-    dbgprint("Area 9\n");
-
+    
     /* Did we finish the while loop? */
     if (cycle_end) {
       if (readback == 0) {
@@ -569,8 +537,7 @@ dbgprint("Area 5\n");
       cptr = wptr;
     }
   }
-  dbgprint("Area 10\n");
-
+  
   /* Refresh pointer derferences */
   device = EB_DEVICE(devicep);
   transport = EB_TRANSPORT(device->transport);
@@ -592,7 +559,6 @@ dbgprint("Area 5\n");
   
   /* Clear the queue */
   device->un_link.ready = EB_NULL;
-  dbgprint("Leaving eb_device_flush\n");
-
+  
   return EB_OK;
 }
diff --git a/api/transport/lm32.c b/api/transport/lm32.c
index f0f1727d35330404962685f49fdae5f32e8579e0..26cdf14118791c353b3669c304e1f593991d5297 100644
--- a/api/transport/lm32.c
+++ b/api/transport/lm32.c
@@ -35,6 +35,13 @@
 #include "../etherbone.h"
 #include "lm32.h"
 
+extern int mprintf(char const *format, ...);
+
+#define DEBUG_EB 1
+
+#define dbgprint(fmt, ...) \
+            do { if (DEBUG_EB) mprintf(fmt, ##__VA_ARGS__); } while (0)
+
 
 #define IP_START	0
 #define IP_VER_IHL	0
diff --git a/hdl/eb_slave_core/etherbone_pkg.vhd b/hdl/eb_slave_core/etherbone_pkg.vhd
index 7a3e75f9b354de9cd06e9ab87b019f7ad985b8ba..1ed047b1fa08ae3a6bbeb98ba5ce127e6ccb9ff9 100644
--- a/hdl/eb_slave_core/etherbone_pkg.vhd
+++ b/hdl/eb_slave_core/etherbone_pkg.vhd
@@ -7,8 +7,24 @@ use work.wishbone_pkg.all;
 use work.wr_fabric_pkg.all;
 
 package etherbone_pkg is
+  constant c_etherbone_sdb : t_sdb_device := (
+    abi_class     => x"0000", -- undocumented device
+    abi_ver_major => x"01",
+    abi_ver_minor => x"01",
+    wbd_endian    => c_sdb_endian_big,
+    wbd_width     => x"4", --32-bit port granularity
+    sdb_component => (
+    addr_first    => x"0000000000000000",
+    addr_last     => x"00000000000000ff",
+    product => (
+    vendor_id     => x"0000000000000651", -- GSI
+    device_id     => x"68202b22",
+    version       => x"00000001",
+    date          => x"20130211",
+    name          => "Etherbone-Config   ")));
+  
   component eb_slave_core is
-generic(g_sdb_address : std_logic_vector(63 downto 0)); 
+    generic(g_sdb_address : std_logic_vector(63 downto 0)); 
     port(
       clk_i       : in  std_logic;
       nRst_i      : in  std_logic;