[PATCH] ZYNQ BSP
Gedare Bloom
gedare at rtems.org
Sun Apr 21 15:44:55 UTC 2013
I have no real technical questions, but I do have three conceptual questions:
1) Would it make sense that someone might want to use the BSP without
using the Xilinx libraries?
2) Will the BSP compile without the libraries available? If not it
will be harder to verify that RTEMS changes do not break at least the
compilation of the BSP.
3) Should the disclaimer in the zynq.h be moved to a general file in
the root directory like SLAC.txt or something that we can point the
SLAC contributions toward? The SLAC.txt can then include whatever
authorship and sponsor disclaimers are required by your organization,
which can also be used for your past work with the virtex BSPs. Also,
does the "Maintenance of notices" include binary redistributions of
the software, and does the disclaimer of copyright supercede such an
obligation regardless?
-Gedare
On Sat, Apr 20, 2013 at 9:50 PM, Ric Claus <claus at slac.stanford.edu> wrote:
> ---
> 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
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel
More information about the devel
mailing list