[PATCH] ZYNQ BSP

Ric Claus claus at slac.stanford.edu
Sun Apr 21 01:50:26 UTC 2013


---
 c/src/lib/libbsp/arm/acinclude.m4                  |    2 +
 c/src/lib/libbsp/arm/zynq/Makefile.am              |  320 ++++++
 c/src/lib/libbsp/arm/zynq/README                   |   45 +
 c/src/lib/libbsp/arm/zynq/bsp_specs                |   13 +
 c/src/lib/libbsp/arm/zynq/clock/clock.c            |  158 +++
 c/src/lib/libbsp/arm/zynq/configure.ac             |  113 ++
 c/src/lib/libbsp/arm/zynq/console/uart.c           |  259 +++++
 c/src/lib/libbsp/arm/zynq/include/bsp.h            |  168 +++
 c/src/lib/libbsp/arm/zynq/include/cache_.h         |  127 +++
 c/src/lib/libbsp/arm/zynq/include/clock.h          |   70 ++
 c/src/lib/libbsp/arm/zynq/include/ethernet.h       |  369 +++++++
 c/src/lib/libbsp/arm/zynq/include/i2c.h            |  135 +++
 c/src/lib/libbsp/arm/zynq/include/irq.h            |   93 ++
 c/src/lib/libbsp/arm/zynq/include/mmu.h            |  112 ++
 c/src/lib/libbsp/arm/zynq/include/tm27.h           |   73 ++
 c/src/lib/libbsp/arm/zynq/include/uart.h           |  133 +++
 c/src/lib/libbsp/arm/zynq/include/zynq.h           |   73 ++
 c/src/lib/libbsp/arm/zynq/irq/irq.c                |  214 ++++
 c/src/lib/libbsp/arm/zynq/make/custom/zc702.cfg    |    5 +
 c/src/lib/libbsp/arm/zynq/make/custom/zedboard.cfg |    5 +
 c/src/lib/libbsp/arm/zynq/make/custom/zynq.inc     |   14 +
 c/src/lib/libbsp/arm/zynq/misc/i2c.c               |  247 +++++
 c/src/lib/libbsp/arm/zynq/misc/idle-thread.c       |   34 +
 c/src/lib/libbsp/arm/zynq/misc/mmu.c               |   88 ++
 c/src/lib/libbsp/arm/zynq/misc/restart.c           |   32 +
 c/src/lib/libbsp/arm/zynq/misc/timer.c             |   43 +
 c/src/lib/libbsp/arm/zynq/network/ethEmacPs.c      |  411 ++++++++
 c/src/lib/libbsp/arm/zynq/network/ethEmacPs_dma.c  |  649 ++++++++++++
 c/src/lib/libbsp/arm/zynq/network/ethEmacPs_hw.c   |  269 +++++
 .../libbsp/arm/zynq/network/ethEmacPs_phySpeed.c   |  384 +++++++
 c/src/lib/libbsp/arm/zynq/network/ethernet.c       | 1070 ++++++++++++++++++++
 c/src/lib/libbsp/arm/zynq/startup/bspreset.c       |   50 +
 c/src/lib/libbsp/arm/zynq/startup/bspstart.c       |  117 +++
 c/src/lib/libbsp/arm/zynq/startup/bspstarthooks.c  |  169 +++
 c/src/lib/libbsp/arm/zynq/startup/linkcmds.zc702   |   46 +
 .../lib/libbsp/arm/zynq/startup/linkcmds.zedboard  |   46 +
 c/src/lib/libbsp/arm/zynq/startup/linkcmds.zynq    |   77 ++
 37 files changed, 6233 insertions(+), 0 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/zynq/Makefile.am
 create mode 100644 c/src/lib/libbsp/arm/zynq/README
 create mode 100644 c/src/lib/libbsp/arm/zynq/bsp_specs
 create mode 100644 c/src/lib/libbsp/arm/zynq/clock/clock.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/configure.ac
 create mode 100644 c/src/lib/libbsp/arm/zynq/console/uart.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/bsp.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/cache_.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/clock.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/ethernet.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/i2c.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/irq.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/mmu.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/tm27.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/uart.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/include/zynq.h
 create mode 100644 c/src/lib/libbsp/arm/zynq/irq/irq.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/make/custom/zc702.cfg
 create mode 100644 c/src/lib/libbsp/arm/zynq/make/custom/zedboard.cfg
 create mode 100644 c/src/lib/libbsp/arm/zynq/make/custom/zynq.inc
 create mode 100644 c/src/lib/libbsp/arm/zynq/misc/i2c.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/misc/idle-thread.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/misc/mmu.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/misc/restart.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/misc/timer.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/network/ethEmacPs.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/network/ethEmacPs_dma.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/network/ethEmacPs_hw.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/network/ethEmacPs_phySpeed.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/network/ethernet.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/bspreset.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/bspstart.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/bspstarthooks.c
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/linkcmds.zc702
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/linkcmds.zedboard
 create mode 100644 c/src/lib/libbsp/arm/zynq/startup/linkcmds.zynq

diff --git a/c/src/lib/libbsp/arm/acinclude.m4 b/c/src/lib/libbsp/arm/acinclude.m4
index 6214bb7..91acb80 100644
--- a/c/src/lib/libbsp/arm/acinclude.m4
+++ b/c/src/lib/libbsp/arm/acinclude.m4
@@ -32,6 +32,8 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR],
     AC_CONFIG_SUBDIRS([smdk2410]);;
   stm32f4 )
     AC_CONFIG_SUBDIRS([stm32f4]);;
+  zynq )
+    AC_CONFIG_SUBDIRS([zynq]);;
   *)
     AC_MSG_ERROR([Invalid BSP]);;
   esac
