[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, ®, 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, ®, 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