diff --git a/c/src/lib/libbsp/arm/zynq/Makefile.am b/c/src/lib/libbsp/arm/zynq/Makefile.am
new file mode 100644
index 0000000..584505e
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/Makefile.am
@@ -0,0 +1,320 @@
+##
+#
+# @file
+#
+# @brief Makefile of LibBSP for the ZYNQ-based boards.
+#
+
+ACLOCAL_AMFLAGS = -I ../../../../aclocal
+
+include $(top_srcdir)/../../../../automake/compile.am
+
+include_bspdir    = $(includedir)/bsp
+include_libcpudir = $(includedir)/libcpu
+
+dist_project_lib_DATA = bsp_specs
+
+###############################################################################
+#                  Header                                                     #
+###############################################################################
+
+include_HEADERS  = include/bsp.h
+include_HEADERS += include/tm27.h
+
+nodist_include_HEADERS  = ../../shared/include/coverhd.h
+nodist_include_HEADERS += include/bspopts.h
+
+nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h
+
+include_bsp_HEADERS  =
+include_bsp_HEADERS += ../../shared/include/utility.h
+include_bsp_HEADERS += ../../shared/include/irq-generic.h
+include_bsp_HEADERS += ../../shared/include/irq-info.h
+include_bsp_HEADERS += ../../shared/include/stackalloc.h
+include_bsp_HEADERS += ../../shared/tod.h
+include_bsp_HEADERS += ../shared/include/linker-symbols.h
+include_bsp_HEADERS += ../shared/include/start.h
+include_bsp_HEADERS += include/zynq.h
+include_bsp_HEADERS += include/irq.h
+include_bsp_HEADERS += include/mmu.h
+include_bsp_HEADERS += include/uart.h
+include_bsp_HEADERS += include/clock.h
+include_bsp_HEADERS += include/ethernet.h
+include_bsp_HEADERS += include/i2c.h
+
+include_bsp_HEADERS += @BSP_XILCOM@/canps_v1_01_a/src/xcanps.h
+include_bsp_HEADERS += @BSP_XILCOM@/canps_v1_01_a/src/xcanps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/cpu_cortexa9_v1_01_a/src/xcpu_cortexa9.h
+include_bsp_HEADERS += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg.h
+include_bsp_HEADERS += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/dmaps_v1_04_a/src/xdmaps.h
+include_bsp_HEADERS += @BSP_XILCOM@/dmaps_v1_04_a/src/xdmaps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps.h
+include_bsp_HEADERS += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_bd.h
+include_bsp_HEADERS += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_bdring.h
+include_bsp_HEADERS += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops.h
+include_bsp_HEADERS += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps.h
+include_bsp_HEADERS += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips.h
+include_bsp_HEADERS += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic.h
+include_bsp_HEADERS += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/scutimer_v1_02_a/src/xscutimer.h
+include_bsp_HEADERS += @BSP_XILCOM@/scutimer_v1_02_a/src/xscutimer_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/scuwdt_v1_02_a/src/xscuwdt.h
+include_bsp_HEADERS += @BSP_XILCOM@/scuwdt_v1_02_a/src/xscuwdt_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_assert.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_cache.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_cache_l.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_exception.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_io.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_mmu.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_printf.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xil_types.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xparameters_ps.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xpseudo_asm.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xpseudo_asm_gcc.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xreg_cortexa9.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xstatus.h
+include_bsp_HEADERS += @BSP_XILCOM@/standalone_v3_09_a/src/xtime_l.h
+include_bsp_HEADERS += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps.h
+include_bsp_HEADERS += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps.h
+include_bsp_HEADERS += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps.h
+include_bsp_HEADERS += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps_endpoint.h
+include_bsp_HEADERS += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/wdtps_v1_02_a/src/xwdtps.h
+include_bsp_HEADERS += @BSP_XILCOM@/wdtps_v1_02_a/src/xwdtps_hw.h
+include_bsp_HEADERS += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps.h
+include_bsp_HEADERS += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps_hw.h
+
+include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/arm-cp15.h
+
+###############################################################################
+#                  Data                                                       #
+###############################################################################
+
+noinst_LIBRARIES = libbspstart.a
+
+libbspstart_a_SOURCES = ../shared/start/start.S
+
+project_lib_DATA = start.$(OBJEXT)
+
+project_lib_DATA += startup/linkcmds
+project_lib_DATA += startup/linkcmds.zynq
+project_lib_DATA += startup/linkcmds.$(RTEMS_BSP)
+
+EXTRA_DIST  = startup/linkcmds.$(RTEMS_BSP)
+
+###############################################################################
+#                  LibBSP                                                     #
+###############################################################################
+
+noinst_LIBRARIES += libbsp.a
+
+libbsp_a_SOURCES  =
+libbsp_a_CPPFLAGS = -I$(srcdir)/include
+libbsp_a_LIBADD   =
+
+# Shared
+libbsp_a_SOURCES += ../../shared/bootcard.c
+libbsp_a_SOURCES += ../../shared/bspclean.c
+libbsp_a_SOURCES += ../../shared/bspgetworkarea.c
+libbsp_a_SOURCES += ../../shared/bsplibc.c
+libbsp_a_SOURCES += ../../shared/bsppost.c
+libbsp_a_SOURCES += ../../shared/gnatinstallhandler.c
+libbsp_a_SOURCES += ../../shared/sbrk.c
+libbsp_a_SOURCES += ../../shared/src/stackalloc.c
+libbsp_a_SOURCES += ../shared/abort/simple_abort.c
+
+# Xilinx-supplied
+libbsp_a_SOURCES += @BSP_XILCOM@/canps_v1_01_a/src/xcanps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/canps_v1_01_a/src/xcanps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/canps_v1_01_a/src/xcanps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/canps_v1_01_a/src/xcanps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg.c
+libbsp_a_SOURCES += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/devcfg_v2_02_a/src/xdevcfg_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/dmaps_v1_04_a/src/xdmaps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/dmaps_v1_04_a/src/xdmaps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/dmaps_v1_04_a/src/xdmaps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_bdring.c
+libbsp_a_SOURCES += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_control.c
+libbsp_a_SOURCES += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/emacps_v1_03_a/src/xemacps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops.c
+libbsp_a_SOURCES += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/gpiops_v1_01_a/src/xgpiops_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_master.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_options.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_sinit.c
+libbsp_a_SOURCES += @BSP_XILCOM@/iicps_v1_02_a/src/xiicps_slave.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips.c
+libbsp_a_SOURCES += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips_options.c
+libbsp_a_SOURCES += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/qspips_v2_01_a/src/xqspips_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic_hw.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scugic_v1_03_a/src/xscugic_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/scutimer_v1_02_a/src/xscutimer.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scutimer_v1_02_a/src/xscutimer_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scutimer_v1_02_a/src/xscutimer_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/scuwdt_v1_02_a/src/xscuwdt.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scuwdt_v1_02_a/src/xscuwdt_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/scuwdt_v1_02_a/src/xscuwdt_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/boot.S
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/cpu_init.S
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/translation_table.s
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xtime_l.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_assert.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_cache.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_exception.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_io.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_mmu.c
+libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_printf.c
+#libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_testcache.c
+#libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_testio.c
+#libbsp_a_SOURCES += @BSP_XILCOM@/standalone_v3_09_a/src/xil_testmem.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps_options.c
+libbsp_a_SOURCES += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/ttcps_v1_01_a/src/xttcps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_hw.c
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_options.c
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/uartps_v1_03_a/src/xuartps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps_endpoint.c
+libbsp_a_SOURCES += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/usbps_v1_04_a/src/xusbps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/wdtps_v1_02_a/src/xwdtps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/wdtps_v1_02_a/src/xwdtps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/wdtps_v1_02_a/src/xwdtps_sinit.c
+
+libbsp_a_SOURCES += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps.c
+libbsp_a_SOURCES += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps_intr.c
+libbsp_a_SOURCES += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps_selftest.c
+libbsp_a_SOURCES += @BSP_XILCOM@/xadcps_v1_01_a/src/xadcps_sinit.c
+
+libbsp_a_CPPFLAGS += -I$(PROJECT_INCLUDE)/bsp
+
+# Config - Xilinx tool-generated files
+include_bsp_HEADERS += @BSP_XILGEN@/xparameters.h
+include_bsp_HEADERS += @BSP_XILGEN@/bspconfig.h
+libbsp_a_SOURCES += @BSP_XILGEN@/xadcps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xcanps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xdevcfg_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xdmaps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xemacps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xgpiops_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xiicps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xqspips_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xscugic_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xscutimer_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xscuwdt_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xttcps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xuartps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xusbps_g.c
+libbsp_a_SOURCES += @BSP_XILGEN@/xwdtps_g.c
+
+# Startup
+libbsp_a_SOURCES += startup/bspreset.c
+libbsp_a_SOURCES += startup/bspstart.c
+
+# IRQ
+libbsp_a_SOURCES += ../../shared/src/irq-default-handler.c
+libbsp_a_SOURCES += ../../shared/src/irq-generic.c
+libbsp_a_SOURCES += ../../shared/src/irq-info.c
+libbsp_a_SOURCES += ../../shared/src/irq-legacy.c
+libbsp_a_SOURCES += ../../shared/src/irq-server.c
+libbsp_a_SOURCES += ../../shared/src/irq-shell.c
+libbsp_a_SOURCES += irq/irq.c
+
+# Console
+libbsp_a_SOURCES += ../../shared/console.c
+libbsp_a_SOURCES += ../../shared/console_select.c
+libbsp_a_SOURCES += console/uart.c
+libbsp_a_SOURCES += ../../shared/console_read.c
+libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console_control.c
+
+# Clock
+libbsp_a_SOURCES += clock/clock.c
+libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
+
+# RTC
+#libbsp_a_SOURCES += ../../shared/tod.c
+#libbsp_a_SOURCES += rtc/rtc-config.c
+
+# Misc
+libbsp_a_SOURCES += misc/mmu.c
+libbsp_a_SOURCES += misc/restart.c
+libbsp_a_SOURCES += misc/timer.c
+libbsp_a_SOURCES += misc/idle-thread.c
+
+# I2C
+libbsp_a_SOURCES += misc/i2c.c
+
+# Cache
+libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c
+libbsp_a_SOURCES += include/cache_.h
+#libbsp_a_CPPFLAGS += -I$(srcdir)/../shared/zynq/include
+
+# Start hooks
+libbsp_a_SOURCES += startup/bspstarthooks.c
+
+###############################################################################
+#                  Network                                                    #
+###############################################################################
+
+if HAS_NETWORKING
+
+noinst_PROGRAMS = network.rel
+
+network_rel_SOURCES  = network/ethernet.c
+network_rel_SOURCES += network/ethEmacPs.c
+network_rel_SOURCES += network/ethEmacPs_dma.c
+network_rel_SOURCES += network/ethEmacPs_hw.c
+network_rel_SOURCES += network/ethEmacPs_phySpeed.c
+network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(libbsp_a_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
+network_rel_LDFLAGS  = $(RTEMS_RELLDFLAGS)
+
+libbsp_a_LIBADD += network.rel
+
+endif
+
+###############################################################################
+#                  Special Rules                                              #
+###############################################################################
+
+DISTCLEANFILES = include/bspopts.h
+
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/lib/libbsp/arm/zynq/README b/c/src/lib/libbsp/arm/zynq/README
new file mode 100644
index 0000000..9f15d2b
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/README
@@ -0,0 +1,45 @@
+Development boards are the Xilinx ZC702 and Zedboard.  Basic initialization via
+XMD, First Stage BootLoader or U-Boot is assumed.  Drivers:
+
+        o Standard UART 0, 1 (Console = 0, 115200N1)
+        o Clock uses TIMER 0
+        o Ethernet
+        o I2C
+
+This BSP depends on third party software from Xilinx.  One method to obtain it,
+is to follow the ZC702 Built-In Self Test (XTP180) tutorial from Xilinx.  You
+can obtain it at http://www.xilinx.com/support.html by searching for 'zynq
+bist'.  You will need to accept their license agreement in order to download the
+'BIST Design Files' zip file.
+
+This tutorial guides you with downloading a zip file and building an application
+using the Xilinx ISE Design tools.  In the process some files will be generated
+that are associated with your particular system configuration.  Since there are
+many possible configurations, this BSP handles the generated files separately
+from the common files.  The path to the source files in the unzipped BIST tree
+is
+zc702_prebuilt_bist_design/zc702_bist.sdk/SDK/SDK_Export/standalone_bsp_0/ps7_cortexa9_0/libsrc/. The
+generated files are xparameters.h, bspconfig.h and *_g.c.  These must be copied
+into a separate directory.
+
+To build the BSP, modify configure.ac by changing the variables BSP_XILCOM and
+BSP_XILGEN to point to where you have the results from the above tutorial
+installed.  These files will be accessed in a read-only fashion.  The BSP_XILGEN
+variable goes with the particular board you are building the BSP for, so if you
+have more than one kind of board, ensure that it gets set to point to the
+directory containing the generated files for each kind of board.
+
+You may need to update the paths of the Xilinx files in the BSP's Makefile.am,
+since these can change from Xilinx release to release.  Of course, more than
+just the file paths can change as well, so further patching may be needed.  The
+current (Sat Apr 20 16:37:32 2013) state of the files is based on the 14.5
+release of the Xilinx ISE Design tool suite.
+
+This BSP is far from complete.  It currently has no support for running on both
+cores of the Zynq, for example.  Only one core is booted.  There are also many
+additional peripherals that are not yet supported.  Of the peripherals that are
+supported, not all possible combination of configurations have been tested.  The
+I2C is as yet untested as well.
+
+R. Claus
+SLAC / Stanford University
diff --git a/c/src/lib/libbsp/arm/zynq/bsp_specs b/c/src/lib/libbsp/arm/zynq/bsp_specs
new file mode 100644
index 0000000..7df53f8
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/bsp_specs
@@ -0,0 +1,13 @@
+%rename endfile old_endfile
+%rename startfile old_startfile
+%rename link old_link
+
+*startfile:
+%{!qrtems: %(old_startfile)} \
+%{!nostdlib: %{qrtems: start.o%s crti.o%s crtbegin.o%s}}
+
+*link:
+%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N}
+
+*endfile:
+%{!qrtems: *(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s }
diff --git a/c/src/lib/libbsp/arm/zynq/clock/clock.c b/c/src/lib/libbsp/arm/zynq/clock/clock.c
new file mode 100644
index 0000000..68ccdae
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/clock/clock.c
@@ -0,0 +1,158 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Clock driver configuration.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <irq-generic.h>
+
+#include <bsp/clock.h>
+
+
+XScuTimer Zynq_Timer_Instance;       /* Cortex A9 Scu Private Timer Instance */
+
+
+#ifdef ARM_MULTILIB_ARCH_V4
+
+/* This is defined in ../../../shared/clockdrv_shell.h */
+void Clock_isr(rtems_irq_hdl_param arg);
+
+
+static void zynq_clock_at_tick(void)
+{
+  XScuTimer_ClearInterruptStatus(&Zynq_Timer_Instance);
+}
+
+static void zynq_clock_handler_install(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  /* Install the interrupt handler and enable the vector */
+  sc = rtems_interrupt_handler_install( ZYNQ_CLOCK_INTERRUPT,
+                                        "Clock",
+                                        RTEMS_INTERRUPT_UNIQUE,
+                                        (rtems_interrupt_handler) Clock_isr,
+                                        NULL );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_fatal_error_occurred(0xdead0003);
+  }
+}
+
+static void zynq_clock_initialize(void)
+{
+  /* Look up the timer configuration */
+  XScuTimer_Config *cfg = XScuTimer_LookupConfig(ZYNQ_TIMER_DEVICE_ID);
+  if (cfg == NULL) {
+    printk("%s: ScuTimer configuration for device ID %d not found\n",
+           __func__, ZYNQ_TIMER_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0000);
+  }
+
+  /* Initialize the Scu Private Timer driver */
+  int sc = XScuTimer_CfgInitialize(&Zynq_Timer_Instance, cfg, cfg->BaseAddr);
+  if (sc != XST_SUCCESS) {
+    printk("%s: ScuTimer configuration initialization for device ID %d failed\n",
+           __func__, ZYNQ_TIMER_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0001);
+  }
+
+  /* Perform a self-test to ensure that the hardware was built correctly. */
+  sc = XScuTimer_SelfTest(&Zynq_Timer_Instance);
+  if (sc != XST_SUCCESS) {
+    printk("%s: ScuTimer self-test for device ID %d failed\n",
+           __func__, ZYNQ_TIMER_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0002);
+  }
+
+  uint32_t interval = ((uint64_t) ZYNQ_CLOCK_REFERENCE
+    * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000u;
+
+  /* Load the timer counter register */
+  XScuTimer_LoadTimer(&Zynq_Timer_Instance, interval);
+
+  /* Enable Auto reload mode */
+  XScuTimer_EnableAutoReload(&Zynq_Timer_Instance);
+
+  /* Enable the timer interrupts for timer mode */
+  XScuTimer_EnableInterrupt(&Zynq_Timer_Instance);
+
+  /* Enable timer */
+  XScuTimer_Start(&Zynq_Timer_Instance);
+
+  printk("%s: ClkRef = %08x = %u Hz, uS/tick = %08x = %u, interval = %08lx = %lu\n",
+         __func__, ZYNQ_CLOCK_REFERENCE, ZYNQ_CLOCK_REFERENCE,
+         rtems_configuration_get_microseconds_per_tick(),
+         rtems_configuration_get_microseconds_per_tick(), interval, interval);
+}
+
+static void zynq_clock_cleanup(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  /* Disable timer */
+  XScuTimer_Stop(&Zynq_Timer_Instance);
+
+  /* Remove the interrupt handler */
+  sc = rtems_interrupt_handler_remove(
+    ZYNQ_CLOCK_INTERRUPT,
+    (rtems_interrupt_handler) Clock_isr,
+    NULL
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_fatal_error_occurred(0xdead0004);
+  }
+}
+
+static uint32_t zynq_clock_nanoseconds_since_last_tick(void)
+{
+  uint64_t k = (1000000000ULL << 32) / ZYNQ_CLOCK_REFERENCE;
+  uint64_t c = zynq_timer();
+
+  if (XScuTimer_IsExpired(&Zynq_Timer_Instance)) {
+    c = zynq_timer() + XScuTimer_GetLoadReg(Zynq_Timer_Instance.Config.BaseAddr);
+  }
+
+  return (uint32_t) ((c * k) >> 32);
+}
+
+#define Clock_driver_support_at_tick()                 zynq_clock_at_tick()
+#define Clock_driver_support_initialize_hardware()     zynq_clock_initialize()
+#define Clock_driver_support_install_isr(isr, old_isr) \
+  do {						       \
+    zynq_clock_handler_install();		       \
+    old_isr = NULL;				       \
+  } while (0)
+
+#define Clock_driver_support_shutdown_hardware()       zynq_clock_cleanup()
+#define Clock_driver_nanoseconds_since_last_tick \
+  zynq_clock_nanoseconds_since_last_tick
+
+/* Include shared source clock driver code */
+#include "../../../shared/clockdrv_shell.h"
+
+#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/c/src/lib/libbsp/arm/zynq/configure.ac b/c/src/lib/libbsp/arm/zynq/configure.ac
new file mode 100644
index 0000000..3fb5662
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/configure.ac
@@ -0,0 +1,113 @@
+##
+#
+# @file
+#
+# @brief Configure script of LibBsp for the ZYNQ-based boards.
+#
+
+AC_PREREQ([2.69])
+AC_INIT([rtems-c-src-lib-libbsp-arm-zynq],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla])
+AC_CONFIG_SRCDIR([bsp_specs])
+RTEMS_TOP(../../../../../..)
+
+RTEMS_CANONICAL_TARGET_CPU
+AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.12.2])
+RTEMS_BSP_CONFIGURE
+
+RTEMS_PROG_CC_FOR_TARGET
+RTEMS_CANONICALIZE_TOOLS
+RTEMS_PROG_CCAS
+
+RTEMS_CHECK_NETWORKING
+AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
+
+# Adjust these paths for your installation (see README)
+AC_SUBST([BSP_XILCOM],[$XILINX_DIR/zc702-bist-rdf0166-14.5-c/zc702_prebuilt_bist_design/zc702_bist.sdk/SDK/SDK_Export/standalone_bsp_0/ps7_cortexa9_0/libsrc])
+AC_SUBST([BSP_XILGEN],[$XILINX_DIR/config/${RTEMS_BSP}])
+
+RTEMS_BSPOPTS_SET([ZYNQ_OSCILLATOR_MAIN],[*],[XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ])
+RTEMS_BSPOPTS_HELP([ZYNQ_OSCILLATOR_MAIN],[main oscillator frequency in Hz])
+
+RTEMS_BSPOPTS_SET([ZYNQ_TIMER_CLK],[*],[(XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ/2)])
+RTEMS_BSPOPTS_HELP([ZYNQ_TIMER_CLK],[timer clock in Hz (= CPU clock / 2)])
+
+# Device selection
+RTEMS_BSPOPTS_SET([ZYNQ_INTC],[*],[XPAR_SCUGIC_0])
+RTEMS_BSPOPTS_HELP([ZYNQ_INTC],[Prefix of the interrupt controller])
+
+RTEMS_BSPOPTS_SET([ZYNQ_TMR_0],[*],[XPAR_XSCUTIMER_0])
+RTEMS_BSPOPTS_HELP([ZYNQ_TMR_0],[Prefix of the first timer])
+
+RTEMS_BSPOPTS_SET([ZYNQ_UART_0],[*],[XPAR_XUARTPS_0])
+RTEMS_BSPOPTS_HELP([ZYNQ_UART_0],[Prefix of the first UART])
+
+RTEMS_BSPOPTS_SET([ZYNQ_ETH_0],[*],[XPAR_XEMACPS_0])
+RTEMS_BSPOPTS_HELP([ZYNQ_ETH_0],[Prefix of the first Ethernet interface])
+
+RTEMS_BSPOPTS_SET([ZYNQ_I2C_0],[*],[XPAR_XIICPS_0])
+RTEMS_BSPOPTS_HELP([ZYNQ_I2C_0],[Prefix of the first I2C interface])
+
+# Interrupt selection
+RTEMS_BSPOPTS_SET([ZYNQ_IRQ_TMR_0],[*],[XPAR_SCUTIMER_INTR])
+RTEMS_BSPOPTS_HELP([ZYNQ_IRQ_TMR_0],[IRQ of the first timer])
+
+RTEMS_BSPOPTS_SET([ZYNQ_IRQ_UART_0],[*],[XPAR_XUARTPS_1_INTR])
+RTEMS_BSPOPTS_HELP([ZYNQ_IRQ_UART_0],[IRQ of the first UART])
+
+RTEMS_BSPOPTS_SET([ZYNQ_IRQ_ETH_0],[*],[XPAR_XEMACPS_0_INTR])
+RTEMS_BSPOPTS_HELP([ZYNQ_IRQ_ETH_0],[IRQ of the first Ethernet interface])
+
+RTEMS_BSPOPTS_SET([ZYNQ_IRQ_I2C_0],[*],[XPAR_XIICPS_0_INTR])
+RTEMS_BSPOPTS_HELP([ZYNQ_IRQ_I2C_0],[IRQ of the first I2C interface])
+
+# Not supported, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_ETHERNET_RGMII],[*],[1])
+#RTEMS_BSPOPTS_HELP([ZYNQ_ETHERNET_RGMII],[enable RGMII for Ethernet])
+
+RTEMS_BSPOPTS_SET([ZYNQ_UART_0_BAUD],[*],[115200])
+RTEMS_BSPOPTS_HELP([ZYNQ_UART_0_BAUD],[baud for UART 0])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_UART_1_BAUD],[*],[115200])
+#RTEMS_BSPOPTS_HELP([ZYNQ_UART_1_BAUD],[baud for UART 1])
+
+RTEMS_BSPOPTS_SET([ZYNQ_DISABLE_MMU],[*],[])
+RTEMS_BSPOPTS_HELP([ZYNQ_DISABLE_MMU],[disable MMU])
+
+RTEMS_BSPOPTS_SET([ZYNQ_DISABLE_READ_WRITE_DATA_CACHE],[*],[])
+RTEMS_BSPOPTS_HELP([ZYNQ_DISABLE_READ_WRITE_DATA_CACHE],[disable cache for read-write data sections])
+
+RTEMS_BSPOPTS_SET([ZYNQ_DISABLE_READ_ONLY_PROTECTION],[*],[])
+RTEMS_BSPOPTS_HELP([ZYNQ_DISABLE_READ_ONLY_PROTECTION],[disable MMU protection of read-only sections])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_STOP_GPDMA],[*],[1])
+#RTEMS_BSPOPTS_HELP([ZYNQ_STOP_GPDMA],[stop general purpose DMA at start-up to avoid DMA interference])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_STOP_ETHERNET],[*],[1])
+#RTEMS_BSPOPTS_HELP([ZYNQ_STOP_ETHERNET],[stop Ethernet controller at start-up to avoid DMA interference])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_STOP_USB],[*],[1])
+#RTEMS_BSPOPTS_HELP([ZYNQ_STOP_USB],[stop USB controller at start-up to avoid DMA interference])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_ENABLE_WATCHDOG_RESET],[*],[1])
+#RTEMS_BSPOPTS_HELP([ZYNQ_ENABLE_WATCHDOG_RESET],[bsp_reset() will use the watchdog to reset the chip])
+
+# Not used, yet
+#RTEMS_BSPOPTS_SET([ZYNQ_DMA_CHANNEL_COUNT],[*],[8])
+#RTEMS_BSPOPTS_HELP([ZYNQ_DMA_CHANNEL_COUNT],[DMA channel count])
+
+RTEMS_BSPOPTS_SET([TESTS_USE_PRINTK],[*],[1])
+RTEMS_BSPOPTS_HELP([TESTS_USE_PRINTK],[tests use printk() for output])
+
+RTEMS_BSPOPTS_SET([BSP_PRINT_EXCEPTION_CONTEXT],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_PRINT_EXCEPTION_CONTEXT],[If defined, prints the exception context when an unexpected exception occurs.])
+
+RTEMS_BSP_CLEANUP_OPTIONS(0, 1)
+RTEMS_BSP_LINKCMDS
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/c/src/lib/libbsp/arm/zynq/console/uart.c b/c/src/lib/libbsp/arm/zynq/console/uart.c
new file mode 100644
index 0000000..0dd3fda
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/console/uart.c
@@ -0,0 +1,259 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Console driver
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/bspIo.h>
+#include <rtems/termiostypes.h>
+
+#include <libchip/serial.h>
+#include <libchip/sersupp.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/uart.h>
+
+/*#define DEBUG 1*/
+
+/* Debug */
+#ifdef DEBUG
+  #include <stdio.h>
+  #define PRINTF(...) printf(__VA_ARGS__)
+  #define PRINTK(...) printk(__VA_ARGS__)
+#else
+  #define PRINTF(...)
+  #define PRINTK(...)
+#endif
+
+extern unsigned int XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
+
+/* We are interested in RX timeout, RX trigger and TX trigger interrupts */
+#define UART_IXR_MASK (XUARTPS_IXR_TOUT | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TTRIG)
+#define UART_FIFO_SIZE 64  /* From UG585 */
+
+/* FIXME: Console selection */
+console_tbl Console_Configuration_Ports [] = {
+#ifdef ZYNQ_CFG_UART_0
+  ZYNQ_CFG_UART_0,
+#endif
+#ifdef ZYNQ_CFG_UART_1
+  ZYNQ_CFG_UART_1
+#endif
+};
+
+#define ZYNQ_UART_COUNT \
+  (sizeof(Console_Configuration_Ports) / sizeof(Console_Configuration_Ports[0]))
+
+unsigned long Console_Configuration_Count = ZYNQ_UART_COUNT;
+
+XUartPs Zynq_Uart_Instance[ZYNQ_UART_COUNT];
+
+static char buf[UART_FIFO_SIZE];
+
+
+static int zynq_uart_first_open(int major, int minor, void *arg)
+{
+  rtems_libio_open_close_args_t *oca = arg;
+  struct rtems_termios_tty      *tty = oca->iop->data1;
+  console_tbl                   *ct  = Console_Port_Tbl[minor];
+  console_data                  *cd  = &Console_Port_Data[minor];
+
+  cd->termios_data = tty;
+  rtems_termios_set_initial_baud(tty, (int32_t) ct->pDeviceParams);
+
+  return 0;
+}
+
+static ssize_t zynq_uart_write(int minor, const char *buf, size_t len)
+{
+  XUartPs *cu = &Zynq_Uart_Instance[minor];
+
+  XUartPs_Send(cu, (unsigned char*)buf, len);
+
+  return len;
+}
+
+static void zynq_uart_write_polled(int minor, char c)
+{
+  XUartPs *cu = &Zynq_Uart_Instance[minor];
+
+  XUartPs_SendByte(cu->Config.BaseAddress, c);
+}
+
+static void zynq_uart_interrupt_handler(void *arg)
+{
+  XUartPs_InterruptHandler((XUartPs*)arg);
+}
+
+static void EventHandler(void*    arg,
+                         uint32_t event,
+                         unsigned byteCount)
+{
+  int             minor = (int) arg;
+  console_data   *cd    = &Console_Port_Data[minor];
+
+  /* Iterate until no more interrupts are pending */
+  switch (event) {
+    case XUARTPS_EVENT_RECV_TOUT:
+    case XUARTPS_EVENT_RECV_DATA:       /* Enqueue received characters */
+    {
+      static unsigned idx = UART_FIFO_SIZE;
+      unsigned        len = 0;
+      XUartPs        *cu  = &Zynq_Uart_Instance[minor];
+      volatile int    i   = 1000;
+
+      if (idx == UART_FIFO_SIZE) {
+        len = XUartPs_Recv(cu, (uint8_t*)buf, sizeof(buf));
+        rtems_termios_enqueue_raw_characters(cd->termios_data, buf, len);
+        idx = len;
+        break;
+      }
+
+      /* I can't believe it works this way!  Hope this wait is short... */
+      while (!XUartPs_IsReceiveData(cu->Config.BaseAddress) && --i);
+      len = XUartPs_ReceiveBuffer(cu);
+      rtems_termios_enqueue_raw_characters(cd->termios_data, &buf[idx], byteCount - idx + 1);
+      idx = byteCount + 1;
+      break;
+    }
+
+    case XUARTPS_EVENT_SENT_DATA:       /* Dequeue transmitted characters */
+      rtems_termios_dequeue_characters(cd->termios_data, byteCount);
+      break;
+
+    default:
+      printk("%s: event = %08x, byteCount = %08x\n", __func__, event, byteCount);
+      break;
+  }
+}
+
+static void zynq_uart_initialize(int minor)
+{
+  console_tbl    *ct = Console_Port_Tbl[minor];
+  XUartPs        *cu = &Zynq_Uart_Instance[minor];
+  XUartPs_Config *uc = XUartPs_LookupConfig(minor);
+  if (uc == NULL) {
+    printk("%s: UartPs configuration for device ID %d not found\n",
+           __func__, minor);
+    rtems_fatal_error_occurred(0xdead0000);
+  }
+
+  /* Initialize the UART driver */
+  int sc = XUartPs_CfgInitialize(cu, uc, uc->BaseAddress);
+  if (sc != XST_SUCCESS) {
+    printk("%s: UartPs configuration initialization for device ID %d failed\n",
+           __func__, minor);
+    rtems_fatal_error_occurred(0xdead0001);
+  }
+
+#if 0  // This fails for some reason
+  /* Perform a self-test to ensure that the hardware was built correctly. */
+  sc = XUartPs_SelfTest(cu);
+  if (sc != XST_SUCCESS) {
+    printk("%s: UartPs self-test for device ID %d failed\n",
+           __func__, minor);
+    rtems_fatal_error_occurred(0xdead0002);
+  }
+#endif
+
+  /* Register a handler to receive the notification events */
+  XUartPs_SetHandler(cu, EventHandler, (void*)minor);
+
+  /* Install interrupt handler and enable the vector */
+  rtems_interrupt_handler_install( ct->ulIntVector,
+                                   "UART",
+                                   RTEMS_INTERRUPT_UNIQUE,
+                                   zynq_uart_interrupt_handler,
+                                   (void *)cu );
+
+  /* Empty the transmit and receive FIFOs */
+  while (XUartPs_IsReceiveData(cu->Config.BaseAddress)) {
+    XUartPs_RecvByte(cu->Config.BaseAddress);
+  }
+
+  /* Enable the UART interrupts */
+  XUartPs_SetInterruptMask(cu, UART_IXR_MASK);
+
+  PRINTK("%-40s: devId = %04x, base = %08x, Hz = %08x, baudRate = %08x\n", __func__,
+         cu->Config.DeviceId, cu->Config.BaseAddress, cu->Config.InputClockHz, cu->BaudRate);
+}
+
+static int zynq_uart_set_attributes(int minor, const struct termios *term)
+{
+  XUartPs *cu = &Zynq_Uart_Instance[minor];
+  int      baud_flags = term->c_cflag & CBAUD;
+
+  if (baud_flags != 0) {
+    int32_t baud = rtems_termios_baud_to_number(baud_flags);
+
+    XUartPs_SetBaudRate(cu, baud);
+  }
+
+  return 0;
+}
+
+console_fns zynq_uart_fns = {
+  .deviceProbe                = libchip_serial_default_probe,
+  .deviceFirstOpen            = zynq_uart_first_open,
+  .deviceLastClose            = NULL,
+  .deviceRead                 = NULL,
+  .deviceWrite                = zynq_uart_write,
+  .deviceInitialize           = zynq_uart_initialize,
+  .deviceWritePolled          = zynq_uart_write_polled,
+  .deviceSetAttributes        = zynq_uart_set_attributes,
+  .deviceOutputUsesInterrupts = true
+};
+
+void zynq_uart_output(char c)
+{
+#ifdef ZYNQ_CONSOLE_DEVICE_ID
+  XUartPs_Config *uc = XUartPs_LookupConfig(ZYNQ_CONSOLE_DEVICE_ID);
+
+  if (c == '\n') {
+      XUartPs_SendByte(uc->BaseAddress, '\r');
+  }
+
+  XUartPs_SendByte(uc->BaseAddress, c);
+#endif
+}
+
+int zynq_uart_input(void)
+{
+#ifdef ZYNQ_CONSOLE_DEVICE_ID
+  XUartPs_Config *uc = XUartPs_LookupConfig(ZYNQ_CONSOLE_DEVICE_ID);
+
+  return XUartPs_RecvByte(uc->BaseAddress);
+#else
+  return 0;
+#endif
+}
+
+BSP_output_char_function_type     BSP_output_char = zynq_uart_output;
+
+BSP_polling_getchar_function_type BSP_poll_char   = zynq_uart_input;
diff --git a/c/src/lib/libbsp/arm/zynq/include/bsp.h b/c/src/lib/libbsp/arm/zynq/include/bsp.h
new file mode 100644
index 0000000..3e31c1a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/bsp.h
@@ -0,0 +1,168 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Global BSP definitions.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_BSP_H
+#define LIBBSP_ARM_ZYNQ_BSP_H
+
+#include <bspopts.h>         /* Generated from configure.ac and bspopts.h.in */
+
+#define BSP_FEATURE_IRQ_EXTENSION /* Needed by llibbsp/shared/clockdrv_shell.h */
+
+#ifndef ASM
+
+#include <rtems.h>
+#include <rtems/console.h>
+#include <rtems/clockdrv.h>
+
+#include <bsp.h>
+#include <bsp/default-initial-extension.h>
+#include <bsp/xscutimer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq ZYNQ Support
+ *
+ * @ingroup bsp_kit
+ *
+ * @brief ZYNQ support package.
+ *
+ * @{
+ */
+
+/* Trickery to expand macro arguments before concatenating them */
+#define BSP_CONCAT(a, b) a ## _ ## b
+#define BSP_EXPAND_AND_CONCAT(a, b) BSP_CONCAT(a, b)
+
+#define BSP_DEVICE_ID(a) BSP_EXPAND_AND_CONCAT(a, DEVICE_ID)
+#define BSP_BASEADDR(a)  BSP_EXPAND_AND_CONCAT(a, BASEADDR)
+
+/**
+ * Network setup.
+ */
+struct rtems_bsdnet_ifconfig;
+
+/**
+ * @brief Network driver attach and detach function.
+ */
+int zynq_eth_attach_detach(struct rtems_bsdnet_ifconfig *config,
+                           int                           attaching);
+
+/**
+ * @brief Standard network driver attach and detach function.
+ */
+#define RTEMS_BSP_NETWORK_DRIVER_ATTACH zynq_eth_attach_detach
+
+/**
+ * @brief Standard network driver name.
+ */
+#define RTEMS_BSP_NETWORK_DRIVER_NAME "eth0"
+
+/**
+ * @brief Optimized idle task.
+ *
+ * This idle task sets the power mode to idle.  This causes the processor clock
+ * to be stopped, while on-chip peripherals remain active.  Any enabled
+ * interrupt from a peripheral or an external interrupt source will cause the
+ * processor to resume execution.
+ *
+ * To enable the idle task use the following in the system configuration:
+ *
+ * @code
+ * #include <bsp.h>
+ *
+ * #define CONFIGURE_INIT
+ *
+ * #define CONFIGURE_IDLE_TASK_BODY zynq_idle
+ *
+ * #include <confdefs.h>
+ * @endcode
+ */
+void *zynq_idle(uintptr_t ignored);
+
+extern XScuTimer Zynq_Timer_Instance;
+
+static inline unsigned zynq_timer(void)
+{
+  return XScuTimer_GetCounterValue(&Zynq_Timer_Instance);
+}
+
+static inline void zynq_micro_seconds_delay(unsigned us)
+{
+  unsigned start   = zynq_timer();
+  unsigned delay   = us * (ZYNQ_TIMER_CLK / 1000000);
+  unsigned elapsed = 0;
+
+  while (elapsed < delay) {
+    elapsed = zynq_timer() - start;
+  }
+}
+
+#define BSP_CONSOLE_UART_BASE ZYNQ_BASE_UART_1
+
+void bsp_restart(void *addr);
+
+void *bsp_idle_thread(uintptr_t arg);
+
+#define BSP_IDLE_TASK_BODY bsp_idle_thread
+
+#define ZYNQ_DO_RESTART(addr)                                       \
+  do {                                                              \
+    ARM_SWITCH_REGISTERS;                                           \
+    rtems_interrupt_level level __attribute__((unused));            \
+    uint32_t ctrl = 0;                                              \
+                                                                    \
+    rtems_interrupt_disable(level);                                 \
+                                                                    \
+    arm_cp15_data_cache_test_and_clean();                           \
+    arm_cp15_instruction_cache_invalidate();                        \
+                                                                    \
+    ctrl = arm_cp15_get_control();                                  \
+    ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M); \
+    arm_cp15_set_control(ctrl);                                     \
+                                                                    \
+    __asm__ volatile (ARM_SWITCH_TO_ARM                             \
+                      "mov pc, %[addr]\n"                           \
+                      ARM_SWITCH_BACK                               \
+                      : ARM_SWITCH_OUTPUT                           \
+                      : [addr] "r" (addr));                         \
+  } while (0)
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* ASM */
+
+#endif /* LIBBSP_ARM_ZYNQ_BSP_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/cache_.h b/c/src/lib/libbsp/arm/zynq/include/cache_.h
new file mode 100644
index 0000000..2289379
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/cache_.h
@@ -0,0 +1,127 @@
+/**
+ * @file
+ *
+ * @ingroup arm
+ *
+ * @brief ARM cache defines and implementation.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBCPU_ARM_CACHE__H
+#define LIBCPU_ARM_CACHE__H
+
+#include <bsp/xil_cache.h>
+#include <bsp/xil_cache_l.h>
+
+#define CPU_DATA_CACHE_ALIGNMENT 32
+#define CPU_INSTRUCTION_CACHE_ALIGNMENT 32
+
+  static inline void _CPU_cache_flush_1_data_line(const void *d_addr)
+  {
+    Xil_DCacheFlushLine((unsigned)d_addr);
+  }
+
+  static inline void _CPU_cache_invalidate_1_data_line(const void *d_addr)
+  {
+    Xil_DCacheInvalidateLine((unsigned)d_addr);
+  }
+
+  static inline void _CPU_cache_freeze_data(void)
+  {
+    /* TODO */
+  }
+
+  static inline void _CPU_cache_unfreeze_data(void)
+  {
+    /* TODO */
+  }
+
+  static inline void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
+  {
+    Xil_ICacheInvalidateLine((unsigned)d_addr);
+  }
+
+  static inline void _CPU_cache_freeze_instruction(void)
+  {
+    /* TODO */
+  }
+
+  static inline void _CPU_cache_unfreeze_instruction(void)
+  {
+    /* TODO */
+  }
+
+  static inline void _CPU_cache_flush_entire_data(void)
+  {
+    Xil_DCacheFlush();
+  }
+
+  static inline void _CPU_cache_invalidate_entire_data(void)
+  {
+    Xil_DCacheInvalidate();
+  }
+
+  static inline void _CPU_cache_enable_data(void)
+  {
+    rtems_interrupt_level level;
+
+    rtems_interrupt_disable(level);
+    Xil_DCacheEnable();
+    rtems_interrupt_enable(level);
+  }
+
+  static inline void _CPU_cache_disable_data(void)
+  {
+    rtems_interrupt_level level;
+
+    rtems_interrupt_disable(level);
+    Xil_DCacheInvalidate();
+    Xil_DCacheDisable();
+    rtems_interrupt_enable(level);
+  }
+
+  static inline void _CPU_cache_invalidate_entire_instruction(void)
+  {
+    Xil_ICacheInvalidate();
+  }
+
+  static inline void _CPU_cache_enable_instruction(void)
+  {
+    rtems_interrupt_level level;
+
+    rtems_interrupt_disable(level);
+    Xil_ICacheEnable();
+    rtems_interrupt_enable(level);
+  }
+
+  static inline void _CPU_cache_disable_instruction(void)
+  {
+    rtems_interrupt_level level;
+
+    rtems_interrupt_disable(level);
+    Xil_ICacheDisable();
+    rtems_interrupt_enable(level);
+  }
+
+#endif /* LIBCPU_ARM_CACHE__H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/clock.h b/c/src/lib/libbsp/arm/zynq/include/clock.h
new file mode 100644
index 0000000..e0d5880
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/clock.h
@@ -0,0 +1,70 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Clock driver configuration.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_CLOCK_H
+#define LIBBSP_ARM_ZYNQ_CLOCK_H
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/zynq.h>
+#include <bsp/xscutimer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq_clock Clock Support
+ *
+ * @ingroup zynq
+ *
+ * @brief Clock support.
+ *
+ * @{
+ */
+
+#define ZYNQ_CLOCK_MODULE_ENABLE()
+
+extern XScuTimer Zynq_Timer_Instance;
+
+#define ZYNQ_TIMER_DEVICE_ID  BSP_DEVICE_ID(ZYNQ_TMR_0)
+
+#define ZYNQ_CLOCK_INTERRUPT  ZYNQ_IRQ_TMR_0
+
+#define ZYNQ_CLOCK_TIMER_BASE BSP_BASEADDR(ZYNQ_TMR_0)
+
+#define ZYNQ_CLOCK_REFERENCE  ZYNQ_TIMER_CLK
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ZYNQ_CLOCK_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/ethernet.h b/c/src/lib/libbsp/arm/zynq/include/ethernet.h
new file mode 100644
index 0000000..c5cb5a0
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/ethernet.h
@@ -0,0 +1,369 @@
+/**
+ * @file
+ *
+ * @ingroup zynq_eth
+ *
+ * @brief Ethernet driver configuration.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_ETHERNET_H
+#define LIBBSP_ARM_ZYNQ_ETHERNET_H
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_mii_ioctl.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#include <bsp.h>
+#include <bsp/zynq.h>
+#include <bsp/xemacps.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq_eth Ethernet Support
+ *
+ * @ingroup zynq
+ *
+ * @brief Ethernet support.
+ *
+ * @{
+ */
+
+#define ZYNQ_ETH_DEVICE_ID        BSP_DEVICE_ID(ZYNQ_ETH_0)
+
+#define ZYNQ_ETH_CONFIG_REG_BASE  BSP_BASEADDR(ZYNQ_ETH_0)
+
+#define ZYNQ_ETH_CONFIG_INTERRUPT ZYNQ_IRQ_ETH_0
+
+/*#define DEBUG 1*/
+/*#define RECORD 1*/
+
+/* Debug */
+#ifdef DEBUG
+  #include <stdio.h>
+  #define PRINTF(...) printf(__VA_ARGS__)
+  #define PRINTK(...) printk(__VA_ARGS__)
+  #define DUMP2(...)  dump2(__VA_ARGS__)
+  #define DUMP4(...)  dump4(__VA_ARGS__)
+#else
+  #define PRINTF(...)
+  #define PRINTK(...)
+  #define DUMP2(...)
+  #define DUMP4(...)
+#endif
+
+static void dump2(char* pfx, const char* f, bool swap, void* p, int l);
+static void dump2(char* pfx, const char* f, bool swap, void* p, int l)
+{
+  int   i;
+  uint16_t* q = (uint16_t*)p;
+
+  printk("%-40s: %s ptr = %08x, len = %08x\n", f, pfx, (uint)p, l);
+
+  l = (l + 1) >> 1;                     /* Convert to number of words */
+
+  while (l > 0) {
+    printk("%08x  ", (uint)q);
+    for (i = 0; l > 0 && i < 8; ++q, --l, ++i) {
+      printk("%04x ", (swap ? ntohs(*q) : *q));
+    }
+    printk("\n");
+  }
+}
+
+
+static void dump4(char* pfx, const char* f, bool swap, void* p, int l);
+static void dump4(char* pfx, const char* f, bool swap, void* p, int l)
+{
+  int   i;
+  uint* q = (uint*)p;
+
+  printk("%-40s: %s ptr = %08x, len = %08x\n", f, pfx, (uint)p, l);
+
+  l = (l + 3) >> 2;                     /* Convert to number of words */
+
+  while (l > 0) {
+    printk("%08x  ", (uint)q);
+    for (i = 0; l > 0 && i < 4; ++q, --l, ++i) {
+      printk("%08x ", (swap ? ntohl(*q) : *q));
+    }
+    printk("\n");
+  }
+}
+
+
+#define XEMACPS_BD_TO_INDEX(ring, bd)				\
+  (((unsigned)(bd) - (unsigned)(ring)->BaseBdAddr) / (ring)->Separation)
+
+
+#define RXBD_CNT 64
+#define TXBD_CNT 128
+
+#define ETH_EMACPS_LINKSPEED_AUTODETECT 0
+#define ETH_EMACPS_LINKSPEED_1000       3
+#define ETH_EMACPS_LINKSPEED_100        2
+#define ETH_EMACPS_LINKSPEED_10         1
+
+#define ETH_EMACPS_CONFIG_RX_UNIT_COUNT_DEFAULT 16
+#define ETH_EMACPS_CONFIG_RX_UNIT_COUNT_MAX INT_MAX
+
+#define ETH_EMACPS_CONFIG_TX_UNIT_COUNT_DEFAULT 32
+#define ETH_EMACPS_CONFIG_TX_UNIT_COUNT_MAX INT_MAX
+
+#define ETH_EMACPS_CONFIG_UNIT_MULTIPLE 8U
+
+#define ETH_EMACPS_CONFIG_INTERRUPT ZYNQ_ETH_CONFIG_INTERRUPT
+#define ETH_EMACPS_CONFIG_LINKSPEED ETH_EMACPS_LINKSPEED_AUTODETECT
+
+#define ETH_EMACPS_RX_DATA_OFFSET 2
+
+/* Events */
+#define ETH_EMACPS_EVENT_INITIALIZE RTEMS_EVENT_1
+#define ETH_EMACPS_EVENT_TXSTART    RTEMS_EVENT_2
+#define ETH_EMACPS_EVENT_INTERRUPT  RTEMS_EVENT_3
+#define ETH_EMACPS_EVENT_STOP       RTEMS_EVENT_4
+
+
+typedef enum {
+  ETH_EMACPS_STATE_NOT_INITIALIZED = 0,
+  ETH_EMACPS_STATE_DOWN,
+  ETH_EMACPS_STATE_UP
+} EthEmacPsState;
+
+/* TX Buffer Descriptor (BD) Status fields (UG585) */
+#define EMACPS_ETH_TX_RETRIES           (0x1 << 29)
+#define EMACPS_ETH_TX_AHB_ERROR         (0x1 << 27)
+#define EMACPS_ETH_TX_LATE_COLLISION    (0x1 << 26)
+#define EMACPS_ETH_TX_CKSUM_ERROR       (0x7 << 20)
+#define EMACPS_ETH_TX_NO_ERROR          (0x0 << 20)
+#define EMACPS_ETH_TX_VLAN_ERROR        (0x1 << 20)
+#define EMACPS_ETH_TX_SNAP_ERROR        (0x2 << 20)
+#define EMACPS_ETH_TX_IP_ERROR          (0x3 << 20)
+#define EMACPS_ETH_TX_ID_ERROR          (0x4 << 20)
+#define EMACPS_ETH_TX_BADFRAG_ERROR     (0x5 << 20)
+#define EMACPS_ETH_TX_TCPUDP_ERROR      (0x6 << 20)
+#define EMACPS_ETH_TX_EOP_ERROR         (0x7 << 20)
+
+/* RX Buffer Descriptor (BD) Status fields (UG585) */
+#define EMACPS_ETH_RX_BCAST             (0x1 << 30)
+#define EMACPS_ETH_RX_MCAST             (0x1 << 29)
+#define EMACPS_ETH_RX_UCAST             (0x1 << 28)
+#define EMACPS_ETH_RX_EXTERNAL          (0x3 << 25)
+#define EMACPS_ETH_RX_ADX1              (0x0 << 25)
+#define EMACPS_ETH_RX_ADX2              (0x1 << 25)
+#define EMACPS_ETH_RX_ADX3              (0x2 << 25)
+#define EMACPS_ETH_RX_ADX4              (0x3 << 25)
+#define EMACPS_ETH_RX_BIT_24            (0x1 << 24)
+#define EMACPS_ETH_RX_BIT_22_23         (0x3 << 22)
+#define EMACPS_ETH_RX_REG1              (0x0 << 22)
+#define EMACPS_ETH_RX_REG2              (0x1 << 22)
+#define EMACPS_ETH_RX_REG3              (0x2 << 22)
+#define EMACPS_ETH_RX_REG4              (0x3 << 22)
+#define EMACPS_ETH_RX_VLAN              (0x1 << 21)
+#define EMACPS_ETH_RX_PRIORITY          (0x1 << 20)
+#define EMACPS_ETH_RX_CFI               (0x1 << 16)
+#define EMACPS_ETH_RX_EOF               (0x1 << 15)
+#define EMACPS_ETH_RX_SOF               (0x1 << 14)
+#define EMACPS_ETH_RX_FCS               (0x1 << 13)
+
+#define EMACPS_ETH_TX_STAT_MASK         (EMACPS_ETH_TX_RETRIES        | \
+                                         EMACPS_ETH_TX_AHB_ERROR      | \
+                                         EMACPS_ETH_TX_LATE_COLLISION | \
+                                         EMACPS_ETH_TX_CKSUM_ERROR    )
+
+#define EMACPS_ETH_RX_STAT_MASK         (EMACPS_ETH_RX_BCAST          | \
+                                         EMACPS_ETH_RX_MCAST          | \
+                                         EMACPS_ETH_RX_UCAST          | \
+                                         EMACPS_ETH_RX_EXTERNAL       | \
+                                         EMACPS_ETH_RX_BIT_24         | \
+                                         EMACPS_ETH_RX_BIT_22_23      | \
+                                         EMACPS_ETH_RX_VLAN           | \
+                                         EMACPS_ETH_RX_PRIORITY       | \
+                                         EMACPS_ETH_RX_CFI            | \
+                                         EMACPS_ETH_RX_EOF            | \
+                                         EMACPS_ETH_RX_SOF            | \
+                                         EMACPS_ETH_RX_FCS            )
+
+struct EthEmacPsStats
+{
+  uint32_t rxd_frames;
+  uint32_t rx_interrupts;
+
+  uint32_t txd_frames;
+  uint32_t tx_interrupts;
+
+  uint32_t rx_drop;
+  uint32_t rx_recv;
+  uint32_t rx_memErr;
+  uint32_t rx_dma_errors;
+  uint32_t rx_overruns;
+  uint32_t rx_no_buffers;
+  uint32_t rx_unknowns;
+
+  uint32_t rx_stat_bcast;
+  uint32_t rx_stat_mcast;
+  uint32_t rx_stat_ucast;
+  uint32_t rx_stat_adx1;
+  uint32_t rx_stat_adx2;
+  uint32_t rx_stat_adx3;
+  uint32_t rx_stat_adx4;
+  uint32_t rx_stat_bit_24;
+  uint32_t rx_stat_reg1;
+  uint32_t rx_stat_reg2;
+  uint32_t rx_stat_reg3;
+  uint32_t rx_stat_reg4;
+  uint32_t rx_stat_vlan;
+  uint32_t rx_stat_priority;
+  uint32_t rx_stat_cfi;
+  uint32_t rx_stat_eof;
+  uint32_t rx_stat_sof;
+  uint32_t rx_stat_fcs;
+
+  uint32_t tx_drop;
+  uint32_t tx_xmit;
+  uint32_t tx_dma_errors;
+  uint32_t tx_underruns;
+  uint32_t tx_no_buffers;
+  uint32_t tx_excessive_retries;
+  uint32_t tx_collisions;
+  uint32_t tx_usedread;
+  uint32_t tx_unknowns;
+  uint32_t tx_overflows;
+  uint32_t tx_full_queues;
+
+  uint32_t tx_stat_retries;
+  uint32_t tx_stat_ahb_errors;
+  uint32_t tx_stat_late_collisions;
+  uint32_t tx_stat_no_errors;
+  uint32_t tx_stat_vlan_errors;
+  uint32_t tx_stat_snap_errors;
+  uint32_t tx_stat_ip_errors;
+  uint32_t tx_stat_id_errors;
+  uint32_t tx_stat_badfrag_errors;
+  uint32_t tx_stat_tcpudp_errors;
+  uint32_t tx_stat_eop_errors;
+};
+
+typedef struct {
+  XEmacPs                  instance;
+  struct arpcom            arpcom;
+  EthEmacPsState           state;
+  struct rtems_mdio_info   mdio;
+  unsigned                 rxUnitCount;
+  unsigned                 txUnitCount;
+  struct mbuf            **rxMbufTable;
+  struct mbuf            **txMbufTable;
+  rtems_vector_number      irqNumber;
+  rtems_id                 controlTask;
+
+  /* Pointers to memory holding buffer descriptors (used only with SDMA) */
+  void                    *rxBdSpace;
+  void                    *txBdSpace;
+
+  unsigned                 linkSpeed;
+
+  struct EthEmacPsStats    stats;
+} EthEmacPs;
+
+static inline char *eth_emacps_config_alloc_table_area(size_t size)
+{
+  char* tableArea;
+
+  PRINTK("%-40s: beg\n", __func__);
+  tableArea = rtems_heap_allocate_aligned_with_boundary(size, 32, 0);
+  PRINTK("%-40s: end - tableArea = %08x\n", __func__, (uint)tableArea);
+  return tableArea;
+}
+
+static inline void eth_emacps_config_free_table_area(char *table_area)
+{
+  PRINTK("%-40s: beg\n", __func__);
+  /* FIXME: Type */
+  free(table_area, (int) 0xdeadbeef);
+  PRINTK("%-40s: end\n", __func__);
+}
+
+/* ethEmacPs */
+void              eth_emacps_low_level_init(void*);
+rtems_status_code eth_emacps_output(EthEmacPs*, struct mbuf*);
+int               eth_emacps_input(EthEmacPs*, XEmacPs_BdRing*);
+void              eth_emacps_handle_error(EthEmacPs*);
+void              eth_emacps_handle_tx_errors(EthEmacPs*);
+void              eth_emacps_error_task(void *);
+
+/* ethEmacPs_dma */
+int               eth_emacps_setup_rx_dscs(EthEmacPs*, XEmacPs_BdRing*);
+int               eth_emacps_setup_tx_dscs(EthEmacPs*, XEmacPs_BdRing*);
+void              eth_emacps_process_rxd_bds(EthEmacPs*, XEmacPs_BdRing*, int);
+void              eth_emacps_process_txd_bds(EthEmacPs*, XEmacPs_BdRing*);
+void              eth_emacps_free_tx_rx_mbufs(EthEmacPs*);
+void              eth_emacps_free_only_tx_mbufs(EthEmacPs*);
+rtems_status_code eth_emacps_sgsend(EthEmacPs*, struct mbuf*);
+int               eth_emacps_init_dma(EthEmacPs*);
+void              eth_emacps_send_handler(void*);
+void              eth_emacps_recv_handler(void*);
+
+/* ethEmacPs_hw */
+void              eth_emacps_start(EthEmacPs*);
+void              eth_emacps_stop(EthEmacPs*);
+void              eth_emacps_reset(EthEmacPs*);
+int               eth_emacps_init_mac(EthEmacPs*);
+int               eth_emacps_setup_isr(EthEmacPs*);
+void              eth_emacps_init_on_error(EthEmacPs*);
+void              eth_emacps_error_handler(void*, uint8_t, uint32_t);
+
+/* ethEmacPs_phySpeed */
+unsigned          eth_emacps_phy_setup(EthEmacPs*);
+unsigned          eth_emacps_get_IEEE_phy_speed(EthEmacPs*);
+unsigned          eth_emacps_configure_IEEE_phy_speed(EthEmacPs*, unsigned);
+
+/* ethernet */
+struct mbuf      *eth_emacps_add_new_mbuf(EthEmacPs*, struct mbuf**, int);
+int               zynq_eth_attach_detach(struct rtems_bsdnet_ifconfig*, int);
+
+extern rtems_id  gEthEmacPsRxTask;
+extern rtems_id  gEthEmacPsTxTask;
+extern rtems_id  gEthEmacPsErTask;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ZYNQ_ETHERNET_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/i2c.h b/c/src/lib/libbsp/arm/zynq/include/i2c.h
new file mode 100644
index 0000000..79ed2e5
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/i2c.h
@@ -0,0 +1,135 @@
+/**
+ * @file
+ *
+ * @ingroup zynq_i2c
+ *
+ * @brief I2C support API.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_I2C_H
+#define LIBBSP_ARM_ZYNQ_I2C_H
+
+#include <rtems.h>
+#include <rtems/libi2c.h>
+
+#include <bsp.h>
+#include <bsp/zynq.h>
+#include <bsp/xiicps.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq_i2c I2C Support
+ *
+ * @ingroup zynq
+ *
+ * @brief I2C Support
+ *
+ * All writes and reads will be performed in master mode.  Exclusive bus access
+ * will be assumed.
+ *
+ * @{
+ */
+
+#define ZYNQ_I2C_DEVICE_ID BSP_DEVICE_ID(ZYNQ_I2C_0)
+
+#define ZYNQ_I2C_BASE      BSP_BASEADDR(ZYNQ_I2C_0)
+
+#define ZYNQ_I2C_INTERRUPT ZYNQ_IRQ_I2C_0
+
+#define DEVICE_BUSY -1
+
+typedef struct {
+  rtems_libi2c_bus_t   bus;
+  XIicPs               instance;
+  rtems_vector_number  vector;
+  rtems_id             state_update;
+} zynq_i2c_bus_entry;
+
+/**
+ * @brief Resets the I2C module @a instance.
+ */
+void zynq_i2c_reset(zynq_i2c_bus_entry *e);
+
+/**
+ * @brief Abort an I2C transaction for module @a instance.
+ */
+void zynq_i2c_abort(zynq_i2c_bus_entry *e);
+
+/**
+ * @brief Sets the I2C module @a instance clock.
+ *
+ * Valid @a clock_in_hz values are 100000 and 400000.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code zynq_i2c_clock(zynq_i2c_bus_entry *e, unsigned clock_in_hz);
+
+/**
+ * @brief Initializes the I2C module @a instance.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a instance value.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code zynq_i2c_init(rtems_libi2c_bus_t *bus);
+
+/**
+ * @brief Waits for transaction completion of the I2C module @a instance.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ */
+rtems_status_code wait_for_transaction_done(zynq_i2c_bus_entry *e);
+
+/**
+ * @brief Writes data via the I2C module @a instance.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+int zynq_i2c_write(rtems_libi2c_bus_t *bus, uint8_t *out, int n);
+
+/**
+ * @brief Reads data via the I2C module @a instance.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ * @retval RTEMS_NOT_IMPLEMENTED Stop is @a false.
+ */
+int zynq_i2c_read(rtems_libi2c_bus_t *bus, uint8_t *in, int n);
+
+/** @} */
+
+extern XIicPs Zynq_I2C_Instance;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ZYNQ_I2C_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/irq.h b/c/src/lib/libbsp/arm/zynq/include/irq.h
new file mode 100644
index 0000000..d9039be
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/irq.h
@@ -0,0 +1,93 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief Interrupt definitions.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_IRQ_H
+#define LIBBSP_ARM_ZYNQ_IRQ_H
+
+#ifndef ASM
+
+#include <rtems.h>
+#include <rtems/irq.h>
+#include <rtems/irq-extension.h>
+
+#include <bsp/zynq.h>
+#include <bsp/xscugic.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup bsp_interrupt
+ *
+ * @{
+ */
+
+#define ZYNQ_INTC_DEVICE_ID  BSP_DEVICE_ID(ZYNQ_INTC)
+
+#define ZYNQ_IRQ_INDEX(module, subindex) ((module) + (subindex))
+
+#define ZYNQ_IRQ_MODULE_SGI    0U
+#define ZYNQ_IRQ_MODULE_PPI   16U
+#define ZYNQ_IRQ_MODULE_SPI   32U
+#define ZYNQ_IRQ_MODULE_COUNT  3U
+
+#define ZYNQ_IRQ_PRIORITY_VALUE_MIN  0U
+#define ZYNQ_IRQ_PRIORITY_VALUE_MAX  XSCUGIC_PRIORITY_MAX
+#define ZYNQ_IRQ_PRIORITY_COUNT     (ZYNQ_IRQ_PRIORITY_VALUE_MAX + 1U)
+#define ZYNQ_IRQ_PRIORITY_HIGHEST    ZYNQ_IRQ_PRIORITY_VALUE_MIN
+#define ZYNQ_IRQ_PRIORITY_LOWEST     ZYNQ_IRQ_PRIORITY_VALUE_MAX
+
+#define BSP_INTERRUPT_VECTOR_MIN      0  /* ZYNQ_IRQ_SW_0 */
+#define BSP_INTERRUPT_VECTOR_MAX      XPS_FPGA15_INT_ID
+
+#define ZYNQ_IRQ_COUNT              (BSP_INTERRUPT_VECTOR_MAX + 1)
+
+void zynq_irq_set_priority_trigger(rtems_vector_number vector,
+                                   unsigned            priority,
+                                   unsigned            trigger);
+
+void zynq_irq_get_priority_trigger(rtems_vector_number  vector,
+                                   unsigned            *priority,
+                                   unsigned            *trigger);
+
+void zynq_set_exception_handler(Arm_symbolic_exception_name exception, void (*handler)(void));
+
+extern XScuGic Zynq_Intc_Instance;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* ASM */
+
+#endif /* LIBBSP_ARM_ZYNQ_IRQ_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/mmu.h b/c/src/lib/libbsp/arm/zynq/include/mmu.h
new file mode 100644
index 0000000..e81dab3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/mmu.h
@@ -0,0 +1,112 @@
+/**
+ * @file
+ *
+ * @ingroup zynq_mmu
+ *
+ * @brief MMU support API.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_MMU_H
+#define LIBBSP_ARM_ZYNQ_MMU_H
+
+#include <libcpu/arm-cp15.h>
+
+#include <bsp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq_mmu MMU Support
+ *
+ * @ingroup zynq
+ *
+ * @brief MMU support.
+ *
+ * @{
+ */
+
+#define ZYNQ_MMU_CLIENT_DOMAIN 15U
+
+#define ZYNQ_MMU_READ_ONLY \
+  ((ZYNQ_MMU_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
+    | ARM_MMU_SECT_DEFAULT)
+
+#define ZYNQ_MMU_READ_ONLY_CACHED \
+  (ZYNQ_MMU_READ_ONLY | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
+
+#define ZYNQ_MMU_READ_WRITE \
+  ((ZYNQ_MMU_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
+    | ARM_MMU_SECT_AP_0 \
+    | ARM_MMU_SECT_DEFAULT)
+
+#define ZYNQ_MMU_READ_WRITE_CACHED \
+  (ZYNQ_MMU_READ_WRITE | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
+
+/**
+ * @brief Disable the MMU.
+ *
+ * @return The MMU-related CP15 flags prior to disabling the MMU
+ */
+uint32_t zynq_disable_mmu(void);
+
+/**
+ * @brief Enable the MMU.
+ */
+void zynq_enable_mmu(void);
+
+/**
+ * @brief Sets the @a section_flags for the address range [@a begin, @a end).
+ *
+ *  The caller is responsible for ensuring that the MMU is in an acceptable
+ *  state for translation table entries to be replaced.
+ *
+ * @return Previous section flags of the first modified entry.
+ */
+uint32_t zynq_set_translation_table_block(const void *begin,
+                                          const void *end,
+                                          uint32_t    section_flags);
+
+/**
+ * @brief Sets the @a section_flags for the address range [@a begin, @a end).
+ *
+ *  This function places the MMU in an acceptable state for replacing
+ *  translation table entries prior to calling
+ *  @a zynq_set_translation_table_block().
+ *
+ * @return Previous section flags of the first modified entry.
+ */
+uint32_t zynq_set_translation_table_entries(const void *begin,
+                                            const void *end,
+                                            uint32_t    section_flags);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ZYNQ_MMU_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/tm27.h b/c/src/lib/libbsp/arm/zynq/include/tm27.h
new file mode 100644
index 0000000..34ca3e5
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/tm27.h
@@ -0,0 +1,73 @@
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <info at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_TMTEST27
+#error "This is an RTEMS internal file you must not include directly."
+#endif
+
+#ifndef __tm27_h
+#define __tm27_h
+
+#include <assert.h>
+
+#include <rtems.h>
+
+#include <bsp/zynq.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#define MUST_WAIT_FOR_INTERRUPT 1
+
+static void Install_tm27_vector(void (*handler)(rtems_vector_number))
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  // @todo - Clear it: ZYNQ_SW_INT = 0;
+
+  sc = rtems_interrupt_handler_install(
+    ZYNQ_IRQ_SW_0,
+    "SW",
+    RTEMS_INTERRUPT_UNIQUE,
+    (rtems_interrupt_handler) handler,
+    NULL
+  );
+  assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void Cause_tm27_intr(void)
+{
+  XScuGic_SoftwareIntr(&Zynq_Intc_Instance, ZYNQ_IRQ_SW_0, 0);
+}
+
+static void Clear_tm27_intr(void)
+{
+  // @todo - Clear it: ZYNQ_SW_INT = 0;
+  zynq_irq_set_priority_trigger(ZYNQ_IRQ_SW_0, ZYNQ_IRQ_PRIORITY_LOWEST, 0);
+}
+
+static void Lower_tm27_intr(void)
+{
+  bsp_interrupt_vector_enable(ZYNQ_IRQ_SW_0);
+  zynq_irq_set_priority_trigger(ZYNQ_IRQ_SW_0, ZYNQ_IRQ_PRIORITY_HIGHEST, 0);
+}
+
+#endif /* __tm27_h */
diff --git a/c/src/lib/libbsp/arm/zynq/include/uart.h b/c/src/lib/libbsp/arm/zynq/include/uart.h
new file mode 100644
index 0000000..66ab291
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/uart.h
@@ -0,0 +1,133 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Console driver configuration.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_UART_H
+#define LIBBSP_ARM_ZYNQ_UART_H
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/xuartps.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup zynq_console Console Support
+ *
+ * @ingroup zynq
+ *
+ * @brief Console support.
+ *
+ * @{
+ */
+
+#ifdef ZYNQ_UART_0
+#  define ZYNQ_IRQ_TMR           ZYNQ_IRQ_TMR_0
+#  define ZYNQ_CLK_UART_0        XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
+#  define ZYNQ_CFG_UART_0                             \
+  {                                                   \
+    .sDeviceName   = "/dev/ttyS0",                    \
+    .deviceType    = SERIAL_CUSTOM,                   \
+    .pDeviceFns    = &zynq_uart_fns,                  \
+    .deviceProbe   = NULL,                            \
+    .pDeviceFlow   = NULL,                            \
+    .ulMargin      = 16,                              \
+    .ulHysteresis  = 8,                               \
+    .pDeviceParams = (void *) ZYNQ_UART_0_BAUD,       \
+    .ulCtrlPort1   = BSP_BASEADDR(ZYNQ_UART_0),       \
+    .ulCtrlPort2   = 0,                               \
+    .ulDataPort    = BSP_BASEADDR(ZYNQ_UART_0),       \
+    .getRegister   = zynq_uart_get_register,          \
+    .setRegister   = zynq_uart_set_register,          \
+    .getData       = NULL,                            \
+    .setData       = NULL,                            \
+    .ulClock       = ZYNQ_CLK_UART_0,                 \
+    .ulIntVector   = ZYNQ_IRQ_UART_0                  \
+  }
+#endif
+#ifdef ZYNQ_UART_1
+#  define ZYNQ_CLK_UART_1        XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
+#  define ZYNQ_CFG_UART_1                             \
+  {                                                   \
+    .sDeviceName   = "/dev/ttyS1",                    \
+    .deviceType    = SERIAL_CUSTOM,                   \
+    .pDeviceFns    = &zynq_uart_fns,                  \
+    .deviceProbe   = NULL,                            \
+    .pDeviceFlow   = NULL,                            \
+    .ulMargin      = 16,                              \
+    .ulHysteresis  = 8,                               \
+    .pDeviceParams = (void *) ZYNQ_UART_1_BAUD,       \
+    .ulCtrlPort1   = BSP_BASEADDR(ZYNQ_UART_1),       \
+    .ulCtrlPort2   = 0,                               \
+    .ulDataPort    = BSP_BASEADDR(ZYNQ_UART_1),       \
+    .getRegister   = zynq_uart_get_register,          \
+    .setRegister   = zynq_uart_set_register,          \
+    .getData       = NULL,                            \
+    .setData       = NULL,                            \
+    .ulClock       = ZYNQ_CLK_UART_1,                 \
+    .ulIntVector   = ZYNQ_IRQ_UART_1                  \
+  }
+#endif
+
+/* The console will be the first UART found */
+#if   defined(ZYNQ_UART_0)
+#  define ZYNQ_CONSOLE_DEVICE_ID  BSP_DEVICE_ID(ZYNQ_UART_0)
+#elif defined(ZYNQ_UART_1)
+#  define ZYNQ_CONSOLE_DEVICE_ID  BSP_DEVICE_ID(ZYNQ_UART_1)
+#endif
+
+static inline uint8_t zynq_uart_get_register(uintptr_t addr, uint8_t i)
+{
+  volatile uint32_t *reg = (volatile uint32_t *) addr;
+
+  return (uint8_t) reg [i];
+}
+
+static inline void zynq_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
+{
+  volatile uint32_t *reg = (volatile uint32_t *) addr;
+
+  reg [i] = val;
+}
+
+/** @} */
+
+extern console_fns    zynq_uart_fns;
+extern XUartPs        Zynq_Uart_Instance[];
+extern XUartPs_Config XUartPs_ConfigTable[];
+
+void zynq_uart_output(char);
+int  zynq_uart_input(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ZYNQ_UART_H */
diff --git a/c/src/lib/libbsp/arm/zynq/include/zynq.h b/c/src/lib/libbsp/arm/zynq/include/zynq.h
new file mode 100644
index 0000000..2554a8a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/include/zynq.h
@@ -0,0 +1,73 @@
+/**
+ * @file
+ *
+ * @ingroup zynq_reg
+ *
+ * @brief Register base addresses.
+ */
+
+/*
+ * Authorship
+ * ----------
+ * This software was created by
+ *     R. Claus <claus at slac.stanford.edu>, 2013,
+ *       Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * This software was produced by
+ *     the Stanford Linear Accelerator Center, Stanford University,
+ *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software.  Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#ifndef LIBBSP_ARM_ZYNQ_ZYNQ_H
+#define LIBBSP_ARM_ZYNQ_ZYNQ_H
+
+#include <bspopts.h>         /* Generated from configure.ac and bspopts.h.in */
+
+/**
+ * @defgroup zynq_reg Register Definitions
+ *
+ * @ingroup zynq
+ *
+ * @brief Register definitions.
+ *
+ * @{
+ */
+
+#include <bsp/xparameters.h>
+
+/** @} */
+
+#endif /* LIBBSP_ARM_ZYNQ_ZYNQ_H */
diff --git a/c/src/lib/libbsp/arm/zynq/irq/irq.c b/c/src/lib/libbsp/arm/zynq/irq/irq.c
new file mode 100644
index 0000000..33af108
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/irq/irq.c
@@ -0,0 +1,214 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/mmu.h>
+
+#include "xil_types.h"
+#include "xil_assert.h"
+#include "xscugic.h"
+
+/*#define DEBUG 1*/
+
+/* Debug */
+#ifdef DEBUG
+  #include <stdio.h>
+  #define PRINTF(...) printf(__VA_ARGS__)
+  #define PRINTK(...) printk(__VA_ARGS__)
+#else
+  #define PRINTF(...)
+  #define PRINTK(...)
+#endif
+
+XScuGic Zynq_Intc_Instance;
+
+
+void zynq_irq_set_priority_trigger(rtems_vector_number vector,
+                                   unsigned            priority,
+                                   unsigned            trigger)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  XScuGic_SetPriorityTriggerType(&Zynq_Intc_Instance, vector, priority, trigger);
+  rtems_interrupt_enable(level);
+}
+
+void zynq_irq_get_priority_trigger(rtems_vector_number  vector,
+                                   unsigned            *priority,
+                                   unsigned            *trigger)
+{
+  unsigned char p;
+  unsigned char t;
+
+  XScuGic_GetPriorityTriggerType(&Zynq_Intc_Instance, vector, &p, &t);
+
+  *priority = p;
+  *trigger  = t;
+}
+
+void bsp_interrupt_dispatch(void)
+{
+  unsigned vector;
+
+  /*
+   * Read the int_ack register to identify the highest priority interrupt ID
+   * and make sure it is valid. Reading Int_Ack will clear the interrupt
+   * in the GIC.
+   */
+  vector = XScuGic_CPUReadReg(&Zynq_Intc_Instance,
+                              XSCUGIC_INT_ACK_OFFSET) & XSCUGIC_ACK_INTID_MASK;
+
+  /*
+   * If the interrupt is shared, do some locking here if there are multiple
+   * processors.
+   */
+  /*
+   * If pre-emption is required:
+   * Re-enable pre-emption by setting the CPSR I bit for non-secure ,
+   * interrupts or the F bit for secure interrupts
+   */
+
+  /*
+   * If we need to change security domains, issue a SMC instruction here.
+   */
+
+  /* Enable interrupts in program status register */
+  uint32_t psr = _ARMV4_Status_irq_enable();
+
+  /*
+   * Execute the ISR. Jump into the Interrupt service routine based on the
+   * IRQSource. A software trigger is cleared by the ACK.
+   */
+  bsp_interrupt_handler_dispatch(vector);
+
+  /* Restore program status register */
+  _ARMV4_Status_restore(psr);
+
+  /*
+   * Write to the EOI register, we are all done here.
+   * Let this function return, the boot code will restore the stack.
+   */
+  XScuGic_CPUWriteReg(&Zynq_Intc_Instance, XSCUGIC_EOI_OFFSET, vector);
+
+  /*
+   * Return from the interrupt. Change security domains could happen here.
+   */
+}
+
+rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  XScuGic_Enable(&Zynq_Intc_Instance, vector);
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: Vector %08x enabled\n", __func__, vector);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  XScuGic_Disable(&Zynq_Intc_Instance, vector);
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: Vector %08x disabled\n", __func__, vector);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+void zynq_set_exception_handler(Arm_symbolic_exception_name exception,
+                                void (*handler)(void))
+{
+  PRINTK("%-40s: exc = %08x, max = %08x, handler = %08x\n",
+         __func__, exception, MAX_EXCEPTIONS, (uint)handler);
+
+  if ((unsigned) exception < MAX_EXCEPTIONS) {
+    uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS;
+
+    PRINTK("%-40s: tbl = %08x, bsp_tbl = %08x\n",
+           __func__, (uint)table, (uint)bsp_vector_table_begin);
+
+    table [exception] = (uint32_t) handler;
+
+    PRINTK("%-40s: &tbl[exc] = %08x\n", __func__, (uint)&table[exception]);
+
+#ifndef ZYNQ_DISABLE_MMU
+    rtems_cache_flush_multiple_data_lines(table, 64);
+    rtems_cache_invalidate_multiple_instruction_lines(NULL, 64);
+#endif
+  }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+  int sc;
+
+  /* Look up the interrupt controller configuration */
+  XScuGic_Config *cfg = XScuGic_LookupConfig(ZYNQ_INTC_DEVICE_ID);
+  if (cfg == NULL) {
+    printk("%s: ScuGic configuration for device ID %d not found\n",
+           __func__, ZYNQ_INTC_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0000);
+  }
+
+  /* Initialize the interrupt controller driver */
+  sc = XScuGic_CfgInitialize(&Zynq_Intc_Instance, cfg, cfg->CpuBaseAddress);
+  if (sc != XST_SUCCESS) {
+    printk("%s: ScuGic configuration initialization for device ID %d failed\n",
+           __func__, ZYNQ_INTC_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0001);
+  }
+
+  /* Perform a self-test to ensure that the hardware was built correctly. */
+  sc = XScuGic_SelfTest(&Zynq_Intc_Instance);
+  if (sc != XST_SUCCESS) {
+    printk("%s: ScuGic self-test for device ID %d failed\n",
+           __func__, ZYNQ_INTC_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0002);
+  }
+
+  /* Install the IRQ exception handler */
+  zynq_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt);
+
+  PRINTK("%-40s: IRQ handler %08x installed: %08x\n",
+         __func__, ARM_EXCEPTION_IRQ, (uint)_ARMV4_Exception_interrupt);
+
+  return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/arm/zynq/make/custom/zc702.cfg b/c/src/lib/libbsp/arm/zynq/make/custom/zc702.cfg
new file mode 100644
index 0000000..cf3bf4e
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/make/custom/zc702.cfg
@@ -0,0 +1,5 @@
+#
+#  Config file for ZC702.
+#
+
+include $(RTEMS_ROOT)/make/custom/zynq.inc
diff --git a/c/src/lib/libbsp/arm/zynq/make/custom/zedboard.cfg b/c/src/lib/libbsp/arm/zynq/make/custom/zedboard.cfg
new file mode 100644
index 0000000..827f8b8
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/make/custom/zedboard.cfg
@@ -0,0 +1,5 @@
+#
+#  Config file for ZEDBOARD.
+#
+
+include $(RTEMS_ROOT)/make/custom/zynq.inc
diff --git a/c/src/lib/libbsp/arm/zynq/make/custom/zynq.inc b/c/src/lib/libbsp/arm/zynq/make/custom/zynq.inc
new file mode 100644
index 0000000..de135a6
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/make/custom/zynq.inc
@@ -0,0 +1,14 @@
+#
+#  Config file for ZYNQ-based boards.
+#
+
+include $(RTEMS_ROOT)/make/custom/default.cfg
+
+RTEMS_CPU = arm
+
+#  This contains the compiler options necessary to select the CPU model
+#  and (hopefully) optimize for it.
+CPU_CFLAGS = -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=soft
+
+# optimize flag: typically -O2
+CFLAGS_OPTIMIZE_V ?= -O2 -g
diff --git a/c/src/lib/libbsp/arm/zynq/misc/i2c.c b/c/src/lib/libbsp/arm/zynq/misc/i2c.c
new file mode 100644
index 0000000..50752ab
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/misc/i2c.c
@@ -0,0 +1,247 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief I2C support implementation.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <rtems/status-checks.h>
+
+#include <bsp.h>
+#include <bsp/i2c.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+//#include <bsp/system-clocks.h>  // Not found
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#define DEBUG
+
+#define PRINTK RTEMS_DEBUG_PRINT
+
+// PS I2C0 Init Parameters -> ZC702 via MIO
+#define ZC702_IIC_DEVICE_ID  XPAR_XIICPS_0_DEVICE_ID
+#define ZC702_IIC_SCLK_RATE  100000
+
+
+// PS I2C1 Init Parameters -> FMC via EMIO
+#define FMC_IIC_DEVICE_ID  XPAR_XIICPS_1_DEVICE_ID
+#define FMC_IIC_SCLK_RATE  100000
+
+
+void zynq_i2c_reset(zynq_i2c_bus_entry *e)
+{
+  XIicPs_Reset(&e->instance);
+}
+
+void zynq_i2c_abort(zynq_i2c_bus_entry *e)
+{
+  XIicPs_Abort(&e->instance);
+}
+
+rtems_status_code zynq_i2c_clock(zynq_i2c_bus_entry *e,
+                                 unsigned            clock_in_hz)
+{
+  int sc;
+
+  sc = XIicPs_SetSClk(&e->instance, clock_in_hz);
+  if (sc != XST_SUCCESS) {
+    PRINTK("Setting I2C clock rate for device ID %d failed\n",
+           ZYNQ_I2C_DEVICE_ID);
+    return sc;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static void zynq_i2c_handler(void *arg)
+{
+  XIicPs_MasterInterruptHandler((XIicPs*)arg);
+}
+
+rtems_status_code wait_for_transaction_done(zynq_i2c_bus_entry *e)
+{
+  bsp_interrupt_vector_enable(e->vector);
+
+  return rtems_semaphore_obtain(e->state_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+rtems_status_code zynq_i2c_init(rtems_libi2c_bus_t *bus)
+{
+  int                 sc;
+  unsigned            clock_in_hz = XPAR_XIICPS_0_I2C_CLK_FREQ_HZ;
+  zynq_i2c_bus_entry *e           = (zynq_i2c_bus_entry *)bus;
+
+  /* Look up the timer configuration */
+  XIicPs_Config *cfg = XIicPs_LookupConfig(ZYNQ_I2C_DEVICE_ID);
+  if (cfg == NULL) {
+    printk("%s: I2C configuration for device ID %d not found\n",
+           __func__, ZYNQ_I2C_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0000);
+  }
+
+  /* Initialize the IIC driver */
+  sc = XIicPs_CfgInitialize(&e->instance, cfg, cfg->BaseAddress);
+  if (sc != XST_SUCCESS) {
+    printk("%s: I2C configuration initialization for device ID %d failed\n",
+           __func__, ZYNQ_I2C_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0001);
+  }
+
+  /* Perform a self-test to ensure that the hardware was built correctly. */
+  sc = XIicPs_SelfTest(&e->instance);
+  if (sc != XST_SUCCESS) {
+    printk("%s: I2C self-test for device ID %d failed\n",
+           __func__, ZYNQ_I2C_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0002);
+  }
+
+  /* Set up the clock */
+  sc = zynq_i2c_clock(e, clock_in_hz);
+  if (sc != RTEMS_SUCCESSFUL) {
+    printk("%s: I2C SetSClk() failed for device ID %d failed\n",
+           __func__, ZYNQ_I2C_DEVICE_ID);
+    rtems_fatal_error_occurred(0xdead0003);
+  }
+
+  /* Create semaphore */
+  sc = rtems_semaphore_create(rtems_build_name('I', '2', 'C', '0' + ZYNQ_I2C_DEVICE_ID),
+                              0,
+                              RTEMS_SIMPLE_BINARY_SEMAPHORE,
+                              0,
+                              &e->state_update);
+  RTEMS_CHECK_SC(sc, "create status update semaphore");
+
+  /* Install interrupt handler and disable this vector */
+  sc = rtems_interrupt_handler_install(e->vector,
+                                       "I2C",
+                                       RTEMS_INTERRUPT_UNIQUE,
+                                       zynq_i2c_handler,
+                                       e);
+  RTEMS_CHECK_SC(sc, "install interrupt handler");
+  bsp_interrupt_vector_disable(e->vector);
+
+  /* Enable module in master mode */
+  /* ??? */
+  return sc;
+}
+
+int zynq_i2c_write(rtems_libi2c_bus_t *bus, uint8_t *out, int n)
+{
+  rtems_status_code   sc;
+  zynq_i2c_bus_entry *e  = (zynq_i2c_bus_entry *)bus;
+  const uint8_t addr = 0;               /* @todo - REVISIT */
+  uint8_t reg;                          /* @todo - REVISIT */
+
+  if (XIicPs_BusIsBusy(&e->instance)) {
+    return DEVICE_BUSY;
+  }
+
+  sc = XIicPs_MasterSendPolled(&e->instance, &reg, 1, addr);
+  if (sc != XST_SUCCESS) {
+    PRINTK("XIicPs_MasterSendPolled failed\n");
+    return XST_FAILURE;
+  }
+
+  sc = XIicPs_MasterSendPolled(&e->instance, out, n, addr);
+  if (sc != XST_SUCCESS) {
+    PRINTK("XIicPs_MasterSendPolled failed\n");
+    return XST_FAILURE;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+int zynq_i2c_read(rtems_libi2c_bus_t *bus, uint8_t *in, int n)
+{
+  rtems_status_code   sc;
+  zynq_i2c_bus_entry *e  = (zynq_i2c_bus_entry *)bus;
+  const uint8_t addr = 0;               /* @todo - REVISIT */
+  uint8_t reg;                          /* @todo - REVISIT */
+
+  if (XIicPs_BusIsBusy(&e->instance)) {
+    return DEVICE_BUSY;
+  }
+
+  /* Set the IIC Repeated Start option */
+  sc = XIicPs_SetOptions(&e->instance, XIICPS_REP_START_OPTION);
+  if (sc != XST_SUCCESS) {
+    return XST_FAILURE;
+  }
+
+  /* Send the buffer using the I2C and check for errors */
+  sc = XIicPs_MasterSendPolled(&e->instance, &reg, 1, addr);
+  if (sc != XST_SUCCESS) {
+    PRINTK("XIicPs_MasterSendPolled failed\n");
+    return XST_FAILURE;
+  }
+
+  /* Receive the data */
+  sc = XIicPs_MasterRecvPolled(&e->instance, in, n, addr);
+  if (sc != XST_SUCCESS) {
+    PRINTK("XIicPs_MasterRecvPolled failed\n");
+    return XST_FAILURE;
+  }
+
+  /* Clear the I2C Repeated Start option */
+  sc = XIicPs_ClearOptions(&e->instance, XIICPS_REP_START_OPTION);
+  if (sc != XST_SUCCESS) {
+    return XST_FAILURE;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static int zynq_i2c_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg)
+{
+  int                 rv = -1;
+  zynq_i2c_bus_entry *e  = (zynq_i2c_bus_entry *)bus;
+
+  switch (cmd) {
+    case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
+      rv = XIicPs_SetOptions(&e->instance, (unsigned)arg);
+      break;
+    //case RTEMS_LIBI2C_IOCTL_GET_TFRMODE:
+    //  *(unsigned*)arg = XIicPs_GetOptions(&e->instance);
+    //  break;
+    default:
+      rv = -RTEMS_NOT_DEFINED;
+      break;
+  }
+
+  return rv;
+}
+
+const rtems_libi2c_bus_ops_t zynq_i2c_ops = {
+  .init        = zynq_i2c_init,
+  .send_start  = NULL, //zynq_i2c_send_start,
+  .send_stop   = NULL, //zynq_i2c_send_stop,
+  .send_addr   = NULL, //zynq_i2c_send_addr,
+  .read_bytes  = zynq_i2c_read,
+  .write_bytes = zynq_i2c_write,
+  .ioctl       = zynq_i2c_ioctl
+};
diff --git a/c/src/lib/libbsp/arm/zynq/misc/idle-thread.c b/c/src/lib/libbsp/arm/zynq/misc/idle-thread.c
new file mode 100644
index 0000000..bd71d5c
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/misc/idle-thread.c
@@ -0,0 +1,34 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief bsp_idle_thread() implementation.
+ */
+
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+
+#include <libcpu/arm-cp15.h>
+
+void *bsp_idle_thread(uintptr_t arg)
+{
+  while (true) {
+    arm_cp15_wait_for_interrupt();
+  }
+
+  return NULL;
+}
diff --git a/c/src/lib/libbsp/arm/zynq/misc/mmu.c b/c/src/lib/libbsp/arm/zynq/misc/mmu.c
new file mode 100644
index 0000000..a81a259
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/misc/mmu.c
@@ -0,0 +1,88 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief MMU support implementation.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <bsp/mmu.h>
+#include <bsp/xil_mmu.h>
+
+
+uint32_t zynq_disable_mmu(void)
+{
+  uint32_t ctrl = arm_cp15_get_control() & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M);
+
+  Xil_DisableMMU();
+
+  return ctrl;
+}
+
+void zynq_enable_mmu(void)
+{
+  Xil_EnableMMU();
+}
+
+uint32_t zynq_set_translation_table_block(const void *begin,
+                                          const void *end,
+                                          uint32_t    section_flags)
+{
+  uint32_t *ttb = arm_cp15_get_translation_table_base();
+  uint32_t i    = ARM_MMU_SECT_GET_INDEX(begin);
+  uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end));
+  uint32_t section_flags_of_first_entry = ttb [i];
+
+  while (i < iend) {
+    Xil_SetTlbAttributes(i << ARM_MMU_SECT_BASE_SHIFT, section_flags);
+    ++i;
+  }
+
+  return section_flags_of_first_entry;
+}
+
+uint32_t zynq_set_translation_table_entries(const void *begin,
+                                            const void *end,
+                                            uint32_t    section_flags)
+{
+  rtems_interrupt_level level;
+  uint32_t ctrl;
+  uint32_t section_flags_of_first_entry = 0;
+
+  rtems_interrupt_disable(level);
+  ctrl = zynq_disable_mmu();
+
+  section_flags_of_first_entry =
+    zynq_set_translation_table_entries(begin, end, section_flags);
+
+  if (ctrl) {
+    zynq_enable_mmu();
+  }
+  rtems_interrupt_enable(level);
+
+  return section_flags_of_first_entry;
+}
diff --git a/c/src/lib/libbsp/arm/zynq/misc/restart.c b/c/src/lib/libbsp/arm/zynq/misc/restart.c
new file mode 100644
index 0000000..669a8bf
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/misc/restart.c
@@ -0,0 +1,32 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Restart implementation.
+ */
+
+/*
+ * Copyright (c) 2010, 2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <libcpu/arm-cp15.h>
+
+#include <bsp.h>
+
+void bsp_restart(void *addr)
+{
+  ZYNQ_DO_RESTART(addr);
+}
diff --git a/c/src/lib/libbsp/arm/zynq/misc/timer.c b/c/src/lib/libbsp/arm/zynq/misc/timer.c
new file mode 100644
index 0000000..d91e8db
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/misc/timer.c
@@ -0,0 +1,43 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Benchmark timer support.
+ */
+
+/*
+ * Copyright (c) 2008, 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <rtems/btimer.h>
+#include <rtems/timerdrv.h>
+
+#include <bsp.h>
+
+static uint32_t benchmark_timer_base;
+
+void benchmark_timer_initialize(void)
+{
+  benchmark_timer_base = zynq_timer();
+}
+
+uint32_t benchmark_timer_read(void)
+{
+  return zynq_timer() - benchmark_timer_base;
+}
+
+void benchmark_timer_disable_subtracting_average_overhead(bool find_average_overhead)
+{
+  /* VOID */
+}
diff --git a/c/src/lib/libbsp/arm/zynq/network/ethEmacPs.c b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs.c
new file mode 100644
index 0000000..55cdab2
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs.c
@@ -0,0 +1,411 @@
+/**
+ * @file
+ *
+ * @ingroup eth_emacps
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam at sics.se>
+ *
+ */
+
+/*
+ * Copyright (c) 2010 Xilinx, Inc.  All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <xparameters.h>
+#include <xemacps.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_mii_ioctl.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/utility.h>
+#include <bsp/ethernet.h>
+
+
+// RiC: This is not used, but save it so it can be resurrected
+//#if LWIP_IGMP
+//static uint8_t eth_emacps_mcast_entry_mask = 0;
+//
+//
+//static int eth_emacps_mac_filter_update (struct netif   *netif,
+//                                         struct ip_addr *group,
+//                                         uint8_t         action)
+//{
+//  return 0;
+//}
+//#endif
+
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the mbuf that is passed to the function. This mbuf
+ * might be chained.
+ *
+ */
+static rtems_status_code low_level_output(EthEmacPs *emacPs, struct mbuf *m)
+{
+  /* TX space is available as long as there are valid BDs */
+  XEmacPs_BdRing   *txRing = &(XEmacPs_GetTxRing(&emacPs->instance));
+  int               cnt    = XEmacPs_BdRingGetFreeCnt(txRing);
+  rtems_status_code sc;
+
+  PRINTK("%-40s: beg, cnt = %08x\n", __func__, cnt);
+
+  /* Check if space is available to send */
+  if (cnt > 0) {
+    sc = eth_emacps_sgsend(emacPs, m);
+    if ((sc == RTEMS_SUCCESSFUL) || (sc == RTEMS_NO_MEMORY)) {
+      sc = RTEMS_SUCCESSFUL;
+    } else {
+      ++emacPs->stats.tx_drop;
+      PRINTK("%-40s: sc = %08x, drop = %08x\n", __func__,
+             sc, emacPs->stats.tx_drop);
+      m_freem(m);
+    }
+  } else {
+    ++emacPs->stats.tx_full_queues;
+    sc = RTEMS_UNSATISFIED;
+  }
+
+  PRINTK("%-40s: end, cnt = %08x\n", __func__, cnt);
+  return sc;
+}
+
+
+/*
+ * eth_emacps_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+rtems_status_code eth_emacps_output(EthEmacPs   *emacPs,
+                                    struct mbuf *m)
+{
+  rtems_status_code     sc;
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_disable(level);
+
+  /* Resolve hardware address, then send (or queue) packet */
+  sc = low_level_output(emacPs, m);
+
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end, sc = %08x\n", __func__, sc);
+  return sc;
+}
+
+
+/*
+ * low_level_input():
+ *
+ * Should allocate an mbuf and transfer the bytes of the incoming
+ * packet from the interface into the mbuf.
+ *
+ * Returns the number of packets read
+ *
+ */
+static int low_level_input(EthEmacPs *emacPs, XEmacPs_BdRing *rxRing)
+{
+  unsigned              k;
+  XEmacPs_Bd           *rxBdSet;
+  XEmacPs_Bd           *curBd;
+  struct ifnet *const   ifp   = &emacPs->arpcom.ac_if;
+  struct mbuf         **mbufs = emacPs->rxMbufTable;
+  unsigned              nBds  = XEmacPs_BdRingFromHwRx(rxRing,
+                                                       emacPs->rxUnitCount,
+                                                       &rxBdSet);
+
+  PRINTK("%-40s: beg, numBds = %08x\n", __func__, nBds);
+
+  /* See if there is data to process */
+  for (k = 0, curBd = rxBdSet; k < nBds; k++) {
+    unsigned             bdIdx = XEMACPS_BD_TO_INDEX(rxRing, curBd);
+    struct mbuf         *m     = mbufs[bdIdx];
+    struct ether_header *eh    = mtod(m, struct ether_header*);
+    int                  sz    = XEmacPs_BdGetLength(curBd);
+
+    PRINTK("%-40s: bdIdx = %08x, mBuf = %08x, m_data = %08x, sz = %08x\n", __func__,
+           bdIdx, (uint)m, (uint)m->m_data, sz);
+
+    /* Update mbuf */
+    m->m_len        = sz              - ETHER_HDR_LEN;
+    m->m_pkthdr.len = sz              - ETHER_HDR_LEN;
+    m->m_data       = mtod(m, char *) + ETHER_HDR_LEN;
+
+    PRINTK("%-40s: %02u: %u\n", __func__, bdIdx, sz);
+
+    PRINTK("%-40s: status = %08x, hdr = %08x, hlen = %04x, data = %08x, dlen = %04x\n", __func__,
+           XEmacPs_BdGetStatus(curBd), eh, ETHER_HDR_LEN, m->m_data, m->m_len);
+
+    DUMP4("mb:", __func__, false, m, sizeof(*m));
+    DUMP2("bd:", __func__, true,  eh, sz);
+
+    ++emacPs->stats.rx_recv;
+
+    /* Hand it over */
+    ether_input(ifp, eh, m);
+
+    /* Next one */
+    curBd = XEmacPs_BdRingNext(rxRing, curBd);
+  }
+
+  /* Free up the BD's */
+  if (nBds) {
+    XEmacPs_BdRingFree(rxRing, nBds, rxBdSet);
+  }
+  dsb();
+
+  PRINTK("%-40s: end, %u\n", __func__, nBds);
+  return nBds;
+}
+
+
+/*
+ * eth_emacps_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface. It uses the function low_level_input() that
+ * should handle the actual reception of bytes from the network
+ * interface.
+ *
+ * Returns the number of packets read
+ *
+ */
+int eth_emacps_input(EthEmacPs *emacPs, XEmacPs_BdRing *rxRing)
+{
+  unsigned              n;
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Move received packet into a new mbuf */
+  rtems_interrupt_disable(level);
+  n = low_level_input(emacPs, rxRing);
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end, %u\n", __func__, n);
+  return n;
+}
+
+
+void eth_emacps_low_level_init(void *arg)
+{
+  EthEmacPs    *emacPs = (EthEmacPs *)arg;
+  struct ifnet *ifp    = &emacPs->arpcom.ac_if;
+  int           xs;
+
+  /* Initialize instance */
+  XEmacPs_Config* cfg = XEmacPs_LookupConfig(ifp->if_unit);
+  if (cfg == NULL) {
+    printk("%-40s: EmacPs configuration for device ID %d not found\n",
+           __func__, ifp->if_unit);
+    rtems_fatal_error_occurred(0xdead0000);
+  }
+
+  xs = XEmacPs_CfgInitialize(&emacPs->instance, cfg, cfg->BaseAddress);
+  if (xs != 0) {
+    printk("%-40s: EmacPs CfgInitialize for device ID %d failed with status %d\n",
+           __func__, ifp->if_unit, xs);
+    rtems_fatal_error_occurred(0xdead0001);
+  }
+
+  /* Initialize the MAC */
+  xs = eth_emacps_init_mac(emacPs);
+  if (xs != 0) {
+    printk("%-40s: EmacPs initialization for device ID %d failed with status %d\n",
+           __func__, ifp->if_unit, xs);
+    rtems_fatal_error_occurred(0xdead0002);
+  }
+
+  /* Setup burst length */
+  XEmacPs_DMABLengthUpdate(&emacPs->instance, XEMACPS_16BYTE_BURST);
+
+  /* Set up ISR */
+  xs = eth_emacps_setup_isr(emacPs);
+  if (xs != 0) {
+    printk("%-40s: Setting up callbacks for device ID %d failed with status %d\n",
+           __func__, ifp->if_unit, xs);
+    rtems_fatal_error_occurred(0xdead0003);
+  }
+
+  /* Initialize DMA */
+  xs = eth_emacps_init_dma(emacPs);
+  if (xs != 0) {
+    printk("%-40s: Initializing DMAs for device ID %d failed with status %d\n",
+           __func__, ifp->if_unit, xs);
+    rtems_fatal_error_occurred(0xdead0004);
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+void eth_emacps_handle_error(EthEmacPs *emacPs)
+{
+  rtems_status_code sc;
+
+  sc = rtems_bsdnet_event_send(gEthEmacPsErTask, ETH_EMACPS_EVENT_INTERRUPT);
+  assert(sc == RTEMS_SUCCESSFUL);
+}
+
+
+void eth_emacps_error_task(void *arg)
+{
+  rtems_status_code  sc     = RTEMS_SUCCESSFUL;
+  rtems_event_set    events = 0;
+  EthEmacPs         *emacPs = (EthEmacPs *) arg;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Main event loop */
+  for (;;) {
+    int                   xs = 0;
+    rtems_interrupt_level level;
+
+    PRINTK("%-40s: Waiting...\n", __func__);
+    /* Wait for events */
+    sc = rtems_bsdnet_event_receive( ETH_EMACPS_EVENT_INTERRUPT,
+                                     RTEMS_EVENT_ANY | RTEMS_WAIT,
+                                     RTEMS_NO_TIMEOUT,
+                                     &events );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    PRINTK("%-40s: WAKE up: 0x%08" PRIx32 "\n", __func__, events);
+
+    rtems_interrupt_disable(level);
+
+    eth_emacps_free_tx_rx_mbufs(emacPs);
+
+    xs = XEmacPs_CfgInitialize(&emacPs->instance, &emacPs->instance.Config,
+                                   emacPs->instance.Config.BaseAddress);
+    if (xs != 0) {
+      printk("%-40s: EmacPs Configuration failed with status %d\n", __func__, xs);
+    }
+
+    /* Initialize the mac */
+    eth_emacps_init_on_error(emacPs);
+
+    /* Setup burst length */
+    XEmacPs_DMABLengthUpdate(&emacPs->instance, XEMACPS_16BYTE_BURST);
+
+    eth_emacps_setup_isr(emacPs);
+    eth_emacps_init_dma(emacPs);
+    eth_emacps_start(emacPs);
+
+    rtems_interrupt_enable(level);
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+void eth_emacps_handle_tx_errors(EthEmacPs* emacPs)
+{
+  unsigned baseAdx = emacPs->instance.Config.BaseAddress;
+  uint32_t netCtrlReg;
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_level level;
+  rtems_interrupt_disable(level);
+
+  /* Disable transmitter */
+  netCtrlReg  = XEmacPs_ReadReg(baseAdx, XEMACPS_NWCTRL_OFFSET);
+  netCtrlReg &= ~XEMACPS_NWCTRL_TXEN_MASK;
+  XEmacPs_WriteReg(baseAdx, XEMACPS_NWCTRL_OFFSET, netCtrlReg);
+
+  eth_emacps_free_only_tx_mbufs(emacPs);
+
+  eth_emacps_setup_tx_dscs(emacPs, &XEmacPs_GetTxRing(&emacPs->instance));
+
+  /* Enable transmitter */
+  netCtrlReg  = XEmacPs_ReadReg(baseAdx, XEMACPS_NWCTRL_OFFSET);
+  netCtrlReg |= XEMACPS_NWCTRL_TXEN_MASK;
+  XEmacPs_WriteReg(baseAdx, XEMACPS_NWCTRL_OFFSET, netCtrlReg);
+
+  rtems_interrupt_enable(level);
+  PRINTK("%-40s: end\n", __func__);
+}
diff --git a/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_dma.c b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_dma.c
new file mode 100644
index 0000000..ea8fb42
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_dma.c
@@ -0,0 +1,649 @@
+/**
+ * @file
+ *
+ * @ingroup eth_emacps
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010 Xilinx, Inc.  All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <assert.h>
+
+#include <bsp/ethernet.h>
+#include <bsp/xstatus.h>
+
+#include <bsp/xil_mmu.h>
+#include <bsp/xil_exception.h>
+
+#include <bsp/xemacps_bd.h>
+
+/* Byte alignment of BDs */
+#define BD_ALIGNMENT XEMACPS_DMABD_MINIMUM_ALIGNMENT
+
+
+static void eth_emacps_update_tx_stats(EthEmacPs  *emacPs,
+                                       XEmacPs_Bd *bd)
+{
+  uint32_t s = XEmacPs_BdGetStatus(bd);
+
+  /* Update error counters */
+  if (s & EMACPS_ETH_TX_STAT_MASK) {
+    if (s & EMACPS_ETH_TX_RETRIES) {
+      ++emacPs->stats.tx_stat_retries;
+    }
+    if (s & EMACPS_ETH_TX_AHB_ERROR) {
+      ++emacPs->stats.tx_stat_ahb_errors;
+    }
+    if (s & EMACPS_ETH_TX_LATE_COLLISION) {
+      ++emacPs->stats.tx_stat_late_collisions;
+    }
+    switch (s & EMACPS_ETH_TX_CKSUM_ERROR) {
+      case EMACPS_ETH_TX_NO_ERROR:
+        ++emacPs->stats.tx_stat_no_errors;
+        break;
+      case EMACPS_ETH_TX_VLAN_ERROR:
+        ++emacPs->stats.tx_stat_vlan_errors;
+        break;
+      case EMACPS_ETH_TX_SNAP_ERROR:
+        ++emacPs->stats.tx_stat_snap_errors;
+        break;
+      case EMACPS_ETH_TX_IP_ERROR:
+        ++emacPs->stats.tx_stat_ip_errors;
+        break;
+      case EMACPS_ETH_TX_ID_ERROR:
+        ++emacPs->stats.tx_stat_id_errors;
+        break;
+      case EMACPS_ETH_TX_BADFRAG_ERROR:
+        ++emacPs->stats.tx_stat_badfrag_errors;
+        break;
+      case EMACPS_ETH_TX_TCPUDP_ERROR:
+        ++emacPs->stats.tx_stat_tcpudp_errors;
+        break;
+      case EMACPS_ETH_TX_EOP_ERROR:
+        ++emacPs->stats.tx_stat_eop_errors;
+        break;
+    }
+  }
+}
+
+#ifdef RECORD
+extern struct {
+  struct mbuf *alloc;
+  unsigned     ctrl;
+  struct mbuf *free;
+  unsigned     status;
+}        mbufList[64];
+extern unsigned mbufIdx;
+extern unsigned mbufFreeIdx;
+#endif
+
+void eth_emacps_process_txd_bds(EthEmacPs      *emacPs,
+                                XEmacPs_BdRing *txRing)
+{
+  unsigned      k;
+  XEmacPs_Bd   *txBdSet;
+  XEmacPs_Bd   *curBd;
+  struct mbuf **mbufs = emacPs->txMbufTable;
+  unsigned      nBds  = XEmacPs_BdRingFromHwTx(txRing,
+                                               emacPs->txUnitCount,
+                                               &txBdSet);
+
+  PRINTK("%-40s: beg, numBds = %08x\n", __func__, nBds);
+
+  /* txBdSet is located in non-cached memory, so no need to call invalidate */
+
+  /* Free the processed BD's */
+  for (k = 0, curBd = txBdSet; k < nBds; ++k) {
+    unsigned     bdIdx  = XEMACPS_BD_TO_INDEX(txRing, curBd);
+    struct mbuf *m      = mbufs[bdIdx];
+    unsigned     status = XEMACPS_TXBUF_USED_MASK;
+
+    /* Update statistics counters */
+    eth_emacps_update_tx_stats(emacPs, curBd);
+
+#ifdef RECORD
+    mbufList[mbufFreeIdx   & 0x3ff].free   = m;
+    mbufList[mbufFreeIdx++ & 0x3ff].status = ((unsigned*)curBd)[1] | (mbufIdx << 16);
+#endif
+
+    /* Release mbuf */
+    PRINTK("%-40s: bdIdx = %08x, mbufs = %08x, mbuf = %08x, m_data = %08x\n", __func__,
+           bdIdx, (uint)mbufs, (uint)m, (uint)m->m_data);
+    if (m != NULL) {
+      m_free(m);
+    }
+    mbufs[bdIdx] = NULL;
+
+    /* Reset the BD - these are in uncached memory */
+    if (bdIdx == (emacPs->txUnitCount - 1)) {
+      status |= XEMACPS_TXBUF_WRAP_MASK;
+    }
+    ((unsigned*)curBd)[0] = 0xabadbabe; /* Avoid overwriting previous buffer */
+    ((unsigned*)curBd)[1] = status;     /* Set USED on ALL BDs of a frame */
+
+    /* Next one */
+    curBd = XEmacPs_BdRingNext(txRing, curBd);
+    dsb();
+  }
+
+  if (nBds) {
+    int xs = XEmacPs_BdRingFree(txRing, nBds, txBdSet);
+    if (xs != 0) {
+      printk("%-40s: Error %d from BdRingFree\n", __func__, xs);
+    }
+  }
+
+  PRINTK("%-40s: end, cnt = %08x\n", __func__, nBds);
+}
+
+
+/*!
+ * send_handler():
+ *
+ * @brief Handler called from the ISR at packet transmission DMA completion
+ */
+void eth_emacps_send_handler(void *arg)
+{
+  rtems_status_code sc;
+  EthEmacPs        *emacPs  = (EthEmacPs *)arg;
+  unsigned          baseAdx = emacPs->instance.Config.BaseAddress;
+  unsigned          reg     = XEmacPs_ReadReg(baseAdx, XEMACPS_TXSR_OFFSET);
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Clear the tx_status register by setting tx_complete */
+  XEmacPs_WriteReg(baseAdx, XEMACPS_TXSR_OFFSET, reg);
+
+  ++emacPs->stats.tx_interrupts;        /* Count TX DMA completions */
+
+  /* Wake up the Transmit task to process the sent BDs */
+  sc = rtems_bsdnet_event_send(gEthEmacPsTxTask, ETH_EMACPS_EVENT_INTERRUPT);
+  assert(sc == RTEMS_SUCCESSFUL);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+/*!
+ * sgsend():
+ *
+ * @brief Scatter/gather send of a frame, potentially composed of multiple
+ *        fragments.
+ *
+ * This function should be called only with interrupts disabled.
+ */
+rtems_status_code eth_emacps_sgsend(EthEmacPs *emacPs, struct mbuf *m)
+{
+  int             xs;
+  uint32_t        ctrl;
+  unsigned        bdIdx;
+  XEmacPs_Bd     *curBd, *prvBd;
+  XEmacPs_Bd     *txBdSet;
+  XEmacPs_BdRing *txRing = &(XEmacPs_GetTxRing(&emacPs->instance));
+  struct mbuf   **mbufs  = emacPs->txMbufTable;
+  struct mbuf    *n;
+  int             n_mbufs;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* First count the number of mbufs */
+  for (n = m, n_mbufs = 0; n != NULL; n = n->m_next)
+    n_mbufs++;
+
+  PRINTK("%-40s: n_mbufs = %08x\n", __func__, n_mbufs);
+
+  /* Obtain as many BD's */
+  xs = XEmacPs_BdRingAlloc(txRing, n_mbufs, &txBdSet);
+  if (xs != 0) {
+    printk("%-40s: Error %d allocating TxBD\n", __func__, xs);
+    return RTEMS_NO_MEMORY;
+  }
+
+  for(n = m, curBd = txBdSet; n != NULL; n = n->m_next) {
+    /* Send the data from the mbuf to the interface, one mbuf at a time.
+       The size of the data in each mbuf is kept in the ->m_len variable. */
+    rtems_cache_flush_multiple_data_lines(mtod(n, const void *),
+                                          (size_t) n->m_len);
+
+    bdIdx = XEMACPS_BD_TO_INDEX(txRing, curBd);
+    if (mbufs[bdIdx] != NULL) {
+      printk("%-40s: mbuf not available for index %d\n", __func__, bdIdx);
+      return RTEMS_RESOURCE_IN_USE;
+    }
+    mbufs[bdIdx] = n;
+
+    ctrl = XEMACPS_TXBUF_USED_MASK; /* s/w must continue to own the fragment until we're ready to transmit */
+    if (n->m_len > (XEMACPS_MAX_FRAME_SIZE - 18)) /* What is 18? */
+      ctrl |= (XEMACPS_MAX_FRAME_SIZE - 18) & XEMACPS_TXBUF_LEN_MASK;
+    else
+      ctrl |= n->m_len & XEMACPS_TXBUF_LEN_MASK;
+    if (bdIdx == (emacPs->txUnitCount - 1)) {
+      ctrl |= XEMACPS_TXBUF_WRAP_MASK;
+    }
+    if (n->m_next == NULL) {
+      ctrl |= XEMACPS_TXBUF_LAST_MASK;
+    }
+
+    XEmacPs_BdSetAddressTx(curBd, mtod(n, unsigned));
+    /*XEmacPs_BdSetStatus(curBd, ctrl);*/ /* Only ORs */
+    XEmacPs_BdWrite(curBd, XEMACPS_BD_STAT_OFFSET, ctrl);
+    dsb();
+
+    PRINTK("%-40s: %02" PRIu32 ": %u %s\n", __func__,
+           bdIdx, n->m_len, (n->m_next == NULL) ? "L" : "");
+
+    DUMP4("mb:", __func__, false, n, sizeof(*n));
+    DUMP2("md:", __func__, true,  n->m_data, n->m_len);
+
+    prvBd = curBd;
+    curBd = XEmacPs_BdRingNext(txRing, curBd);
+  }
+
+  /* Quickly hand ownership of all fragments in the frame to h/w.
+     Do this in reverse order to prevent the DMA engine from advancing
+     to the next fragment before s/w gets a chance to hand over ownership */
+  for(n = m, curBd = prvBd; n != NULL; n = n->m_next) {
+    XEmacPs_BdClearTxUsed(curBd);
+
+    curBd = XEmacPs_BdRingPrev(txRing, curBd);
+  }
+  dsb();
+
+  /* Flush the set of BDs to hardware */
+  xs = XEmacPs_BdRingToHw(txRing, n_mbufs, txBdSet);
+  if (xs != 0) {
+    printk("%-40s: Error %d submitting TxBD to hardware\n", __func__, xs);
+    return RTEMS_IO_ERROR;
+  }
+  dsb();
+
+  /* Start transmit - no harm to "start" it again if it is still running */
+  XEmacPs_Transmit( (&emacPs->instance) );
+  dsb();
+
+  /* Increment transmitted frames counter */
+  ++emacPs->stats.txd_frames;
+  PRINTK("%-40s: txd_frames = %08x\n", __func__, emacPs->stats.txd_frames);
+
+  PRINTK("%-40s: end, status = %d\n", __func__, xs);
+  return RTEMS_SUCCESSFUL;
+}
+
+
+static void eth_emacps_update_rx_stats(EthEmacPs  *emacPs,
+                                       XEmacPs_Bd *bd)
+{
+  uint32_t s = XEmacPs_BdGetStatus(bd);
+
+  /* Update error counters */
+  if (s & EMACPS_ETH_RX_STAT_MASK) {
+    if (s & EMACPS_ETH_RX_BCAST) {
+      ++emacPs->stats.rx_stat_bcast;
+    }
+    if (s & EMACPS_ETH_RX_MCAST) {
+      ++emacPs->stats.rx_stat_mcast;
+    }
+    if (s & EMACPS_ETH_RX_UCAST) {
+      ++emacPs->stats.rx_stat_ucast;
+    }
+    switch (s & EMACPS_ETH_RX_EXTERNAL) {
+      case EMACPS_ETH_RX_ADX1:
+        ++emacPs->stats.rx_stat_adx1;
+        break;
+      case EMACPS_ETH_RX_ADX2:
+        ++emacPs->stats.rx_stat_adx2;
+        break;
+      case EMACPS_ETH_RX_ADX3:
+        ++emacPs->stats.rx_stat_adx3;
+        break;
+      case EMACPS_ETH_RX_ADX4:
+        ++emacPs->stats.rx_stat_adx4;
+        break;
+    }
+    if (s & EMACPS_ETH_RX_BIT_24) {
+      ++emacPs->stats.rx_stat_bit_24;
+    }
+    switch (s & EMACPS_ETH_RX_BIT_22_23) {
+      case EMACPS_ETH_RX_REG1:
+        ++emacPs->stats.rx_stat_reg1;
+        break;
+      case EMACPS_ETH_RX_REG2:
+        ++emacPs->stats.rx_stat_reg2;
+        break;
+      case EMACPS_ETH_RX_REG3:
+        ++emacPs->stats.rx_stat_reg3;
+        break;
+      case EMACPS_ETH_RX_REG4:
+        ++emacPs->stats.rx_stat_reg4;
+        break;
+    }
+    if (s & EMACPS_ETH_RX_VLAN) {
+      ++emacPs->stats.rx_stat_vlan;
+    }
+    if (s & EMACPS_ETH_RX_PRIORITY) {
+      ++emacPs->stats.rx_stat_priority;
+    }
+    if (s & EMACPS_ETH_RX_CFI) {
+      ++emacPs->stats.rx_stat_cfi;
+    }
+    if (s & EMACPS_ETH_RX_EOF) {
+      ++emacPs->stats.rx_stat_eof;
+    }
+    if (s & EMACPS_ETH_RX_SOF) {
+      ++emacPs->stats.rx_stat_sof;
+    }
+    if (s & EMACPS_ETH_RX_FCS) {
+      ++emacPs->stats.rx_stat_fcs;
+    }
+  }
+}
+
+
+void eth_emacps_process_rxd_bds(EthEmacPs      *emacPs,
+                                XEmacPs_BdRing *rxRing,
+                                int             wait)
+{
+  struct mbuf **mbufs   = emacPs->rxMbufTable;
+  unsigned      freeBds = XEmacPs_BdRingGetFreeCnt(rxRing);
+  unsigned      k;
+
+  PRINTK("%-40s: beg, nBDs = %08x\n", __func__, freeBds);
+
+  for (k = 0; k < freeBds; k++) {
+    int          xs;
+    struct mbuf *m;
+    XEmacPs_Bd  *curBd;
+    unsigned     bdIdx;
+
+    /* Allocate BDs one at a time instead of all at once to improve odds */
+    xs = XEmacPs_BdRingAlloc(rxRing, 1, &curBd);
+    if (xs != 0) {
+      printk("%-40s: Error %d allocating RxBD\n", __func__, xs);
+      break;
+    }
+
+    /* curBd is located in non-cached memory, so no need to cache invalidate */
+
+    /* Update statistics counters from curBd's previous use */
+    eth_emacps_update_rx_stats(emacPs, curBd);
+
+    /* Associate an mbuf with the BD */
+    m = eth_emacps_add_new_mbuf(emacPs, mbufs, wait);
+    if (m == NULL) {
+      ++emacPs->stats.rx_memErr;
+      ++emacPs->stats.rx_drop;
+      printk("%-40s: Unable to allocate mbuf\n", __func__);
+      XEmacPs_BdRingUnAlloc(rxRing, 1, curBd);
+      dsb();
+      break;
+    }
+
+    bdIdx = XEMACPS_BD_TO_INDEX(rxRing, curBd);
+
+    /* Add mbuf to ring; The lower two bits of m->m_data must be shaved off
+       since DMA uses them for ownership and wrap!  Use  bits 14 and 15 of
+       the Network Configuration register to set up finer alignment.  This
+       is done in eth_emacps_setup_rx_dscs(). */
+    XEmacPs_BdSetAddressRx(curBd, mtod(m, uint32_t) & ~0x3);
+
+    /* Clear ownership and, if necessary, set wrap bit */
+    XEmacPs_BdClearRxNew(curBd);
+    if (bdIdx == (emacPs->rxUnitCount - 1)) {
+      XEmacPs_BdSetRxWrap(curBd);
+    }
+    dsb();
+
+    /* Enqueue to HW, flushing descriptor from cache */
+    xs = XEmacPs_BdRingToHw(rxRing, 1, curBd);
+    if (xs != 0) {
+      printk("%-40s: Error %d committing RxBD to hardware: \n", __func__, xs);
+      if (xs == XST_DMA_SG_LIST_ERROR)
+        printk("  XST_DMA_SG_LIST_ERROR: This function was called out of \n"
+               "  sequence with XEmacPs_BdRingAlloc()\n");
+      else
+        printk("  Set of BDs was rejected because: \n"
+               "  - the first BD did not have its start-of-packet bit set, or\n"
+               "  - the last  BD did not have its end-of-packet   bit set, or\n"
+               "  - any one of the BD set has 0 as length value\n");
+      m_free(m);
+      return;
+    }
+
+    /* Add mbuf to table */
+    mbufs[bdIdx] = m;
+    PRINTK("%-40s: bdIdx = %08x, mBuf = %08x, md = %08x\n", __func__,
+           bdIdx, (uint)m, (uint)m->m_data);
+  }
+
+  PRINTK("%-40s: end, cnt = %08x\n", __func__, k);
+}
+
+
+/*
+ * recv_handler():
+ *
+ * @brief Handler called from the ISR to wake up the receive task.
+ */
+void eth_emacps_recv_handler(void *arg)
+{
+  rtems_status_code sc;
+  EthEmacPs        *emacPs  = (EthEmacPs *)arg;
+  unsigned          baseAdx = emacPs->instance.Config.BaseAddress;
+  unsigned          reg     = XEmacPs_ReadReg(baseAdx, XEMACPS_RXSR_OFFSET);
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Clear the rx_status register by setting frame_recd */
+  XEmacPs_WriteReg(baseAdx, XEMACPS_RXSR_OFFSET, reg);
+
+  ++emacPs->stats.rx_interrupts;
+  PRINTK("%-40s: rx_interrupts = %lu\n", __func__, emacPs->stats.rx_interrupts);
+
+  /* If Reception-Done interrupt is asserted, wake the receive task */
+  sc = rtems_bsdnet_event_send(gEthEmacPsRxTask, ETH_EMACPS_EVENT_INTERRUPT);
+  assert(sc == RTEMS_SUCCESSFUL);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+int eth_emacps_setup_rx_dscs(EthEmacPs *emacPs, XEmacPs_BdRing *rxRing)
+{
+  int        xs;
+  XEmacPs_Bd bdTemplate;
+  unsigned   netCfg;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Setup a BD template for the Rx channel */
+  XEmacPs_BdClear(&bdTemplate);
+
+  /* Create the RxBD ring */
+  xs = XEmacPs_BdRingCreate(rxRing,
+                            (uint32_t)emacPs->rxBdSpace,
+                            (uint32_t)emacPs->rxBdSpace,
+                            BD_ALIGNMENT,
+                            emacPs->rxUnitCount);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up RxBD space, BdRingCreate", __func__, xs);
+    return xs;
+  }
+
+  /*
+   * The template will be copied to every RxBD.
+   * We will not have to explicitly set these again.
+   */
+  xs = XEmacPs_BdRingClone(rxRing, &bdTemplate, XEMACPS_RECV);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up RxBD space, BdRingClone", __func__, xs);
+    return xs;
+  }
+
+  /* Offset buffer alignment by 16 bits to give 32 bit alignment of struct ip */
+  netCfg = XEmacPs_ReadReg(emacPs->instance.Config.BaseAddress,
+                           XEMACPS_NWCFG_OFFSET);
+  netCfg |= (ETH_EMACPS_RX_DATA_OFFSET & 0x3) << 14;
+  XEmacPs_WriteReg(emacPs->instance.Config.BaseAddress,
+                   XEMACPS_NWCFG_OFFSET, netCfg);
+
+  PRINTK("%-40s: end, rxUnitCount = %08x\n", __func__, emacPs->rxUnitCount);
+  return xs;
+}
+
+int eth_emacps_setup_tx_dscs(EthEmacPs *emacPs, XEmacPs_BdRing *txRing)
+{
+  int             xs;
+  XEmacPs_Bd      bdTemplate;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Setup a BD template for the Tx channel */
+  XEmacPs_BdClear(&bdTemplate);
+  XEmacPs_BdSetStatus(&bdTemplate, XEMACPS_TXBUF_USED_MASK);
+
+  /* Create the TxBD ring */
+  xs = XEmacPs_BdRingCreate(txRing,
+                            (uint32_t)emacPs->txBdSpace,
+                            (uint32_t)emacPs->txBdSpace,
+                            BD_ALIGNMENT,
+                            emacPs->txUnitCount);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up TxBD space, BdRingCreate", __func__, xs);
+    return xs;
+  }
+
+  /* Copy the template into every TxBd */
+  xs = XEmacPs_BdRingClone(txRing, &bdTemplate, XEMACPS_SEND);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up TxBD space, BdRingClone", __func__, xs);
+    return xs;
+  }
+
+  PRINTK("%-40s: end, txUnitCount = %08x\n", __func__, emacPs->txUnitCount);
+  return xs;
+}
+
+
+int eth_emacps_init_dma(EthEmacPs* emacPs)
+{
+  XEmacPs_BdRing *rxRing;
+  XEmacPs_BdRing *txRing;
+  int             xs;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Allocate a 1 MB MMU page aligned to 1 MB boundary for the BDs. */
+  size_t    size      = 0x100000;
+  uintptr_t alignment = (uintptr_t)0x100000;
+  uintptr_t boundary  = (uintptr_t)0;
+  uint8_t*  bdSpace   = (uint8_t*)rtems_heap_allocate_aligned_with_boundary(size, alignment, boundary);
+
+  /* Make sure we got the space */
+  if (bdSpace == NULL) {
+    printk("-40s: BD space allocation failed\n", __func__);
+    return -1;
+  }
+
+  /*
+   * The BDs need to be allocated in uncached memory.  Hence the 1 MB address
+   * range just allocated is made uncached by setting appropriate attributes
+   * in the translation table.
+   */
+  Xil_SetTlbAttributes((int)bdSpace, 0xc02);
+
+  rxRing = &XEmacPs_GetRxRing(&emacPs->instance);
+  txRing = &XEmacPs_GetTxRing(&emacPs->instance);
+  PRINTK("%-40s: rxRing = 0x%08x\n", __func__, rxRing);
+  PRINTK("%-40s: txRing = 0x%08x\n", __func__, txRing);
+
+  /*
+   * We allocate 65536 bytes for both Rx and Tx BDs, which can each accomodate
+   * a max of 8192 BDs.  That is much more than any application will ever need.
+   * The rest of the 1 MB page is unused.
+   */
+  emacPs->rxBdSpace = (void *)bdSpace;
+  emacPs->txBdSpace = (void *)(bdSpace + 0x10000);
+
+  PRINTK("%-40s: rxBdSpace = 0x%08x\n", __func__, emacPs->rxBdSpace);
+  PRINTK("%-40s: txBdSpace = 0x%08x\n", __func__, emacPs->txBdSpace);
+
+  if (!emacPs->rxBdSpace || !emacPs->txBdSpace) {
+    printk("%-40s: %s@%d: Unable to allocate memory for TX/RX buffer descriptors",
+           __func__, __FILE__, __LINE__);
+    return XST_FAILURE;
+  }
+
+  /* Set up RX descriptors */
+  xs = eth_emacps_setup_rx_dscs(emacPs, rxRing);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up RX descriptors\n", __func__, xs);
+    return xs;
+  }
+
+  /* Set up TX descriptors */
+  xs = eth_emacps_setup_tx_dscs(emacPs, txRing);
+  if (xs != 0) {
+    printk("%-40s: Error %d setting up TX descriptors\n", __func__, xs);
+    return xs;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+
+  return 0;
+}
+
+
+void eth_emacps_free_tx_rx_mbufs(EthEmacPs* emacPs)
+{
+  int           i;
+  struct mbuf **mbufs = emacPs->rxMbufTable;
+
+  PRINTK("%-40s: beg\n", __func__);
+  eth_emacps_free_only_tx_mbufs(emacPs);
+
+  for (i = 0; i < emacPs->rxUnitCount; ++i) {
+    m_free(mbufs[i]);
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+void eth_emacps_free_only_tx_mbufs(EthEmacPs* emacPs)
+{
+  int           i;
+  struct mbuf **mbufs = emacPs->txMbufTable;
+
+  PRINTK("%-40s: beg\n", __func__);
+  for (i = 0; i < emacPs->txUnitCount; ++i) {
+    if (mbufs[i] != 0) {
+      m_free(mbufs[i]);
+      mbufs[i] = 0;
+    }
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
diff --git a/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_hw.c b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_hw.c
new file mode 100644
index 0000000..863fb25
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_hw.c
@@ -0,0 +1,269 @@
+/**
+ * @file
+ *
+ * @ingroup eth_emacps
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2010 Xilinx, Inc.  All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <assert.h>
+
+#include <bsp/ethernet.h>
+
+
+// RiC: This is not used, but save it so it can be resurrected
+//XEmacPs_Config *eth_emacps_lookup_config(unsigned mac_base)
+//{
+//  extern XEmacPs_Config  XEmacPs_ConfigTable[];
+//  XEmacPs_Config        *cfg = NULL;
+//  int i;
+//
+//  for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
+//    if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
+//      cfg = &XEmacPs_ConfigTable[i];
+//      break;
+//    }
+//  }
+//
+//  return cfg;
+//}
+
+
+int eth_emacps_init_mac(EthEmacPs* emacPs)
+{
+  XEmacPs *instance = &emacPs->instance;
+  int      xs;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  PRINTK("%-40s: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
+         ((char*)emacPs->arpcom.ac_enaddr)[0],
+         ((char*)emacPs->arpcom.ac_enaddr)[1],
+         ((char*)emacPs->arpcom.ac_enaddr)[2],
+         ((char*)emacPs->arpcom.ac_enaddr)[3],
+         ((char*)emacPs->arpcom.ac_enaddr)[4],
+         ((char*)emacPs->arpcom.ac_enaddr)[5]);
+
+  /* Set the MAC address */
+  xs = XEmacPs_SetMacAddress(instance, emacPs->arpcom.ac_enaddr, 1);
+  if (xs != 0) {
+    struct ifnet *ifp = &emacPs->arpcom.ac_if;
+    printk("%-40s: Setting MAC address for device ID %d failed with status %d\n",
+           __func__, ifp->if_unit, xs);
+    return xs;
+  }
+
+  /* Set up the hardware */
+  XEmacPs_SetMdioDivisor(instance, MDC_DIV_224);
+  emacPs->linkSpeed = eth_emacps_phy_setup(emacPs);
+  XEmacPs_SetOperatingSpeed(instance, emacPs->linkSpeed);
+  sleep(1);         /* Setting the operating speed of the MAC needs a delay. */
+
+  PRINTK("%-40s: end\n", __func__);
+  return xs;
+}
+
+
+void eth_emacps_init_on_error (EthEmacPs *emacPs)
+{
+  XEmacPs *instance = &emacPs->instance;
+  int      xs;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  PRINTK("%-40s: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
+         ((char*)emacPs->arpcom.ac_enaddr)[0],
+         ((char*)emacPs->arpcom.ac_enaddr)[1],
+         ((char*)emacPs->arpcom.ac_enaddr)[2],
+         ((char*)emacPs->arpcom.ac_enaddr)[3],
+         ((char*)emacPs->arpcom.ac_enaddr)[4],
+         ((char*)emacPs->arpcom.ac_enaddr)[5]);
+
+  /* Set mac address */
+  xs = XEmacPs_SetMacAddress(instance, emacPs->arpcom.ac_enaddr, 1);
+  if (xs != 0) {
+    printk("%-40s: Setting MAC address failed with error %d\n", __func__, xs);
+  }
+
+  XEmacPs_SetOperatingSpeed(instance, emacPs->linkSpeed);
+  sleep(1);         /* Setting the operating speed of the MAC needs a delay. */
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+int eth_emacps_setup_isr(EthEmacPs* emacPs)
+{
+  int xs;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Setup callbacks */
+  xs  = XEmacPs_SetHandler(&emacPs->instance,
+                           XEMACPS_HANDLER_DMASEND,
+                           (void *) eth_emacps_send_handler,
+                           &emacPs->instance);
+  xs |= XEmacPs_SetHandler(&emacPs->instance,
+                           XEMACPS_HANDLER_DMARECV,
+                           (void *) eth_emacps_recv_handler,
+                           &emacPs->instance);
+  xs |= XEmacPs_SetHandler(&emacPs->instance,
+                           XEMACPS_HANDLER_ERROR,
+                           (void *) eth_emacps_error_handler,
+                           &emacPs->instance);
+  PRINTK("%-40s: end\n", __func__);
+
+  return xs;
+}
+
+
+void eth_emacps_start(EthEmacPs *emacPs)
+{
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Start the emacPs */
+  XEmacPs_Start(&emacPs->instance);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+void eth_emacps_stop(EthEmacPs *emacPs)
+{
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Stop the emacPs */
+  XEmacPs_Stop(&emacPs->instance);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+void eth_emacps_reset(EthEmacPs *emacPs)
+{
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Reset the emacPs */
+  XEmacPs_Reset(&emacPs->instance);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+// RiC: This is not used, but save it so it can be resurrected
+//void eth_emacps_restart_transmitter(EthEmacPs *emacPs)
+//{
+//  unsigned baseAdx = emacPs->instance.Config.BaseAddress;
+//  uint32_t reg;
+//
+//  reg  = XEmacPs_ReadReg(baseAdx, XEMACPS_NWCTRL_OFFSET);
+//  reg &= ~XEMACPS_NWCTRL_TXEN_MASK;
+//  XEmacPs_WriteReg(baseAdx, XEMACPS_NWCTRL_OFFSET, reg);
+//
+//  reg  = XEmacPs_ReadReg(baseAdx, XEMACPS_NWCTRL_OFFSET);
+//  reg |= XEMACPS_NWCTRL_TXEN_MASK;
+//  XEmacPs_WriteReg(baseAdx, XEMACPS_NWCTRL_OFFSET, reg);
+//}
+
+
+void eth_emacps_error_handler(void *arg, uint8_t direction, uint32_t errorWord)
+{
+  rtems_status_code  sc       = RTEMS_SUCCESSFUL;
+  EthEmacPs         *emacPs   = (EthEmacPs*) arg;
+  //XEmacPs           *instance = &emacPs->instance;
+
+  PRINTK("%-40s: beg, dir = %u, err = %lu\n", __func__, direction, errorWord);
+  if (errorWord != 0) {
+    switch (direction) {
+      case XEMACPS_RECV: {
+        if (errorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
+          printk("Receive DMA error\n");
+          ++emacPs->stats.rx_dma_errors;
+          eth_emacps_handle_error(emacPs);
+        }
+        if (errorWord & XEMACPS_RXSR_RXOVR_MASK) {
+          printk("Receive overrun\n");
+          ++emacPs->stats.rx_overruns;
+          sc = rtems_bsdnet_event_send(gEthEmacPsRxTask, ETH_EMACPS_EVENT_INTERRUPT);
+          assert(sc == RTEMS_SUCCESSFUL);
+        }
+        if (errorWord & XEMACPS_RXSR_BUFFNA_MASK) {
+          printk("Receive buffer not available\n");
+          ++emacPs->stats.rx_no_buffers;
+          sc = rtems_bsdnet_event_send(gEthEmacPsRxTask, ETH_EMACPS_EVENT_INTERRUPT);
+          assert(sc == RTEMS_SUCCESSFUL);
+        }
+        if (errorWord & ~XEMACPS_RXSR_ERROR_MASK) {
+          printk("Unknown receive error\n");
+          ++emacPs->stats.rx_unknowns;
+        }
+        break;
+      }
+      case XEMACPS_SEND: {
+        if (errorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
+          printk("Transmit DMA error\n");
+          ++emacPs->stats.tx_dma_errors;
+          eth_emacps_handle_error(emacPs);
+        }
+        if (errorWord & XEMACPS_TXSR_URUN_MASK) {
+          printk("Transmit underrun\n");
+          ++emacPs->stats.tx_underruns;
+          eth_emacps_handle_tx_errors(emacPs);
+        }
+        if (errorWord & XEMACPS_TXSR_BUFEXH_MASK) {
+          printk("Transmit buffer exhausted\n");
+          ++emacPs->stats.tx_no_buffers;
+          eth_emacps_handle_tx_errors(emacPs);
+        }
+        if (errorWord & XEMACPS_TXSR_RXOVR_MASK) {
+          printk("Transmit retry limit exceeded\n");
+          ++emacPs->stats.tx_excessive_retries;
+          eth_emacps_handle_tx_errors(emacPs);
+        }
+        if (errorWord & XEMACPS_TXSR_FRAMERX_MASK) {
+          printk("Transmit collision\n");
+          ++emacPs->stats.tx_collisions;
+          sc = rtems_bsdnet_event_send(gEthEmacPsTxTask, ETH_EMACPS_EVENT_INTERRUPT);
+          assert(sc == RTEMS_SUCCESSFUL);
+        }
+        if (errorWord & XEMACPS_TXSR_USEDREAD_MASK) {
+          printk("Transmit buffer used bit set\n");
+          ++emacPs->stats.tx_usedread;
+          sc = rtems_bsdnet_event_send(gEthEmacPsTxTask, ETH_EMACPS_EVENT_INTERRUPT);
+          assert(sc == RTEMS_SUCCESSFUL);
+        }
+        if (errorWord & ~XEMACPS_TXSR_ERROR_MASK) {
+          printk("Unknown transmit error\n");
+          ++emacPs->stats.tx_unknowns;
+        }
+        break;
+      }
+      default:
+        printk("%-40s: Unknown error word value %lu\n", __func__, errorWord);
+        break;
+    }
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
diff --git a/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_phySpeed.c b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_phySpeed.c
new file mode 100644
index 0000000..9645a68
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/network/ethEmacPs_phySpeed.c
@@ -0,0 +1,384 @@
+/**
+ * @file
+ *
+ * @ingroup eth_emacps
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
+ *               All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Advanced Micro Devices, Inc. nor the names
+ *      of its contributors may be used to endorse or promote products
+ *      derived from this software without specific prior written
+ *      permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Some portions copyright (c) 2010 Xilinx, Inc.  All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <bsp/ethernet.h>
+
+/* Advertisement control register. */
+#define ADVERTISE_10HALF      0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_10FULL      0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_100HALF     0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL     0x0100  /* Try for 100mbps full-duplex */
+
+#define ADVERTISE_100_AND_10  (ADVERTISE_10FULL  | ADVERTISE_100FULL | \
+                               ADVERTISE_10HALF  | ADVERTISE_100HALF)
+#define ADVERTISE_100         (ADVERTISE_100FULL | ADVERTISE_100HALF)
+#define ADVERTISE_10          (ADVERTISE_10FULL  | ADVERTISE_10HALF)
+
+#define ADVERTISE_1000        0x0300
+
+
+#define IEEE_CONTROL_REG_OFFSET                  0
+#define IEEE_STATUS_REG_OFFSET                   1
+#define IEEE_AUTONEGO_ADVERTISE_REG              4
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET      5
+#define IEEE_1000_ADVERTISE_REG_OFFSET           9
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET     10
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG        16
+#define IEEE_SPECIFIC_STATUS_REG                17
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2       19
+#define IEEE_CONTROL_REG_MAC                    21
+#define IEEE_PAGE_ADDRESS_REGISTER              22
+
+
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK      0x2040
+#define IEEE_CTRL_LINKSPEED_MASK            0x0040
+#define IEEE_CTRL_LINKSPEED_1000M           0x0040
+#define IEEE_CTRL_LINKSPEED_100M            0x2000
+#define IEEE_CTRL_LINKSPEED_10M             0x0000
+#define IEEE_CTRL_RESET_MASK                0x8000
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE      0x1000
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE     0x0008
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE    0x0020
+#define IEEE_STAT_AUTONEGOTIATE_RESTART     0x0200
+#define IEEE_STAT_1GBPS_EXTENSIONS          0x0100
+#define IEEE_AN1_ABILITY_MASK               0x1FE0
+#define IEEE_AN3_ABILITY_MASK_1GBPS         0x0C00
+#define IEEE_AN1_ABILITY_MASK_100MBPS       0x0380
+#define IEEE_AN1_ABILITY_MASK_10MBPS        0x0060
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK  0x0030
+
+#define IEEE_ASYMMETRIC_PAUSE_MASK          0x0800
+#define IEEE_PAUSE_MASK                     0x0400
+#define IEEE_AUTONEG_ERROR_MASK             0x8000
+
+#define PHY_DETECT_REG                           1
+#define PHY_DETECT_MASK                     0x1808
+
+/* Frequency setting */
+#define SLCR_LOCK_ADDR                      (XPS_SYS_CTRL_BASEADDR + 0x4)
+#define SLCR_UNLOCK_ADDR                    (XPS_SYS_CTRL_BASEADDR + 0x8)
+#define SLCR_GEM0_CLK_CTRL_ADDR             (XPS_SYS_CTRL_BASEADDR + 0x140)
+#define SLCR_GEM1_CLK_CTRL_ADDR             (XPS_SYS_CTRL_BASEADDR + 0x144)
+#define SLCR_LOCK_KEY_VALUE                 0x767B
+#define SLCR_UNLOCK_KEY_VALUE               0xDF0D
+#define SLCR_ADDR_GEM_RST_CTRL              (XPS_SYS_CTRL_BASEADDR + 0x214)
+#define EMACPS_SLCR_DIV_MASK                0xFC0FC0FF
+
+#define EMAC0_BASE_ADDRESS                  0xE000B000
+#define EMAC1_BASE_ADDRESS                  0xE000C000
+
+
+static int eth_emacps_detect_phy(EthEmacPs *emacPs)
+{
+  uint16_t phy_reg;
+  unsigned phy_addr;
+
+  for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+    XEmacPs_PhyRead(&emacPs->instance, phy_addr, PHY_DETECT_REG, &phy_reg);
+
+    if ((phy_reg != 0xFFFF) &&
+        ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+
+      /* Found a valid PHY address */
+      PRINTK("%-40s: PHY detected at address %d\n", __func__, phy_addr);
+      PRINTK("%-40s: PHY detected\n", __func__);
+
+      return phy_addr;
+    }
+  }
+
+  PRINTK("%-40s: No PHY detected.  Assuming a PHY at address 0\n", __func__);
+
+        /* default to zero */
+  return 0;
+}
+
+
+unsigned eth_emacps_get_IEEE_phy_speed(EthEmacPs *emacPs)
+{
+  uint16_t tmp;
+  uint16_t control;
+  uint16_t status;
+  uint16_t partner_capabilities;
+  unsigned phy_addr = eth_emacps_detect_phy(emacPs);
+  XEmacPs* instance = &emacPs->instance;
+
+  printk("Start PHY autonegotiation\n");
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+  control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+  control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+  control |= IEEE_PAUSE_MASK;
+  control |= ADVERTISE_100;
+  control |= ADVERTISE_10;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &control);
+  control |= ADVERTISE_1000;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, control);
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
+  control |= (7 << 12);                 /* Max number of gigabit attempts */
+  control |= (1 << 11);                 /* Enable downshift */
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+  control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+  control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+  control |= IEEE_CTRL_RESET_MASK;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+  for (;;) {
+    XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    if (control & IEEE_CTRL_RESET_MASK)
+      continue;
+    else
+      break;
+  }
+
+  printk("Waiting for PHY to complete autonegotiation\n");
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+  while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+    sleep(1);
+    XEmacPs_PhyRead(instance, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &tmp);
+    if (tmp & IEEE_AUTONEG_ERROR_MASK) {
+      printk("Autonegotiation error\n");
+    }
+    XEmacPs_PhyRead(instance, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+  }
+
+  printk("Autonegotiation complete\n");
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
+  if      ( ((partner_capabilities >> 14) & 3) == 2)  /* 1000Mbps */
+    return 1000;
+  else if ( ((partner_capabilities >> 14) & 3) == 1)  /* 100Mbps */
+    return 100;
+  else                                                /* 10Mbps */
+    return 10;
+}
+
+
+unsigned eth_emacps_configure_IEEE_phy_speed(EthEmacPs *emacPs, unsigned speed)
+{
+  uint16_t control;
+  XEmacPs *instance = &emacPs->instance;
+  unsigned phy_addr = eth_emacps_detect_phy(emacPs);
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+  control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+  control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+  control |= IEEE_PAUSE_MASK;
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+  XEmacPs_PhyRead(instance, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+  control &= ~IEEE_CTRL_LINKSPEED_1000M;
+  control &= ~IEEE_CTRL_LINKSPEED_100M;
+  control &= ~IEEE_CTRL_LINKSPEED_10M;
+
+  if (speed == 1000) {
+    control |= IEEE_CTRL_LINKSPEED_1000M;
+  }
+
+  else if (speed == 100) {
+    control |= IEEE_CTRL_LINKSPEED_100M;
+    /* Dont advertise PHY speed of 1000 Mbps */
+    XEmacPs_PhyWrite(instance, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
+    /* Dont advertise PHY speed of 10 Mbps */
+    XEmacPs_PhyWrite(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_100);
+  }
+
+  else if (speed == 10) {
+    control |= IEEE_CTRL_LINKSPEED_10M;
+    /* Dont advertise PHY speed of 1000 Mbps */
+    XEmacPs_PhyWrite(instance, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
+    /* Dont advertise PHY speed of 100 Mbps */
+    XEmacPs_PhyWrite(instance, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, ADVERTISE_10);
+  }
+
+  XEmacPs_PhyWrite(instance, phy_addr, IEEE_CONTROL_REG_OFFSET,
+                   control | IEEE_CTRL_RESET_MASK);
+  sleep(1);
+
+  return 0;
+}
+
+
+static void eth_emacps_setup_slcr_divisors(int mac_baseaddr, int speed)
+{
+  volatile unsigned slcrBaseAddress;
+  unsigned          SlcrDiv0 = 0;       /* Stop compiler warnings */
+  unsigned          SlcrDiv1 = 0;       /* Stop compiler warnings */
+  unsigned          SlcrTxClkCntrl;
+
+  *(volatile unsigned *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
+
+  if (mac_baseaddr == EMAC0_BASE_ADDRESS) {
+    slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
+  } else {
+    slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
+  }
+  if (speed == 1000) {
+    if (mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+#endif
+    } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+#endif
+    }
+  } else if (speed == 100) {
+    if (mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+#endif
+    } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+#endif
+    }
+  } else {
+    if (mac_baseaddr == EMAC0_BASE_ADDRESS) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+#endif
+    } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
+      SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+      SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+#endif
+    }
+  }
+  SlcrTxClkCntrl  = *(volatile unsigned *)(slcrBaseAddress);
+  SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
+  SlcrTxClkCntrl |= (SlcrDiv1 << 20);
+  SlcrTxClkCntrl |= (SlcrDiv0 << 8);
+  *(volatile unsigned *)(slcrBaseAddress) = SlcrTxClkCntrl;
+  *(volatile unsigned *)(SLCR_LOCK_ADDR)  = SLCR_LOCK_KEY_VALUE;
+}
+
+
+unsigned eth_emacps_phy_setup(EthEmacPs *emacPs)
+{
+  unsigned baseAdx = emacPs->instance.Config.BaseAddress;
+  unsigned linkSpeed;
+
+#if defined(ETH_EMACPS_CONFIG_LINKSPEED)
+#  if   (ETH_EMACPS_CONFIG_LINKSPEED == ETH_EMACPS_LINKSPEED_AUTODETECT)
+  linkSpeed = eth_emacps_get_IEEE_phy_speed(emacPs);
+  if        (linkSpeed == 1000) {
+    eth_emacps_setup_slcr_divisors(baseAdx, 1000);
+  } else if (linkSpeed == 100) {
+    eth_emacps_setup_slcr_divisors(baseAdx, 100);
+  } else {
+    eth_emacps_setup_slcr_divisors(baseAdx, 10);
+  }
+#  elif (ETH_EMACPS_CONFIG_LINKSPEED == ETH_EMACPS_LINKSPEED_1000)
+  eth_emacps_setup_slcr_divisors(baseAdx, 1000);
+  linkSpeed = 1000;
+  eth_emacps_configure_IEEE_phy_speed(emacPs, linkSpeed);
+  sleep(1);
+#  elif (ETH_EMACPS_CONFIG_LINKSPEED == ETH_EMACPS_LINKSPEED_100)
+  eth_emacps_setup_slcr_divisors(baseAdx, 100);
+  linkSpeed = 100;
+  eth_emacps_configure_IEEE_phy_speed(emacPs, linkSpeed);
+  sleep(1);
+#  elif (ETH_EMACPS_CONFIG_LINKSPEED == ETH_EMACPS_LINKSPEED_10)
+  eth_emacps_setup_slcr_divisors(baseAdx, 10);
+  linkSpeed = 10;
+  eth_emacps_configure_IEEE_phy_speed(emacPs, linkSpeed);
+  sleep(1);
+#  endif
+#else
+#  error ETH_EMACPS_CONFIG_LINKSPEED must be defined.
+#endif
+
+  printk("Link speed: %d\n", linkSpeed);
+  return linkSpeed;
+}
diff --git a/c/src/lib/libbsp/arm/zynq/network/ethernet.c b/c/src/lib/libbsp/arm/zynq/network/ethernet.c
new file mode 100644
index 0000000..53039cc
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/network/ethernet.c
@@ -0,0 +1,1070 @@
+/**
+ * @file
+ *
+ * @ingroup eth_emacps
+ *
+ * @brief Ethernet driver.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
+#define __BSD_VISIBLE                    1
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_mii_ioctl.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/utility.h>
+#include <bsp/ethernet.h>
+
+#if MCLBYTES > (2 * 1024)
+  #error "MCLBYTES too large"
+#endif
+
+#define ETH_EMACPS_CONFIG_TX_BUF_SIZE sizeof(struct mbuf *)
+
+#define DEFAULT_PHY      0
+#define WATCHDOG_TIMEOUT 5
+
+/* Status */
+#define ETH_EMACPS_LAST_FRAGMENT_FLAG 0x8000000u
+
+static EthEmacPs gEthEmacPs[XPAR_XEMACPS_NUM_INSTANCES];
+
+rtems_id gEthEmacPsRxTask = 0;
+rtems_id gEthEmacPsTxTask = 0;
+rtems_id gEthEmacPsErTask = 0;
+
+#ifdef RECORD
+struct {
+  struct mbuf *alloc;
+  unsigned     ctrl;
+  struct mbuf *free;
+  unsigned     status;
+}        mbufList[1024];
+unsigned mbufIdx     = 0;
+unsigned mbufFreeIdx = 0;
+#endif
+
+
+static void eth_emacps_control_request_complete(const EthEmacPs *emacPs)
+{
+  PRINTK("%-40s: beg\n", __func__);
+  rtems_status_code sc = rtems_event_transient_send(emacPs->controlTask);
+  assert(sc == RTEMS_SUCCESSFUL);
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static void eth_emacps_control_request(EthEmacPs      *emacPs,
+                                       rtems_id        task,
+                                       rtems_event_set event)
+{
+  PRINTK("%-40s: beg\n", __func__);
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  uint32_t nest_count = 0;
+
+  emacPs->controlTask = rtems_task_self();
+
+  sc = rtems_bsdnet_event_send(task, event);
+  assert(sc == RTEMS_SUCCESSFUL);
+
+  nest_count = rtems_bsdnet_semaphore_release_recursive();
+  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  assert(sc == RTEMS_SUCCESSFUL);
+  rtems_bsdnet_semaphore_obtain_recursive(nest_count);
+
+  emacPs->controlTask = 0;
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static inline uint32_t eth_emacps_increment( uint32_t value,
+                                             uint32_t cycle )
+{
+  if (value < cycle) {
+    return ++value;
+  } else {
+    return 0;
+  }
+}
+
+static void eth_emacps_enable_promiscous_mode(EthEmacPs* emacPs, bool enable)
+{
+  PRINTK("%-40s: beg\n", __func__);
+  if (enable) {
+    XEmacPs_SetOptions(&emacPs->instance, (XEMACPS_PROMISC_OPTION   |
+                                           XEMACPS_MULTICAST_OPTION |
+                                           XEMACPS_BROADCAST_OPTION));
+  } else {
+    XEmacPs_ClearOptions(&emacPs->instance, (XEMACPS_PROMISC_OPTION   |
+                                             XEMACPS_MULTICAST_OPTION |
+                                             XEMACPS_BROADCAST_OPTION));
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static inline void eth_emacps_enable_receive_interrupts(EthEmacPs* emacPs)
+{
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_disable(level);
+  XEmacPs_IntEnable(&emacPs->instance, (XEMACPS_IXR_FRAMERX_MASK |
+                                        XEMACPS_IXR_RX_ERR_MASK));
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static inline void eth_emacps_disable_receive_interrupts(EthEmacPs* emacPs)
+{
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_disable(level);
+  XEmacPs_IntDisable(&emacPs->instance, (XEMACPS_IXR_FRAMERX_MASK |
+                                         XEMACPS_IXR_RX_ERR_MASK));
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static inline void eth_emacps_enable_transmit_interrupts(EthEmacPs* emacPs)
+{
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_disable(level);
+  XEmacPs_IntEnable(&emacPs->instance, (XEMACPS_IXR_TXCOMPL_MASK |
+                                        XEMACPS_IXR_TX_ERR_MASK));
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static inline void eth_emacps_disable_transmit_interrupts(EthEmacPs* emacPs)
+{
+  rtems_interrupt_level level;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  rtems_interrupt_disable(level);
+  XEmacPs_IntDisable(&emacPs->instance, (XEMACPS_IXR_TXCOMPL_MASK |
+                                         XEMACPS_IXR_TX_ERR_MASK));
+  rtems_interrupt_enable(level);
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+
+static struct mbuf *eth_emacps_new_mbuf(struct ifnet *ifp, int wait)
+{
+  struct mbuf *m  = NULL;
+  int          mw = wait ? M_WAIT : M_DONTWAIT;
+
+  MGETHDR(m, mw, MT_DATA);
+  if (m != NULL) {
+    MCLGET(m, mw);
+    if ((m->m_flags & M_EXT) != 0) {
+      /* Set receive interface */
+      m->m_pkthdr.rcvif = ifp;
+
+      /* Adjust by two bytes for proper IP header alignment */
+      m->m_data = mtod(m, char *) + ETH_EMACPS_RX_DATA_OFFSET;
+
+      return m;
+    } else {
+      m_free(m);
+    }
+  }
+
+  return NULL;
+}
+
+struct mbuf *eth_emacps_add_new_mbuf( EthEmacPs       *emacPs,
+                                      struct mbuf    **mbufs,
+                                      int              wait )
+{
+  struct ifnet *const ifp = &emacPs->arpcom.ac_if;
+  struct mbuf        *m   = eth_emacps_new_mbuf(ifp, wait);
+
+  /* Check mbuf */
+  if (m != NULL) {
+    /* Invalidate cache to insure fresh data is picked up from the DMA */
+    rtems_cache_invalidate_multiple_data_lines(mtod(m, void *),
+                                               MCLBYTES - ETH_EMACPS_RX_DATA_OFFSET);
+  }
+  return m;
+}
+
+static void eth_emacps_receive_task(void *arg)
+{
+  rtems_status_code sc     = RTEMS_SUCCESSFUL;
+  rtems_event_set   events = 0;
+  EthEmacPs  *const emacPs = (EthEmacPs *)arg;
+  XEmacPs_BdRing   *rxRing = &XEmacPs_GetRxRing(&emacPs->instance);
+  unsigned          tooLow = emacPs->rxUnitCount - 4; /* Some number... */
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Main event loop */
+  for (;;) {
+    PRINTK("%-40s: Waiting...\n", __func__);
+    /* Wait for events */
+    sc = rtems_bsdnet_event_receive( ETH_EMACPS_EVENT_INITIALIZE |
+                                     ETH_EMACPS_EVENT_STOP       |
+                                     ETH_EMACPS_EVENT_INTERRUPT,
+                                     RTEMS_EVENT_ANY | RTEMS_WAIT,
+                                     RTEMS_NO_TIMEOUT,
+                                     &events );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    PRINTK("%-40s: WAKE up: 0x%08" PRIx32 "\n", __func__, events);
+
+    /* Stop receiver? */
+    if ((events & ETH_EMACPS_EVENT_STOP) != 0) {
+      PRINTK("%-40s: STOP\n", __func__);
+      eth_emacps_control_request_complete(emacPs);
+
+      PRINTK("%-40s: STOP done\n", __func__);
+
+      /* Wait for events */
+      continue;
+    }
+
+    /* Initialize receiver? */
+    if ((events & ETH_EMACPS_EVENT_INITIALIZE) != 0) {
+      PRINTK("%-40s: INIT\n", __func__);
+      /* Disable receive interrupts */
+      eth_emacps_disable_receive_interrupts(emacPs);
+
+      /* Fill receive queue */
+      eth_emacps_process_rxd_bds(emacPs, rxRing, M_WAIT);
+
+      /* Enable receive interrupts */
+      eth_emacps_enable_receive_interrupts(emacPs);
+
+      eth_emacps_control_request_complete(emacPs);
+
+      PRINTK("%-40s: INIT done\n", __func__);
+
+      /* Wait for events */
+      continue;
+    }
+
+    /* Event must be a ETH_EMACPS_EVENT_INTERRUPT */
+    PRINTK("%-40s: INTERRUPT\n", __func__);
+
+    for (;;) {
+      unsigned nBds = eth_emacps_input(emacPs, rxRing);
+      bool     wait = XEmacPs_BdRingGetFreeCnt(rxRing) < tooLow ? M_WAIT
+                                                                : M_DONTWAIT;
+      PRINTK("%-40s: nBds = %08x\n", __func__, nBds);
+
+      /* Increment received frames counter */
+      emacPs->stats.rxd_frames += nBds;
+
+      /* Refill the empty slots in the receive queue */
+      eth_emacps_process_rxd_bds(emacPs, rxRing, wait);
+
+      if (nBds == 0) {
+        /* Nothing to do, enable receive interrupts */
+        eth_emacps_enable_receive_interrupts(emacPs);
+        break;
+      }
+    }
+    PRINTK("%-40s: INTERRUPT done\n", __func__);
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static struct mbuf *eth_emacps_next_fragment(struct ifnet *ifp,
+                                             struct mbuf  *m)
+{
+  struct mbuf *n = NULL;
+  int size = 0;
+
+  PRINTK("%-40s: beg, ifp = %08x, m = %08x\n", __func__,
+         (uint)ifp, (uint)m);
+
+  for (;;) {
+    if (m == NULL) {
+      /* Dequeue first fragment of the next frame */
+      IF_DEQUEUE(&ifp->if_snd, m);
+
+      /* Empty queue? */
+      if (m == NULL) {
+        return m;
+      }
+    }
+
+    /* Get fragment size */
+    size = m->m_len;
+
+    if (size > 0) {
+      /* Now we have a non-empty fragment */
+      break;
+    } else {
+      /* Discard empty fragments */
+      m = m_free(m);
+    }
+  }
+
+  /* Discard empty successive fragments */
+  n = m->m_next;
+  while (n != NULL && (n->m_len <= 0)) { // || n->m_len >= XEMACPS_MAX_FRAME_SIZE)) {
+    n = m_free(n);
+  }
+  m->m_next = n;
+
+  PRINTK("%-40s: end, m = %08x, d = %08x, len = %08x, n = %08x\n", __func__,
+         (uint)m, mtod(m, uint), m->m_len, (uint)m->m_next);
+
+  return m;
+}
+
+static void eth_emacps_transmit_task(void *arg)
+{
+  rtems_status_code  sc       = RTEMS_SUCCESSFUL;
+  rtems_event_set    events   = 0;
+  EthEmacPs         *emacPs   = (EthEmacPs *) arg;
+  XEmacPs_BdRing    *txRing   = &XEmacPs_GetTxRing(&emacPs->instance);
+  struct ifnet      *ifp      = &emacPs->arpcom.ac_if;
+  struct mbuf       *m        = NULL;
+  struct mbuf       *m0       = NULL;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Main event loop */
+  for (;;) {
+    PRINTK("%-40s: Waiting...\n", __func__);
+    /* Wait for events */
+    sc = rtems_bsdnet_event_receive( ETH_EMACPS_EVENT_INITIALIZE |
+                                     ETH_EMACPS_EVENT_STOP       |
+                                     ETH_EMACPS_EVENT_TXSTART    |
+                                     ETH_EMACPS_EVENT_INTERRUPT,
+                                     RTEMS_EVENT_ANY | RTEMS_WAIT,
+                                     RTEMS_NO_TIMEOUT,
+                                     &events );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    PRINTK("%-40s: WAKE up: 0x%08" PRIx32 "\n", __func__, events);
+
+    /* Stop transmitter? */
+    if ((events & ETH_EMACPS_EVENT_STOP) != 0) {
+      PRINTK("%-40s: STOP\n", __func__);
+      eth_emacps_control_request_complete(emacPs);
+
+      PRINTK("%-40s: STOP done\n", __func__);
+
+      /* Wait for events */
+      continue;
+    }
+
+    /* Initialize transmitter? */
+    if ((events & ETH_EMACPS_EVENT_INITIALIZE) != 0) {
+      PRINTK("%-40s: INIT\n", __func__);
+      /* Disable transmit interrupts */
+      eth_emacps_disable_transmit_interrupts(emacPs);
+
+      /* Discard outstanding fragments (= data loss) */
+      eth_emacps_process_txd_bds(emacPs, txRing);
+
+      eth_emacps_control_request_complete(emacPs);
+
+      PRINTK("%-40s: INIT done\n", __func__);
+
+      /* Wait for events */
+      continue;
+    }
+
+    /* Event must be an ETH_EMACPS_EVENT_INTERRUPT */
+    PRINTK("%-40s: INTERRUPT\n", __func__);
+
+    /* Process completed BDs */
+    eth_emacps_process_txd_bds(emacPs, txRing);
+
+    /* Transmit new fragments */
+    for (;;) {
+      /* Get next fragment from the network stack */
+      m = eth_emacps_next_fragment(ifp, m);
+
+      /* New fragment? */
+      if (m != NULL) {
+        /* Remember which is the first fragment of the frame */
+        if (m0 == NULL) {
+          m0 = m;
+        }
+
+#ifdef RECORD
+        mbufList[mbufIdx   & 0x3ff].alloc = m;
+        mbufList[mbufIdx++ & 0x3ff].ctrl  = (m->m_next ? 0 : XEMACPS_TXBUF_LAST_MASK) | (mbufFreeIdx << 16) | m->m_len;
+#endif
+
+        /* Next fragment of the frame */
+        m = m->m_next;
+
+        /* If the fragment is the last in the frame, hand it to the DMA engine */
+        if (m == NULL) {
+          sc = eth_emacps_output(emacPs, m0);
+          if (sc != RTEMS_SUCCESSFUL) {
+            PRINTK("%-40s: Full ring buffer: 0x%08x\n", __func__, m0);
+
+            /* Frame not sent, wait for transmit interrupt */
+            break;
+          }
+          m0 = m;                       /* i.e., NULL */
+        }
+      } else {
+        /* Nothing to transmit */
+        break;
+      }
+    }
+
+    /* No more fragments? */
+    if (m == NULL) {
+      /* Interface is now inactive */
+      ifp->if_flags &= ~IFF_OACTIVE;
+    } else {
+      /* Enable transmit interrupts */
+      eth_emacps_enable_transmit_interrupts(emacPs);
+    }
+    PRINTK("%-40s: INTERRUPT done\n", __func__);
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static int eth_emacps_mdio_wait_for_not_busy(XEmacPs* instance)
+{
+  rtems_interval one_second = rtems_clock_get_ticks_per_second();
+  rtems_interval i          = 0;
+  unsigned       baseAdx    = instance->Config.BaseAddress;
+
+  PRINTK("%-40s: beg\n", __func__);
+  while ((XEmacPs_ReadReg(baseAdx, XEMACPS_NWSR_OFFSET) &
+          XEMACPS_NWSR_MDIOIDLE_MASK) == 0 && i < one_second) {
+    rtems_task_wake_after(1);
+    ++i;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+  return i != one_second ? 0 : ETIMEDOUT;
+}
+
+static int eth_emacps_mdio_read(int phy, void *arg, unsigned reg, uint32_t *val)
+{
+  int      eno;
+  uint16_t v16;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  if (phy == -1 && phy < XPAR_XEMACPS_NUM_INSTANCES) {
+    EthEmacPs* emacPs;
+
+    if (phy == -1)
+      phy = DEFAULT_PHY;
+
+    emacPs = &gEthEmacPs[phy];
+
+    eno = XEmacPs_PhyRead(&emacPs->instance, (unsigned)arg, reg, &v16);
+    if (eno == XST_EMAC_MII_BUSY)
+      eno = eth_emacps_mdio_wait_for_not_busy(&emacPs->instance);
+    *val = v16;
+  } else {
+    eno = EINVAL;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+
+  return eno;
+}
+
+static int eth_emacps_mdio_write(int phy, void *arg, unsigned reg, uint32_t val)
+{
+  int eno;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  if (phy == -1 && phy < XPAR_XEMACPS_NUM_INSTANCES) {
+    EthEmacPs* emacPs;
+
+    if (phy == -1)
+      phy = DEFAULT_PHY;
+
+    emacPs = &gEthEmacPs[phy];
+
+    eno = XEmacPs_PhyWrite(&emacPs->instance, (unsigned)arg, reg, val);
+    if (eno == XST_EMAC_MII_BUSY)
+      eno = eth_emacps_mdio_wait_for_not_busy(&emacPs->instance);
+  } else {
+    eno = EINVAL;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+  return eno;
+}
+
+static int eth_emacps_up_or_down(EthEmacPs *emacPs, bool up)
+{
+  int               eno = 0;
+  rtems_status_code sc;
+  struct ifnet     *ifp = &emacPs->arpcom.ac_if;
+
+  PRINTK("%-40s: beg, currently %s, going %s\n", __func__,
+         (emacPs->state == ETH_EMACPS_STATE_DOWN ? "DOWN" :
+          (emacPs->state == ETH_EMACPS_STATE_UP ? "UP" : "UNDEFINED")),
+         (up ? "UP" : "DOWN"));
+
+  if (up && emacPs->state == ETH_EMACPS_STATE_DOWN) {
+    /* Initialize the hardware */
+    eth_emacps_low_level_init(emacPs);
+
+    /* Initialize tasks */
+    eth_emacps_control_request(emacPs, gEthEmacPsRxTask, ETH_EMACPS_EVENT_INITIALIZE);
+    eth_emacps_control_request(emacPs, gEthEmacPsTxTask, ETH_EMACPS_EVENT_INITIALIZE);
+
+    /* Install interrupt handler and enable the vector */
+    sc = rtems_interrupt_handler_install( emacPs->irqNumber,
+                                          "Ethernet",
+                                          RTEMS_INTERRUPT_UNIQUE,
+                                          XEmacPs_IntrHandler,
+                                          emacPs );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    /* Enable transmitter and receiver */
+    eth_emacps_start(emacPs);
+
+    /* Start watchdog timer */
+    ifp->if_timer = 0; //1; /* @todo - RiC: Punt on the watchdog for now. */
+
+    /* Change state */
+    emacPs->state = ETH_EMACPS_STATE_UP;
+
+  } else if (!up && emacPs->state == ETH_EMACPS_STATE_UP) {
+    /* Stop the MAC */
+    eth_emacps_stop(emacPs);
+
+    /* Remove interrupt handler */
+    sc = rtems_interrupt_handler_remove( emacPs->irqNumber,
+                                         XEmacPs_IntrHandler,
+                                         emacPs );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    /* Stop tasks */
+    eth_emacps_control_request(emacPs, gEthEmacPsRxTask, ETH_EMACPS_EVENT_STOP);
+    eth_emacps_control_request(emacPs, gEthEmacPsTxTask, ETH_EMACPS_EVENT_STOP);
+
+    /* Stop watchdog timer */
+    ifp->if_timer = 0;
+
+    /* Change state */
+    emacPs->state = ETH_EMACPS_STATE_DOWN;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+  return eno;
+}
+
+static void eth_emacps_interface_init(void *arg)
+{
+  PRINTK("%-40s: beg, arg = %08x, *arg = %08x\n", __func__, (uint)arg, *(uint*)arg);
+  /* Nothing to do */
+  PRINTK("%-40s: end\n", __func__);
+}
+
+static void eth_emacps_interface_stats(EthEmacPs *emacPs)
+{
+  int                    eno   = EIO;
+  int                    media = 0;
+  struct ifnet          *ifp   = &emacPs->arpcom.ac_if;
+  struct EthEmacPsStats *s     = &emacPs->stats;
+  unsigned               base  = emacPs->instance.Config.BaseAddress;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  if (emacPs->state == ETH_EMACPS_STATE_UP) {
+    media = IFM_MAKEWORD(0, 0, 0, 0);
+    eno = rtems_mii_ioctl(&emacPs->mdio, emacPs, SIOCGIFMEDIA, &media);
+  }
+
+  rtems_bsdnet_semaphore_release();
+
+  if (eno == 0) {
+    rtems_ifmedia2str(media, NULL, 0);
+    printf("\n");
+  }
+
+  printf("\n%s: Statistics for interface '%s%d':\n", __func__, ifp->if_name, ifp->if_unit);
+
+  printf(" SW counters:\n");
+  printf("  Frames Transmitted:           %08lx",   s->txd_frames);
+  printf("  Frames Received:              %08lx\n", s->rxd_frames);
+  printf("  Tx Interrupts:                %08lx",   s->tx_interrupts);
+  printf("  Rx Interrupts:                %08lx\n", s->rx_interrupts);
+
+  printf("  Tx drop            errors:    %08lx",   s->tx_drop);
+  printf("  Rx drop            errors:    %08lx\n", s->rx_drop);
+  printf("  Tx fragments:                 %08lx",   s->tx_xmit);
+  printf("  Rx fragments:                 %08lx\n", s->rx_recv);
+  printf("  Tx DMA             errors:    %08lx",   s->tx_dma_errors);
+  printf("  Rx DMA             errors:    %08lx\n", s->rx_dma_errors);
+  printf("  Tx underrun        errors:    %08lx",   s->tx_underruns);
+  printf("  Rx overrun         errors:    %08lx\n", s->rx_overruns);
+  printf("  Tx no buffer       errors:    %08lx",   s->tx_no_buffers);
+  printf("  Rx no buffer       errors:    %08lx\n", s->rx_no_buffers);
+  printf("  Tx excessive retry errors:    %08lx",   s->tx_excessive_retries);
+  printf("  Rx No new mbuf     errors:    %08lx\n", s->rx_memErr);
+  printf("  Tx collisions      errors:    %08lx\n", s->tx_collisions);
+  printf("  Tx used bit set    errors:    %08lx\n", s->tx_usedread);
+  printf("  Tx overflow        errors:    %08lx\n", s->tx_overflows);
+  printf("  Tx full queue      errors:    %08lx\n", s->tx_full_queues);
+  printf("  Tx unknown         errors:    %08lx",   s->tx_unknowns);
+  printf("  Rx unknown         errors:    %08lx\n", s->rx_unknowns);
+
+  printf("\n Buffer descriptor counters:\n");
+  printf("  Tx Retry limit exceeded:      %08lx",   s->tx_stat_retries);
+  printf("  Rx Broadcast adx detected:    %08lx\n", s->rx_stat_bcast);
+  printf("  Tx Frame corruption:          %08lx",   s->tx_stat_ahb_errors);
+  printf("  Rx Multicast hash matches:    %08lx\n", s->rx_stat_mcast);
+  printf("  Tx Late collision:            %08lx",   s->tx_stat_late_collisions);
+  printf("  Rx Unicast   hash matches:    %08lx\n", s->rx_stat_ucast);
+  printf("  Tx IP/TCP/UDP checksum                ");
+  printf("  Rx Specific  adx1 matches:    %08lx\n", s->rx_stat_adx1);
+  printf("     generation offload errors:         ");
+  printf("  Rx Specific  adx2 matches:    %08lx\n", s->rx_stat_adx2);
+  printf("     No error:                  %08lx",   s->tx_stat_no_errors);
+  printf("  Rx Specific  adx3 matches:    %08lx\n", s->rx_stat_adx3);
+  printf("     VLAN packet error:         %08lx",   s->tx_stat_vlan_errors);
+  printf("  Rx Specific  adx4 matches:    %08lx\n", s->rx_stat_adx4);
+  printf("     SNAP packet error:         %08lx",   s->tx_stat_snap_errors);
+  printf("  Rx Bit  24    (see UG585):    %08lx\n", s->rx_stat_bit_24);
+  printf("     Pkt not IP type or short:  %08lx",   s->tx_stat_ip_errors);
+  printf("  Rx Bits 22,23 = 0 (UG585):    %08lx\n", s->rx_stat_reg1);
+  printf("     Pkt not VLAN, SNAP or IP:  %08lx",   s->tx_stat_id_errors);
+  printf("  Rx Bits 22,23 = 1 (UG585):    %08lx\n", s->rx_stat_reg2);
+  printf("     Unsupported packet frag.:  %08lx",   s->tx_stat_badfrag_errors);
+  printf("  Rx Bits 22,23 = 2 (UG585):    %08lx\n", s->rx_stat_reg3);
+  printf("     Not TCP or UDP:            %08lx",   s->tx_stat_tcpudp_errors);
+  printf("  Rx Bits 22,23 = 3 (UG585):    %08lx\n", s->rx_stat_reg4);
+  printf("     Premature end of packet:   %08lx",   s->tx_stat_eop_errors);
+  printf("  Rx VLAN     tag detected:     %08lx\n", s->rx_stat_vlan);
+  printf("                                        ");
+  printf("  Rx Priority tag detected:     %08lx\n", s->rx_stat_priority);
+  printf("                                        ");
+  printf("  Rx CFI:                       %08lx\n", s->rx_stat_cfi);
+  printf("                                        ");
+  printf("  Rx End   of Frame:            %08lx\n", s->rx_stat_eof);
+  printf("                                        ");
+  printf("  Rx Start of Frame:            %08lx\n", s->rx_stat_sof);
+  printf("                                        ");
+  printf("  Rx Bad FCS (if enabled):      %08lx\n", s->rx_stat_fcs);
+
+  printf("\n HW counters:\n");
+  printf("  Octets Txd (w/o err): %08lx%08lx",      XEmacPs_ReadReg(base, XEMACPS_OCTTXH_OFFSET        ), XEmacPs_ReadReg(base, XEMACPS_OCTTXL_OFFSET));
+  printf("  Octets Rxd:           %08lx%08lx\n",    XEmacPs_ReadReg(base, XEMACPS_OCTRXH_OFFSET        ), XEmacPs_ReadReg(base, XEMACPS_OCTRXL_OFFSET));
+  printf("  Frames Txd:                   %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXCNT_OFFSET         ));
+  printf("  Frames Rxd:                   %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXCNT_OFFSET         ));
+  printf("  Broadcast frames Tx:          %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXBCCNT_OFFSET       ));
+  printf("  Broadcast frames Rx:          %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXBROADCNT_OFFSET    ));
+  printf("  Multicast frames Tx:          %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXMCCNT_OFFSET       ));
+  printf("  Multicast frames Rx:          %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXMULTICNT_OFFSET    ));
+  printf("  Pause     frames Tx:          %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXPAUSECNT_OFFSET    ));
+  printf("  Pause     frames Rx:          %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXPAUSECNT_OFFSET    ));
+  printf("  Frames Tx,          64 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX64CNT_OFFSET       ));
+  printf("  Frames Rx,          64 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX64CNT_OFFSET       ));
+  printf("  Frames Tx,   65 -  127 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX65CNT_OFFSET       ));
+  printf("  Frames Rx,   65 -  127 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX65CNT_OFFSET       ));
+  printf("  Frames Tx,  128 -  255 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX128CNT_OFFSET      ));
+  printf("  Frames Rx,  128 -  255 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX128CNT_OFFSET      ));
+  printf("  Frames Tx,  256 -  511 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX256CNT_OFFSET      ));
+  printf("  Frames Rx,  256 -  511 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX256CNT_OFFSET      ));
+  printf("  Frames Tx,  512 - 1023 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX512CNT_OFFSET      ));
+  printf("  Frames Rx,  512 - 1023 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX512CNT_OFFSET      ));
+  printf("  Frames Tx, 1024 - 1518 Bytes: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TX1024CNT_OFFSET     ));
+  printf("  Frames Rx, 1024 - 1518 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX1024CNT_OFFSET     ));
+  printf("  Frames Tx,      > 1518 Bytes: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_TX1519CNT_OFFSET     ));
+  printf("  Transmit  underrun    errors: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXURUNCNT_OFFSET     ));
+  printf("  Receive   overrun     errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXRESERRCNT_OFFSET   ));
+  printf("  Single    Collision   Frames: %08lx",   XEmacPs_ReadReg(base, XEMACPS_SNGLCOLLCNT_OFFSET   ));
+  printf("  Undersize frames    received: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RX1519CNT_OFFSET     ));
+  printf("  Multiple  Collision   Frames: %08lx",   XEmacPs_ReadReg(base, XEMACPS_MULTICOLLCNT_OFFSET  ));
+  printf("  Oversize  frames    received: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXUNDRCNT_OFFSET     ));
+  printf("  Excessive Collisions:         %08lx",   XEmacPs_ReadReg(base, XEMACPS_EXCESSCOLLCNT_OFFSET ));
+  printf("  Jabbers             received: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXOVRCNT_OFFSET      ));
+  printf("  Late      Collisions:         %08lx",   XEmacPs_ReadReg(base, XEMACPS_LATECOLLCNT_OFFSET   ));
+  printf("  Frame check sequence  errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXJABCNT_OFFSET      ));
+  printf("  Deferred Transmission Frames: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXDEFERCNT_OFFSET    ));
+  printf("  Length    field frame errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXFCSCNT_OFFSET      ));
+  printf("  Carrier   Sense       errors: %08lx",   XEmacPs_ReadReg(base, XEMACPS_TXCSENSECNT_OFFSET   ));
+  printf("  Receive   symbol      errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXLENGTHCNT_OFFSET   ));
+  printf("  IP header checksum    errors: %08lx",   XEmacPs_ReadReg(base, XEMACPS_RXORCNT_OFFSET       ));
+  printf("  Receive   resource    errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXALIGNCNT_OFFSET    ));
+  printf("  TCP       checksum    errors: %08lx",   XEmacPs_ReadReg(base, XEMACPS_RXIPCCNT_OFFSET      ));
+  printf("  Alignment             errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXSYMBCNT_OFFSET     ));
+  printf("  UDP       checksum    errors: %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXTCPCCNT_OFFSET     ));
+
+  printf("  PTP      event frame Txd S:   %08lx",   XEmacPs_ReadReg(base, XEMACPS_PTP_TXSEC_OFFSET     ));
+  printf("  PTP      event frame Rxd S:   %08lx\n", XEmacPs_ReadReg(base, XEMACPS_PTP_RXSEC_OFFSET     ));
+  printf("  PTP      event frame Txd nS:  %08lx",   XEmacPs_ReadReg(base, XEMACPS_PTP_TXNANOSEC_OFFSET ));
+  printf("  PTP      event frame Rxd nS:  %08lx\n", XEmacPs_ReadReg(base, XEMACPS_PTP_RXNANOSEC_OFFSET ));
+  printf("  PTP peer event frame Txd S:   %08lx",   XEmacPs_ReadReg(base, XEMACPS_PTPP_TXSEC_OFFSET    ));
+  printf("  PTP peer event frame Rxd S:   %08lx\n", XEmacPs_ReadReg(base, XEMACPS_PTPP_RXSEC_OFFSET    ));
+  printf("  PTP peer event frame Txd nS:  %08lx",   XEmacPs_ReadReg(base, XEMACPS_PTPP_TXNANOSEC_OFFSET));
+  printf("  PTP peer event frame Rxd nS:  %08lx\n", XEmacPs_ReadReg(base, XEMACPS_PTPP_RXNANOSEC_OFFSET));
+  printf("  1588 timer seconds (S):       %08lx",   XEmacPs_ReadReg(base, XEMACPS_1588_SEC_OFFSET      ));
+  printf("  1588 timer sync strobe S:     %08lx\n", XEmacPs_ReadReg(base, XEMACPS_RXUDPCCNT_OFFSET     ));
+  printf("  1588 timer nanoseconds (nS):  %08lx",   XEmacPs_ReadReg(base, XEMACPS_1588_NANOSEC_OFFSET  ));
+  printf("  1588 timer sync strobe nS:    %08lx\n", XEmacPs_ReadReg(base, XEMACPS_LAST_OFFSET          ));
+  printf("  1588 timer adjust:            %08lx",   XEmacPs_ReadReg(base, XEMACPS_1588_ADJ_OFFSET      ));
+  printf("  1588 timer increment:         %08lx\n", XEmacPs_ReadReg(base, XEMACPS_1588_INC_OFFSET      ));
+  printf("\n");
+
+  rtems_bsdnet_semaphore_obtain();
+  PRINTK("%-40s: end\n", __func__);
+}
+
+// @todo - RiC: Still need to sort this out
+static int eth_emacps_multicast_control( bool           add,
+                                         struct ifreq  *ifr,
+                                         struct arpcom *ac )
+{
+  int eno = 0;
+
+  PRINTK("%-40s: beg\n", __func__);
+  if (add) {
+    eno = ether_addmulti(ifr, ac);
+  } else {
+    eno = ether_delmulti(ifr, ac);
+  }
+
+  if (eno == ENETRESET) {
+    struct ether_multistep step;
+    struct ether_multi *enm;
+
+    eno = 0;
+
+    //eth->hashfilterl = 0;
+    //eth->hashfilterh = 0;
+
+    ETHER_FIRST_MULTI(step, ac, enm);
+    while (enm != NULL) {
+      uint64_t addrlo = 0;
+      uint64_t addrhi = 0;
+
+      memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
+      memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
+      while (addrlo <= addrhi) {
+        /* XXX: ether_crc32_le() does not work, why? */
+        uint32_t crc = ether_crc32_be((uint8_t *) &addrlo, ETHER_ADDR_LEN);
+        uint32_t idx = (crc >> 23) & 0x3f;
+
+        if (idx < 32) {
+        //  eth->hashfilterl |= 1U << idx;
+        } else {
+        //  eth->hashfilterh |= 1U << (idx - 32);
+        }
+        ++addrlo;
+      }
+      ETHER_NEXT_MULTI(step, enm);
+    }
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+  return eno;
+}
+
+static int eth_emacps_interface_ioctl( struct ifnet   *ifp,
+                                       ioctl_command_t cmd,
+                                       caddr_t         data )
+{
+  EthEmacPs    *emacPs = (EthEmacPs *) ifp->if_softc;
+  struct ifreq *ifr    = (struct ifreq *) data;
+  int           eno    = 0;
+
+  PRINTK("%-40s: beg, cmd = %08x\n", __func__, cmd);
+
+  switch (cmd)  {
+    case SIOCGIFMEDIA:
+    case SIOCSIFMEDIA:
+      PRINTK("%-40s: MEDIA beg, cmd = %08x, data = %08x\n", __func__, cmd, data);
+      rtems_mii_ioctl(&emacPs->mdio, emacPs, cmd, &ifr->ifr_media);
+      PRINTK("%-40s: MEDIA end\n", __func__);
+      break;
+    case SIOCGIFADDR:
+    case SIOCSIFADDR:
+      PRINTK("%-40s: ADDR beg, cmd = %08x, data = %08x\n", __func__, cmd, data);
+      ether_ioctl(ifp, cmd, data);
+      PRINTK("%-40s: ADDR end\n", __func__);
+      break;
+    case SIOCSIFFLAGS:
+      PRINTK("%-40s: FLAGS beg\n", __func__);
+      eno = eth_emacps_up_or_down(emacPs, (ifp->if_flags & IFF_UP) != 0);
+      if (eno == 0 && (ifp->if_flags & IFF_UP) != 0) {
+        PRINTK("%-40s: FLAGS mid\n", __func__);
+        eth_emacps_enable_promiscous_mode(emacPs, (ifp->if_flags & IFF_PROMISC) != 0);
+      }
+      PRINTK("%-40s: FLAGS end\n", __func__);
+      break;
+    case SIOCADDMULTI:
+    case SIOCDELMULTI:
+      PRINTK("%-40s: MULTI beg\n", __func__);
+      eno = eth_emacps_multicast_control(cmd == SIOCADDMULTI, ifr, &emacPs->arpcom);
+      PRINTK("%-40s: MULTI end\n", __func__);
+      break;
+    case SIO_RTEMS_SHOW_STATS:
+      PRINTK("%-40s: STATS beg\n", __func__);
+      eth_emacps_interface_stats(emacPs);
+      PRINTK("%-40s: STATS end\n", __func__);
+      break;
+    default:
+      PRINTK("%-40s: Error\n", __func__);
+      eno = EINVAL;
+      break;
+  }
+
+  PRINTK("%-40s: end\n", __func__);
+  return eno;
+}
+
+static void eth_emacps_interface_start(struct ifnet *ifp)
+{
+  PRINTK("%-40s: beg\n", __func__);
+
+  EthEmacPs *emacPs = (EthEmacPs *)ifp->if_softc;
+
+  ifp->if_flags |= IFF_OACTIVE;
+
+  /* Wake up tx thread with outbound interface's signal */
+  if (emacPs->state == ETH_EMACPS_STATE_UP) {
+    rtems_status_code sc = RTEMS_SUCCESSFUL;
+    sc = rtems_bsdnet_event_send(gEthEmacPsTxTask, ETH_EMACPS_EVENT_TXSTART);
+    assert(sc == RTEMS_SUCCESSFUL);
+  }
+  PRINTK("%-40s: end\n", __func__);
+}
+
+// @todo - RiC: Punt on this for now
+//static void eth_emacps_interface_watchdog(struct ifnet *ifp)
+//{
+//  EthEmacPs *emacPs = (EthEmacPs *) ifp->if_softc;
+//
+//  if (emacPs->state == ETH_EMAC_STATE_UP) {
+//    eth_emacps_phy_setup(emacPs);  <-- I think this isn't right.
+//
+//    ifp->if_timer = WATCHDOG_TIMEOUT;
+//  }
+//}
+
+static int eth_emacps_attach(struct rtems_bsdnet_ifconfig *ifCfg)
+{
+  EthEmacPs    *emacPs;
+  struct ifnet *ifp;
+  char         *unitName;
+  int           unitIdx;
+  size_t        tableAreaSize = 0;
+  char         *tableArea     = NULL;
+  char         *tableLocation = NULL;
+
+  PRINTK("%-40s: beg\n", __func__);
+
+  /* Check parameters */
+  unitIdx = rtems_bsdnet_parse_driver_name(ifCfg, &unitName);
+  if (unitIdx < 0) {
+    printk("%s: Interface not found (%d)\n", __func__, unitIdx);
+    return 0;
+  }
+
+  if (unitIdx >= XPAR_XEMACPS_NUM_INSTANCES) {
+    printk("%s: Bad unit number (%d)\n", __func__, unitIdx);
+    goto cleanup;
+  }
+
+  if (ifCfg->hardware_address == NULL) {
+    printk("%s: No MAC address given for interface '%s%d'\n", __func__,
+           unitName, unitIdx);
+    goto cleanup;
+  }
+
+  emacPs = &gEthEmacPs[unitIdx];
+  if (emacPs->state != ETH_EMACPS_STATE_NOT_INITIALIZED) {
+    printk("%s: Device '%s%d' is already attached\n", __func__, unitName, unitIdx);
+    goto cleanup;
+  }
+
+  /* MDIO */                 /*@todo - RiC: Still need to sort this out */
+  emacPs->mdio.mdio_r   = eth_emacps_mdio_read;
+  emacPs->mdio.mdio_w   = eth_emacps_mdio_write;
+  emacPs->mdio.has_gmii = 1;
+
+  /* Interrupt number */
+  ifCfg->irno       = ETH_EMACPS_CONFIG_INTERRUPT;
+  emacPs->irqNumber = ifCfg->irno;
+
+  /* Device control */
+  ifCfg->drv_ctrl = emacPs;
+
+  /* Receive unit count */
+  emacPs->rxUnitCount = RXBD_CNT;
+  ifCfg->rbuf_count   = (int) emacPs->rxUnitCount;
+
+  /* Transmit unit count */
+  emacPs->txUnitCount = TXBD_CNT;
+  ifCfg->xbuf_count   = (int) emacPs->txUnitCount;
+
+  /* Remember interrupt number */
+  emacPs->irqNumber = ifCfg->irno;
+
+  /* Copy MAC address */
+  memcpy(emacPs->arpcom.ac_enaddr, ifCfg->hardware_address, ETHER_ADDR_LEN);
+
+  PRINTK("%-40s: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
+         ((char*)emacPs->arpcom.ac_enaddr)[0],
+         ((char*)emacPs->arpcom.ac_enaddr)[1],
+         ((char*)emacPs->arpcom.ac_enaddr)[2],
+         ((char*)emacPs->arpcom.ac_enaddr)[3],
+         ((char*)emacPs->arpcom.ac_enaddr)[4],
+         ((char*)emacPs->arpcom.ac_enaddr)[5]);
+
+  /* Allocate and clear table area */
+  tableAreaSize = emacPs->rxUnitCount * (sizeof(struct mbuf *))
+                + emacPs->txUnitCount * (sizeof(struct mbuf *) +
+                                         ETH_EMACPS_CONFIG_TX_BUF_SIZE);
+  tableArea     = eth_emacps_config_alloc_table_area(tableAreaSize);
+  if (tableArea == NULL) {
+    printk("%s: Unable to allocate table area", __func__);
+    goto cleanup;
+  }
+  memset(tableArea, 0, tableAreaSize);
+
+  tableLocation = tableArea;
+
+  /*
+   * The receive status table must be the first one since it has the strictest
+   * alignment requirements.
+   */
+  emacPs->rxMbufTable = (struct mbuf**)tableLocation;
+  tableLocation      += emacPs->rxUnitCount * sizeof(emacPs->rxMbufTable[0]);
+
+  emacPs->txMbufTable = (struct mbuf**)tableLocation;
+
+  PRINTK("%-40s: rxMbufTable = %08x\n", __func__, emacPs->rxMbufTable);
+  PRINTK("%-40s: txMbufTable = %08x\n", __func__, emacPs->txMbufTable);
+
+  /* Set interface data */
+  ifp = &emacPs->arpcom.ac_if;
+
+  ifp->if_softc          = emacPs;
+  ifp->if_unit           = (short)unitIdx;
+  ifp->if_name           = unitName;
+  ifp->if_mtu            = (ifCfg->mtu > 0) ? (u_long) ifCfg->mtu : ETHERMTU;
+  ifp->if_init           = eth_emacps_interface_init;
+  ifp->if_ioctl          = eth_emacps_interface_ioctl;
+  ifp->if_start          = eth_emacps_interface_start;
+  ifp->if_output         = ether_output;
+  //ifp->if_watchdog       = eth_emacps_interface_watchdog; /* RiC: Punt. */
+  ifp->if_flags          = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX;
+  ifp->if_snd.ifq_maxlen = ifqmaxlen;
+  ifp->if_timer          = 0;           /* Leave the watchdog stopped */
+
+  /* Create shared rx & tx tasks */
+  if ( (gEthEmacPsRxTask == 0) && (gEthEmacPsTxTask == 0) )
+  {
+    gEthEmacPsRxTask = rtems_bsdnet_newproc("ntrx", 4096, eth_emacps_receive_task,  emacPs);
+    gEthEmacPsTxTask = rtems_bsdnet_newproc("nttx", 4096, eth_emacps_transmit_task, emacPs);
+    gEthEmacPsErTask = rtems_bsdnet_newproc("nter", 4096, eth_emacps_error_task,    emacPs);
+  }
+
+  /* Change status */
+  ifp->if_flags |= IFF_RUNNING;
+  emacPs->state  = ETH_EMACPS_STATE_DOWN;
+
+  /* Attach the interface */
+  if_attach(ifp);
+  ether_ifattach(ifp);
+
+  PRINTK("%-40s: end\n", __func__);
+
+  return 1;
+
+cleanup:
+
+  PRINTK ("%-40s: cleanup\n", __func__);
+
+  eth_emacps_config_free_table_area(tableArea);
+
+  /* FIXME: Type */
+  free(unitName, (int) 0xdeadbeef);
+
+  PRINTK("%-40s: end\n", __func__);
+
+  return 0;
+}
+
+static int eth_emacps_detach(struct rtems_bsdnet_ifconfig *ifCfg)
+{
+  EthEmacPs* emacPs = (EthEmacPs*)ifCfg->drv_ctrl;
+
+  /* FIXME: Detach the interface from the upper layers? */
+
+  /* Module soft reset */
+  XEmacPs_Reset(&emacPs->instance);
+
+  return 0;
+}
+
+int zynq_eth_attach_detach(struct rtems_bsdnet_ifconfig *ifCfg,
+                           int                           attaching)
+{
+  /* FIXME: Return value */
+
+  if (attaching) {
+    return eth_emacps_attach(ifCfg);
+  } else {
+    return eth_emacps_detach(ifCfg);
+  }
+}
diff --git a/c/src/lib/libbsp/arm/zynq/startup/bspreset.c b/c/src/lib/libbsp/arm/zynq/startup/bspreset.c
new file mode 100644
index 0000000..f5aefcc
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/bspreset.c
@@ -0,0 +1,50 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Reset code.
+ */
+
+/*
+ * Copyright (c) 2009-2010 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdbool.h>
+
+#include <bspopts.h>
+#include <bsp/bootcard.h>
+#include <bsp.h>
+
+static void watchdog_reset(void)
+{
+#if 0
+  #ifdef ZYNQ_ENABLE_WATCHDOG_RESET
+    ZYNQ_TIMCLK_CTRL |= TIMCLK_CTRL_WDT;
+    zynq.wdt.mctrl   |= WDTTIM_MCTRL_M_RES1 | WDTTIM_MCTRL_M_RES2;
+    zynq.wdt.emr      = WDTTIM_EMR_MATCH_CTRL_SET(zynq.wdt.emr, 0x2);
+    zynq.wdt.ctrl    |= WDTTIM_CTRL_COUNT_ENAB;
+    zynq.wdt.match0   = 1;
+    zynq.wdt.counter  = 0;
+  #endif
+#endif
+}
+
+void bsp_reset( void)
+{
+  watchdog_reset();
+
+  while (true) {
+    /* Do nothing */
+  }
+}
diff --git a/c/src/lib/libbsp/arm/zynq/startup/bspstart.c b/c/src/lib/libbsp/arm/zynq/startup/bspstart.c
new file mode 100644
index 0000000..cc864b7
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/bspstart.c
@@ -0,0 +1,117 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Startup code.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/bspIo.h>
+#include <libchip/serial.h>
+
+#include <bsp.h>
+#include <bsp/bootcard.h>
+#include <bsp/irq-generic.h>
+#include <bsp/irq.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/uart.h>
+
+/* Defined in linkcmds linker script */
+LINKER_SYMBOL(MsgAreaBase);
+LINKER_SYMBOL(MsgAreaSize);
+
+
+/*
+ * Provide weak aliases so that RTEMS distribution builds
+ */
+static void _noopfun(void) {}
+
+
+void app_bsp_start(void)
+__attribute__(( weak, alias("_noopfun") ));
+
+void app_bsp_pretasking_hook(void)
+__attribute__(( weak, alias("_noopfun") ));
+
+void app_bsp_predriver_hook(void)
+__attribute__(( weak, alias("_noopfun") ));
+
+
+static void __bsp_outchar_to_memory(char c)
+{
+  static char* mab = (char*)MsgAreaBase;
+  static char* mb  = (char*)MsgAreaBase;
+
+  *mb++ = c;
+  if (mb >= &mab[(int)MsgAreaSize])  mb = mab;
+  *mb   = '\0';                     /* Overwrite next location to show EOM */
+
+  zynq_uart_output(c);
+}
+
+
+void bsp_start(void)
+{
+  /* Set the character output function;  The application may override it */
+  BSP_output_char = __bsp_outchar_to_memory;
+
+  printk("\n%s:\n  RTEMS %s, built on %s %s\n\n", __FILE__,
+         rtems_get_version_string(), __DATE__, __TIME__);
+
+  /* Initialize RTEMS IRQ system */
+  bsp_interrupt_initialize();
+
+  /* Do application-specific initialization.  An application can
+     provide this when it is linked against pre-built RTEM libraries */
+  app_bsp_start();
+}
+
+
+/*
+ *  BSP pretasking hook.  Called just before drivers are initialized.
+ *  Used to setup libc and install any BSP extensions.
+ *
+ *  Must not use libc (to do io) from here, since drivers are not yet
+ *  initialized.
+ */
+
+void bsp_pretasking_hook(void)
+{
+  /* Do application-specific initialization.  An application can
+     provide this when it is linked against pre-built RTEM libraries */
+  app_bsp_pretasking_hook();
+}
+
+
+/*
+ *  BSP predriver hook.  Called by boot_card() just before drivers are
+ *  initialized.  Clear out any stale interrupts here.
+ */
+void bsp_predriver_hook(void)
+{
+  /* Do application-specific initialization.  An application can
+     provide this when it is linked against pre-built RTEM libraries */
+  app_bsp_predriver_hook();
+}
diff --git a/c/src/lib/libbsp/arm/zynq/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/zynq/startup/bspstarthooks.c
new file mode 100644
index 0000000..1983af3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/bspstarthooks.c
@@ -0,0 +1,169 @@
+/**
+ * @file
+ *
+ * @ingroup zynq
+ *
+ * @brief Startup code.
+ */
+
+/*
+ *                              Copyright 2013
+ *                                     by
+ *                        The Board of Trustees of the
+ *                      Leland Stanford Junior University.
+ *
+ * See the associated software notice in the accompanying zynq.h header file.
+ */
+/*
+ * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/start.h>
+#include <bsp/mmu.h>
+#include <bsp/xtime_l.h>
+#include <bsp/linker-symbols.h>
+
+#ifdef ZYNQ_DISABLE_READ_WRITE_DATA_CACHE
+  #define ZYNQ_MMU_READ_WRITE_DATA ZYNQ_MMU_READ_WRITE
+#else
+  #define ZYNQ_MMU_READ_WRITE_DATA ZYNQ_MMU_READ_WRITE_CACHED
+#endif
+
+#ifdef ZYNQ_DISABLE_READ_ONLY_PROTECTION
+  #define ZYNQ_MMU_READ_ONLY_DATA  ZYNQ_MMU_READ_WRITE_CACHED
+  #define ZYNQ_MMU_CODE            ZYNQ_MMU_READ_WRITE_CACHED
+#else
+  #define ZYNQ_MMU_READ_ONLY_DATA  ZYNQ_MMU_READ_ONLY_CACHED
+  #define ZYNQ_MMU_CODE            ZYNQ_MMU_READ_ONLY_CACHED
+#endif
+
+void __cpu_init(void);
+
+
+static BSP_START_TEXT_SECTION void clear_bss(void)
+{
+  const int *end = (const int *) bsp_section_bss_end;
+  int       *out = (int *)       bsp_section_bss_begin;
+
+  /* Clear BSS */
+  while (out != end) {
+    *out = 0;
+    ++out;
+  }
+}
+
+#ifndef ZYNQ_DISABLE_MMU
+typedef struct {
+  uint32_t begin;
+  uint32_t end;
+  uint32_t flags;
+} zynq_mmu_config;
+
+static const BSP_START_DATA_SECTION zynq_mmu_config
+  mmu_config_table[] = {
+  {
+    .begin = (uint32_t) bsp_section_fast_text_begin,
+    .end   = (uint32_t) bsp_section_fast_text_end,
+    .flags = ZYNQ_MMU_CODE
+  }, {
+    .begin = (uint32_t) bsp_section_fast_data_begin,
+    .end   = (uint32_t) bsp_section_fast_data_end,
+    .flags = ZYNQ_MMU_READ_WRITE_DATA
+  }, {
+    .begin = (uint32_t) bsp_section_start_begin,
+    .end   = (uint32_t) bsp_section_start_end,
+    .flags = ZYNQ_MMU_CODE
+  }, {
+    .begin = (uint32_t) bsp_section_vector_begin,
+    .end   = (uint32_t) bsp_section_vector_end,
+    .flags = ZYNQ_MMU_READ_WRITE_CACHED
+  }, {
+    .begin = (uint32_t) bsp_section_text_begin,
+    .end   = (uint32_t) bsp_section_text_end,
+    .flags = ZYNQ_MMU_CODE
+  }, {
+    .begin = (uint32_t) bsp_section_rodata_begin,
+    .end   = (uint32_t) bsp_section_rodata_end,
+    .flags = ZYNQ_MMU_READ_ONLY_DATA
+  }, {
+    .begin = (uint32_t) bsp_section_data_begin,
+    .end   = (uint32_t) bsp_section_data_end,
+    .flags = ZYNQ_MMU_READ_WRITE_DATA
+  }, {
+    .begin = (uint32_t) bsp_section_bss_begin,
+    .end   = (uint32_t) bsp_section_bss_end,
+    .flags = ZYNQ_MMU_READ_WRITE_DATA
+  }, {
+    .begin = (uint32_t) bsp_section_work_begin,
+    .end   = (uint32_t) bsp_section_work_end,
+    .flags = ZYNQ_MMU_READ_WRITE_DATA
+  }, {
+    .begin = (uint32_t) bsp_section_stack_begin,
+    .end   = (uint32_t) bsp_section_stack_end,
+    .flags = ZYNQ_MMU_READ_WRITE_DATA
+  }
+};
+
+static BSP_START_TEXT_SECTION
+void set_translation_table_entries(const zynq_mmu_config *config)
+{
+  uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
+  uint32_t e = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
+
+  if (config->begin != config->end) {
+    while (i < e) {
+      zynq_set_translation_table_block((void*)config->begin,
+                                       (void*)config->end,
+                                       config->flags);
+      ++i;
+    }
+  }
+}
+
+static BSP_START_TEXT_SECTION
+void patch_mmu_table(void)
+{
+  size_t const n = sizeof(mmu_config_table) / sizeof(mmu_config_table[0]);
+  size_t       i = 0;
+
+  for (i = 0; i < n; ++i) {
+    set_translation_table_entries(&mmu_config_table[i]);
+  }
+}
+#endif
+
+
+BSP_START_TEXT_SECTION void bsp_start_hook_0(void)
+{
+  /* Complete CPU initialization */
+  __cpu_init();
+}
+
+
+BSP_START_TEXT_SECTION void bsp_start_hook_1(void)
+{
+  //stop_dma_activities();
+  //setup_uarts();
+
+  /* Reset and start Global Timer */
+  XTime_SetTime(0ULL);
+
+  /* Clear .bss section */
+  clear_bss();
+
+#ifndef ZYNQ_DISABLE_MMU
+  /* Patch the MMU table with some linker-calculated values */
+  patch_mmu_table();
+#endif
+}
diff --git a/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zc702 b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zc702
new file mode 100644
index 0000000..7c528ba
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zc702
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup zc702_linker
+ *
+ * @brief Linker support.
+ */
+
+/**
+ * @defgroup zc702_linker Application Memory Map
+ *
+ * @ingroup bsp_linker
+ *
+ * @brief Application memory map.
+ *
+ * <table>
+ *   <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
+ *   <tr><td>RAM_INT_0</td><td>0x00000000</td><td>192k</td></tr>
+ *   <tr><td>RAM_INT_1</td><td>0xFFFF0000</td><td>0xfe00</td></tr>
+ *   <tr><td>RAM_MMU</td><td>0x00100000</td><td>16k</td></tr>
+ *   <tr><td>RAM_EXT</td><td>0x00104000</td><td>1023M - 16k</td></tr>
+ * </table>
+ *
+ * <table>
+ *   <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr>
+ *   <tr><td>.start</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.vector</td><td>RAM_INT</td><td></td></tr>
+ *   <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.work</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.stack</td><td>RAM_INT</td><td></td></tr>
+ * </table>
+ */
+
+MEMORY
+{
+   RAM_INT_0   : ORIGIN = 0x00000000, LENGTH = 0x00030000
+   RAM_INT_1   : ORIGIN = 0xFFFF0000, LENGTH = 0x0000fe00
+   RAM_MMU     : ORIGIN = 0x00100000, LENGTH = 16k
+   RAM_EXT     : ORIGIN = 0x00104000, LENGTH = 0x3FF00000 - 0x00104000
+}
+
+INCLUDE linkcmds.zynq
diff --git a/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zedboard b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zedboard
new file mode 100644
index 0000000..8c8f476
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zedboard
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup zedboard_linker
+ *
+ * @brief Linker support.
+ */
+
+/**
+ * @defgroup zedboard_linker Application Memory Map
+ *
+ * @ingroup bsp_linker
+ *
+ * @brief Application memory map.
+ *
+ * <table>
+ *   <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr>
+ *   <tr><td>RAM_INT_0</td><td>0x00000000</td><td>192k</td></tr>
+ *   <tr><td>RAM_INT_1</td><td>0xFFFF0000</td><td>0xfe00</td></tr>
+ *   <tr><td>RAM_MMU</td><td>0x00100000</td><td>16k</td></tr>
+ *   <tr><td>RAM_EXT</td><td>0x00104000</td><td>511M - 16k</td></tr>
+ * </table>
+ *
+ * <table>
+ *   <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr>
+ *   <tr><td>.start</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.vector</td><td>RAM_INT</td><td></td></tr>
+ *   <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr>
+ *   <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.work</td><td>RAM_EXT</td><td></td></tr>
+ *   <tr><td>.stack</td><td>RAM_INT</td><td></td></tr>
+ * </table>
+ */
+
+MEMORY
+{
+   RAM_INT_0   : ORIGIN = 0x00000000, LENGTH = 0x00030000
+   RAM_INT_1   : ORIGIN = 0xFFFF0000, LENGTH = 0x0000fe00
+   RAM_MMU     : ORIGIN = 0x00100000, LENGTH = 16k
+   RAM_EXT     : ORIGIN = 0x00104000, LENGTH = 0x1FF80000 - 0x00104000
+}
+
+INCLUDE linkcmds.zynq
diff --git a/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zynq b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zynq
new file mode 100644
index 0000000..6abb8de
--- /dev/null
+++ b/c/src/lib/libbsp/arm/zynq/startup/linkcmds.zynq
@@ -0,0 +1,77 @@
+/**
+ * @file
+ *
+ * @ingroup zynq_linker
+ *
+ * @brief Linker support.
+ */
+
+REGION_ALIAS ("REGION_START",          RAM_EXT);
+REGION_ALIAS ("REGION_VECTOR",         RAM_EXT); /* _INT_0 */
+REGION_ALIAS ("REGION_TEXT",           RAM_EXT);
+REGION_ALIAS ("REGION_TEXT_LOAD",      RAM_EXT);
+REGION_ALIAS ("REGION_RODATA",         RAM_EXT);
+REGION_ALIAS ("REGION_RODATA_LOAD",    RAM_EXT);
+REGION_ALIAS ("REGION_DATA",           RAM_EXT);
+REGION_ALIAS ("REGION_DATA_LOAD",      RAM_EXT);
+REGION_ALIAS ("REGION_FAST_TEXT",      RAM_EXT);
+REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_FAST_DATA",      RAM_EXT);
+REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT);
+REGION_ALIAS ("REGION_MMU",            RAM_MMU);
+REGION_ALIAS ("REGION_BSS",            RAM_EXT);
+REGION_ALIAS ("REGION_WORK",           RAM_EXT);
+REGION_ALIAS ("REGION_STACK",          RAM_EXT); /* _INT_1 */
+
+bsp_vector_table_in_start_section = 1;
+
+bsp_stack_abt_size  = DEFINED (bsp_stack_abt_size)  ? bsp_stack_abt_size  : 0x400;
+bsp_stack_fiq_size  = DEFINED (bsp_stack_fiq_size)  ? bsp_stack_fiq_size  : 0x400;
+bsp_stack_irq_size  = DEFINED (bsp_stack_irq_size)  ? bsp_stack_irq_size  : 0x2000;
+bsp_stack_svc_size  = DEFINED (bsp_stack_svc_size)  ? bsp_stack_svc_size  : 0x800;
+bsp_stack_und_size  = DEFINED (bsp_stack_und_size)  ? bsp_stack_und_size  : 0x400;
+bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 0x2000;
+
+bsp_stack_align     = DEFINED (bsp_stack_align)     ? bsp_stack_align     : 0x10;
+bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M;
+
+/* Globals needed by the Xilinx routines */
+__abort_stack       = bsp_stack_abt_end;
+__fiq_stack         = bsp_stack_fiq_end;
+__irq_stack         = bsp_stack_irq_end;
+__supervisor_stack  = bsp_stack_svc_end;
+__undef_stack       = bsp_stack_und_end;
+__stack             = bsp_stack_main_end;
+
+_vector_table = DEFINED (bsp_vector_table_in_start_section) ? bsp_start_vector_table_begin : bsp_section_vector_begin;
+
+/* Place the MMU table at the beginning of external RAM so that space isn't   */
+/* lost by having to ALIGN(32768) somewhere in the middle of RAM.             */
+SECTIONS {
+         .mmu_tbl : {
+                  MMUTable = .;
+                  *(.mmu_tbl)
+         } > REGION_MMU AT > REGION_MMU
+}
+
+zynq_translation_table_base = MMUTable;         /* RTEMS must agree w/ Xilinx */
+
+/* Message area for capturing early printk output */
+/* Placed here to be easily findable with a debugger */
+MsgAreaBase = ORIGIN(RAM_EXT) + LENGTH(RAM_EXT);
+MsgAreaSize = DEFINED(MsgAreaSize) ? MsgAreaSize : 1M;
+
+INCLUDE linkcmds.armv4
+
+/* The default entry point (_start) is not the correct one for Zynq BSPs. */
+/* Allow some Xilinx code to run first by overriding it here.             */
+ENTRY (_boot)
+
+/* Put this here to keep it from being placed where the vector table wants    */
+/* to be, which is given by bsp_section_start_begin.  It would more logically */
+/* go between the vector table and the _start function.                       */
+SECTIONS {
+         .start   : {
+                  *(.boot)
+         } > REGION_START AT > REGION_START
+}
--
1.7.1




More information about the devel mailing list