axiethernet: Add axiethernet_v5_0 and Deprecate axiethernet_v4_4

This patch Adds axiethernet_v5_0 and deprecates axiethernet_v4_4.

Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
Kedareswara rao Appana 2015-06-18 13:05:36 +05:30 committed by Nava kishore Manne
parent a01d2a94ac
commit 72d89bdf72
33 changed files with 22219 additions and 0 deletions

View file

@ -0,0 +1,48 @@
###############################################################################
#
# Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
# MODIFICATION HISTORY:
#
# 05/12/10 asa First Release
# 02/01/13 srt Added support for IPI designs (CR 698249)
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver axiethernet
OPTION supported_peripherals = (axi_ethernet_v[3-9]_[0-9][1-9]_[a-z] axi_ethernet_v[3-9]_[0-9] axi_ethernet_buffer);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 5.0;
OPTION NAME = axiethernet;
END driver

View file

@ -0,0 +1,700 @@
###############################################################################
#
# Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
# MODIFICATION HISTORY:
#
# 05/12/10 asa First Release based on the LL TEMAC driver tcl
# 01/07/13 srt Added C_PHYADDR configuration parameter to support SGMII mode
# 02/03/13 srt Added support for IPI designs (CR 698249)
# 02/14/13 srt Added support for Zynq (CR 681136)
# 04/24/13 srt Modified parameter *_SGMII_PHYADDR to *_PHYADDR, the config
# parameter C_PHYADDR applies to SGMII/1000BaseX modes of
# operation (CR 704195)
# 08/06/13 srt Added support to handle multiple instances of AxiEthernet
# FIFO interface (CR 721141)
# 06/08/14 adk Modified the driver tcl to handle the open/close of files
# properly (CR 810643)
# 29/10/14 adk Added support for generating parameters for SGMII/1000BaseX modes
# When IP is configured with the PCS/PMA core (CR 828796)
# 8/1/15 adk Fixed TCL errors when axiethernet is configured with the
# Axi stream fifo (CR 835605).
#
###############################################################################
#uses "xillib.tcl"
set periph_config_params 0
set periph_ninstances 0
proc init_periph_config_struct { deviceid } {
global periph_config_params
set periph_config_params($deviceid) [list]
}
proc get_periph_config_struct_fields { deviceid } {
global periph_config_params
return $periph_config_params($deviceid)
}
proc add_field_to_periph_config_struct { deviceid fieldval } {
global periph_config_params
lappend periph_config_params($deviceid) $fieldval
}
proc display_avb_warning_if_applicable { periph } {
set avb_param_val ""
set avb_param_val [::hsi::utils::get_param_value $periph C_AVB]
if { $avb_param_val == 1 } {
puts "*******************************************************************************\r\n"
puts "WARNING: Audio Video Bridging (AVB) functionality is ENABLED in the AXI Ethernet core."
puts "The AXI Ethernet driver does not support AVB functionality."
puts "Please refer to the System Integration section of the Ethernet AVB User Guide"
puts "http://www.xilinx.com/support/documentation/ip_documentation/eth_avb_endpoint_ug492.pdf for information on AXI-Ethernet AVB Driver integration.\r\n"
puts "*******************************************************************************\r\n"
}
}
# ------------------------------------------------------------------
# Given an Axi Ethernet peripheral, generate all the stuff required in
# the system include file.
#
# Given an Axi Ethernet which is an initiator on a
# Axi4 Stream interface, traverse the Axi4 Stream to the target side,
# figure out the peripheral type that is connected and
# put in appropriate defines. The peripheral on the other side
# can be AXI DMA or AXI Streaming FIFO.
#
# ------------------------------------------------------------------
proc xdefine_axiethernet_include_file {drv_handle file_name drv_string} {
global periph_ninstances
# Open include file
set file_handle [::hsi::utils::open_include_file $file_name]
# Get all peripherals connected to this driver
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
# ----------------------------------------------
# PART 1 - AXI Ethernet related parameters
# ----------------------------------------------
# Handle NUM_INSTANCES
set periph_ninstances 0
puts $file_handle "/* Definitions for driver [string toupper [get_property NAME $drv_handle]] */"
foreach periph $periphs {
init_periph_config_struct $periph_ninstances
incr periph_ninstances 1
}
puts $file_handle "\#define [::hsi::utils::get_driver_param_name $drv_string NUM_INSTANCES] $periph_ninstances"
close $file_handle
# Now print all useful parameters for all peripherals
set device_id 0
foreach periph $periphs {
#puts $file_handle ""
::hsi::utils::define_include_file $drv_handle "xparameters.h" "XAxiEthernet" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_TYPE" "C_TXCSUM" "C_RXCSUM" "C_PHY_TYPE" "C_TXVLAN_TRAN" "C_RXVLAN_TRAN" "C_TXVLAN_TAG" "C_RXVLAN_TAG" "C_TXVLAN_STRP" "C_RXVLAN_STRP" "C_MCAST_EXTEND" "C_STATS" "C_AVB" "C_PHYADDR"
set file_handle [::hsi::utils::open_include_file $file_name]
# Create canonical definitions
xdefine_temac_params_canonical $file_handle $periph $device_id
# Interrupt ID (canonical)
xdefine_temac_interrupt $file_handle $periph $device_id
generate_sgmii_params $drv_handle "xparameters.h"
display_avb_warning_if_applicable $periph
incr device_id
puts $file_handle "\n"
close $file_handle
}
# -------------------------------------------------------
# PART 2 -- AXIFIFO/AXIDMA Connection related parameters
# -------------------------------------------------------
set file_handle [::hsi::utils::open_include_file $file_name]
xdefine_axi_target_params $periphs $file_handle
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}
# ------------------------------------------------------------------
# Main generate function - called by the tools
# ------------------------------------------------------------------
proc generate {drv_handle} {
xdefine_axiethernet_include_file $drv_handle "xparameters.h" "XAxiEthernet"
xdefine_axiethernet_config_file "xaxiethernet_g.c" "XAxiEthernet"
}
# ---------------------------------------------------------------------------
# Given each AXI4 Stream peripheral which is an initiator on a AXI4
# Stream interface, traverse to the target side, figure out the peripheral
# type that is connected and put in appropriate defines.
# The peripheral on the other side can be AXI DMA or AXi Streaming FIFO.
#
# NOTE: This procedure assumes that each AXI4 Stream on each peripheral
# corresponds to a unique device id in the system and populates
# the global device config params structure accordingly.
# ---------------------------------------------------------------------------
proc xdefine_axi_target_params {periphs file_handle} {
global periph_ninstances
#
# First dump some enumerations on AXI_TYPE
#
puts $file_handle "/* AxiEthernet TYPE Enumerations */"
puts $file_handle "#define XPAR_AXI_FIFO 1"
puts $file_handle "#define XPAR_AXI_DMA 2"
puts $file_handle ""
set device_id 0
set validentry 0
# Get unique list of p2p peripherals
foreach periph $periphs {
set p2p_periphs [list]
set periph_name [string toupper [get_property NAME $periph]]
# Get all point2point buses for periph
set p2p_busifs_i [get_intf_pins -of_objects $periph -filter "TYPE==INITIATOR"]
puts $file_handle ""
puts $file_handle "/* Canonical Axi parameters for $periph_name */"
# Add p2p periphs
foreach p2p_busif $p2p_busifs_i {
set busif_name [string toupper [get_property NAME $p2p_busif]]
set conn_busif_handle [::hsi::utils::get_connected_intf $periph $busif_name]
if { [string compare -nocase $conn_busif_handle ""] == 0} {
continue
} else {
# if there is a single match, we know if it is FIFO or DMA
# no need for further iterations
set conn_busif_name [get_property NAME $conn_busif_handle]
set target_periph [get_cells -of_objects $conn_busif_handle]
set target_periph_type [get_property IP_NAME $target_periph]
if { [string compare -nocase $target_periph_type "tri_mode_ethernet_mac"] == 0 } {
continue
}
set tartget_per_name [get_property NAME $target_periph]
set target_periph_name [string toupper [get_property NAME $target_periph]]
set canonical_tag [string toupper [format "AXIETHERNET_%d" $device_id ]]
set validentry 1
break
}
}
if {$validentry == 1} {
if {$target_periph_type == "axi_fifo_mm_s"} {
#
# Handle the connection type (FIFO in this case)
#
set canonical_name [format "XPAR_%s_CONNECTED_TYPE" $canonical_tag]
puts $file_handle "#define $canonical_name XPAR_AXI_FIFO"
add_field_to_periph_config_struct $device_id $canonical_name
set axi_fifo_baseaddr [get_property CONFIG.C_BASEADDR $target_periph]
set canonical_name [format "XPAR_%s_CONNECTED_BASEADDR" $canonical_tag]
puts $file_handle [format "#define $canonical_name %s" $axi_fifo_baseaddr]
add_field_to_periph_config_struct $device_id $canonical_name
# FIFO Interrupts Handling
set int_pin [get_pins -of_objects [get_cells $tartget_per_name] INTERRUPT]
set intc_periph_type [::hsi::utils::get_connected_intr_cntrl $tartget_per_name $int_pin]
set intc_name [get_property IP_NAME $intc_periph_type]
if { $intc_name != [format "ps7_scugic"] } {
set int_id [::hsi::utils::get_port_intr_id [get_cells $tartget_per_name] $int_pin]
set canonical_name [format "XPAR_%s_CONNECTED_FIFO_INTR" $canonical_tag]
puts $file_handle [format "#define $canonical_name %d" $int_id]
add_field_to_periph_config_struct $device_id $canonical_name
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMARX_INTR 0xFF" $canonical_tag]
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMATX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $device_id 0xFF
add_field_to_periph_config_struct $device_id 0xFF
} else {
set canonical_name [format "XPAR_%s_CONNECTED_FIFO_INTR" $canonical_tag]
set temp [string toupper $int_pin]
puts $file_handle [format "#define $canonical_name XPAR_FABRIC_%s_%s_INTR" $target_periph_name $temp]
add_field_to_periph_config_struct $device_id $canonical_name
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMARX_INTR 0xFF" $canonical_tag]
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMATX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $device_id 0xFF
add_field_to_periph_config_struct $device_id 0xFF
}
}
if {$target_periph_type == "axi_dma"} {
set axi_dma_baseaddr [get_property CONFIG.C_BASEADDR $target_periph]
# Handle base address and connection type
set canonical_name [format "XPAR_%s_CONNECTED_TYPE" $canonical_tag]
puts $file_handle "#define $canonical_name XPAR_AXI_DMA"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "XPAR_%s_CONNECTED_BASEADDR" $canonical_tag]
puts $file_handle [format "#define $canonical_name %s" $axi_dma_baseaddr]
add_field_to_periph_config_struct $device_id $canonical_name
puts $file_handle [format "#define XPAR_%s_CONNECTED_FIFO_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $device_id 0xFF
set dmarx_signal [format "s2mm_introut"]
set dmatx_signal [format "mm2s_introut"]
xdefine_dma_interrupts $file_handle $target_periph $device_id $canonical_tag $dmarx_signal $dmatx_signal
}
incr device_id
}
if {$validentry !=1} {
puts "*******************************************************************************\r\n"
puts "The target Peripheral(Axi DMA or AXI FIFO) is not connected properly to the AXI Ethernet core."
puts "*******************************************************************************\r\n"
}
}
}
# ------------------------------------------------------------------
# This procedure creates XPARs that are canonical/normalized for the
# hardware design parameters. It also adds these to the Config table.
# ------------------------------------------------------------------
proc xdefine_temac_params_canonical {file_handle periph device_id} {
puts $file_handle "\n/* Canonical definitions for peripheral [string toupper [get_property NAME $periph]] */"
set canonical_tag [string toupper [format "XPAR_AXIETHERNET_%d" $device_id]]
# Handle device ID
set canonical_name [format "%s_DEVICE_ID" $canonical_tag]
puts $file_handle "\#define $canonical_name $device_id"
add_field_to_periph_config_struct $device_id $canonical_name
# Handle BASEADDR specially
set canonical_name [format "%s_BASEADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [::hsi::utils::get_param_value $periph C_BASEADDR]"
add_field_to_periph_config_struct $device_id $canonical_name
# Handle HIGHADDR specially
set canonical_name [format "%s_HIGHADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [::hsi::utils::get_param_value $periph C_HIGHADDR]"
set canonical_name [format "%s_TEMAC_TYPE" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_TYPE]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_TXCSUM" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_TXCSUM]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_RXCSUM" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_RXCSUM]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_PHY_TYPE" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_PHY_TYPE]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_TXVLAN_TRAN" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_TXVLAN_TRAN]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_RXVLAN_TRAN" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_RXVLAN_TRAN]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_TXVLAN_TAG" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_TXVLAN_TAG]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_RXVLAN_TAG" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_RXVLAN_TAG]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_TXVLAN_STRP" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_TXVLAN_STRP]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_RXVLAN_STRP" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_RXVLAN_STRP]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_MCAST_EXTEND" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_MCAST_EXTEND]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_STATS" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_STATS]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_AVB" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_AVB]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_ENABLE_SGMII_OVER_LVDS" $canonical_tag]
set value [::hsi::utils::get_param_value $periph C_ENABLE_LVDS]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct $device_id $canonical_name
set canonical_name [format "%s_PHYADDR" $canonical_tag]
set phyaddr [::hsi::utils::get_param_value $periph C_PHYADDR]
set value [::hsi::utils::convert_binary_to_decimal $phyaddr]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
}
# ------------------------------------------------------------------
# Create configuration C file as required by Xilinx drivers
# Use the config field list technique
# ------------------------------------------------------------------
proc xdefine_axiethernet_config_file {file_name drv_string} {
global periph_ninstances
set filename [file join "src" $file_name]
file delete $filename
set config_file [open $filename w]
::hsi::utils::write_c_header $config_file "Driver configuration"
puts $config_file "\#include \"xparameters.h\""
puts $config_file "\#include \"[string tolower $drv_string].h\""
puts $config_file "\n/*"
puts $config_file "* The configuration table for devices"
puts $config_file "*/\n"
puts $config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string]
puts $config_file "\{"
set start_comma ""
for {set i 0} {$i < $periph_ninstances} {incr i} {
puts $config_file [format "%s\t\{" $start_comma]
set comma ""
foreach field [get_periph_config_struct_fields $i] {
puts -nonewline $config_file [format "%s\t\t%s" $comma $field]
set comma ",\n"
}
puts -nonewline $config_file "\n\t\}"
set start_comma ",\n"
}
puts $config_file "\n\};\n"
close $config_file
}
# ------------------------------------------------------------------
# Find the two LocalLink DMA interrupts (RX and TX), and define
# the canonical constants in xparameters.h and the config table
# ------------------------------------------------------------------
proc xdefine_dma_interrupts {file_handle target_periph deviceid canonical_tag dmarx_signal dmatx_signal} {
set target_periph_name [string toupper [get_property NAME $target_periph]]
# First get the interrupt ports on this AXI peripheral
set interrupt_port [get_pins -of_objects $target_periph -filter {TYPE==INTERRUPT&&DIRECTION==O}]
if {$interrupt_port == ""} {
puts "Info: There are no AXIDMA Interrupt ports"
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMARX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $deviceid 0xFF
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMATX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $deviceid 0xFF
return
}
# For each interrupt port, find out the ordinal of the interrupt line
# as connected to an interrupt controller
set addentry 0
set dmarx "null"
set dmatx "null"
foreach intr_port $interrupt_port {
set interrupt_signal_name [get_property NAME $intr_port]
set intc_port [get_pins -of_objects $target_periph -filter {TYPE==INTERRUPT&&DIRECTION==O}]
# Make sure the interrupt signal was connected in this design. We assume
# at least one is. (could be a bug if user just wants polled mode)
if { $intc_port != "" } {
set found_intc ""
foreach intr_sink $intc_port {
set pname_type [::hsi::utils::get_connected_intr_cntrl $target_periph $intr_sink]
if {$pname_type != "chipscope_ila"} {
set special [get_property IP_TYPE $pname_type]
if {[string compare -nocase $special "INTERRUPT_CNTLR"] == 0} {
set found_intc $intr_sink
}
}
}
if {$found_intc == ""} {
puts "Info: DMA interrupt not connected to intc\n"
puts "Info: There are no AXIDMA Interrupt ports"
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMARX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $deviceid 0xFF
puts $file_handle [format "#define XPAR_%s_CONNECTED_DMATX_INTR 0xFF" $canonical_tag]
add_field_to_periph_config_struct $deviceid 0xFF
return
}
set intc_periph [get_cells -of_objects $found_intc]
set intc_periph_type [get_property IP_NAME $pname_type]
set intc_name [string toupper [get_property NAME $pname_type]]
} else {
puts "Info: $target_periph_name interrupt signal $interrupt_signal_name not connected"
continue
}
}
# A bit of ugliness here. The only way to figure the ordinal is to
# iterate over the interrupt lines again and see if a particular signal
# matches the original interrupt signal we were tracking.
# If it does, put out the XPAR
if { $intc_periph_type != [format "ps7_scugic"] } {
set rx_int_id [::hsi::utils::get_port_intr_id $target_periph $dmarx_signal]
set canonical_name [format "XPAR_%s_CONNECTED_DMARX_INTR" $canonical_tag]
puts $file_handle [format "#define $canonical_name %d" $rx_int_id]
add_field_to_periph_config_struct $deviceid $canonical_name
set tx_int_id [::hsi::utils::get_port_intr_id $target_periph $dmatx_signal]
set canonical_name [format "XPAR_%s_CONNECTED_DMATX_INTR" $canonical_tag]
puts $file_handle [format "#define $canonical_name %d" $tx_int_id]
add_field_to_periph_config_struct $deviceid $canonical_name
} else {
set addentry 2
}
# Now add to the config table in the proper order (RX first, then TX
if { $intc_periph_type == [format "ps7_scugic"] } {
set canonical_name [format "XPAR_%s_CONNECTED_DMARX_INTR" $canonical_tag]
puts $file_handle [format "#define $canonical_name XPAR_FABRIC_%s_S2MM_INTROUT_INTR" $target_periph_name]
add_field_to_periph_config_struct $deviceid $canonical_name
set canonical_name [format "XPAR_%s_CONNECTED_DMATX_INTR" $canonical_tag]
puts $file_handle [format "#define $canonical_name XPAR_FABRIC_%s_MM2S_INTROUT_INTR" $target_periph_name]
add_field_to_periph_config_struct $deviceid $canonical_name
}
if { $addentry == 1} {
# for some reason, only one DMA interrupt was connected (probably a bug),
# but fill in a dummy entry for the other (may be the wrong direction!)
puts "WARNING: only one SDMA interrupt line connected for $target_periph_name"
}
}
# ------------------------------------------------------------------------------------
# This procedure re-forms the AXI Ethernet interrupt ID XPAR constant and adds it to
# the driver config table. This Tcl needs to be careful of the order of the
# config table entries
# ------------------------------------------------------------------------------------
proc xdefine_temac_interrupt {file_handle periph device_id} {
#set mhs_handle [xget_hw_parent_handle $periph]
set periph_name [string toupper [get_property NAME $periph]]
# set up the canonical constant name
set canonical_name [format "XPAR_AXIETHERNET_%d_INTR" $device_id]
#
# In order to reform the XPAR for the interrupt ID, we need to hunt
# for the interrupt ID based on the interrupt signal name of the TEMAC
#
# First get the interrupt ports on this peripheral
set interrupt_port [::hsi::get_pins -of_objects $periph -filter {TYPE==INTERRUPT&&DIRECTION==O}]
if {$interrupt_port == ""} {
puts "Info: There are no AXI Ethernet Interrupt ports"
# No interrupts were connected, so add dummy entry to the config structure
puts $file_handle [format "#define $canonical_name 0xFF"]
add_field_to_periph_config_struct $device_id 0xFF
}
set addentry 0
# For each interrupt port, find out the ordinal of the interrupt line
# as connected to an interrupt controller
set interrupt_signal_name [get_property NAME $interrupt_port]
#set interrupt_signal [xget_hw_value $interrupt_port]
set intc_prt [::hsi::utils::get_sink_pins [get_pins -of_objects [get_cells $periph] INTERRUPT]]
# Make sure the interrupt signal was connected in this design. We assume
# at least one is. (could be a bug if user just wants polled mode)
if { $intc_prt != "" } {
set intc_periph [::hsi::utils::get_connected_intr_cntrl $periph [get_pins -of_objects [get_cells $periph] INTERRUPT] ]
if {$intc_periph == ""} {
puts "Info: Axi Ethernet interrupt not connected to intc\n"
# No interrupts were connected, so add dummy entry to the config structure
puts $file_handle [format "#define $canonical_name 0xFF"]
add_field_to_periph_config_struct $device_id 0xFF
return
}
set intc_periph_type [get_property IP_NAME $intc_periph]
set intc_name [string toupper [get_property NAME $intc_periph]]
} else {
puts "Info: $periph_name interrupt signal $interrupt_signal_name not connected"
# No interrupts were connected, so add dummy entry to the config structure
puts $file_handle [format "#define $canonical_name 0xFF"]
add_field_to_periph_config_struct $device_id 0xFF
return
}
# A bit of ugliness here. The only way to figure the ordinal is to
# iterate over the interrupt lines again and see if a particular signal
# matches the original interrupt signal we were tracking.
if { $intc_periph_type != [format "ps7_scugic"] } {
set ethernet_int_signal_name [get_pins -of_objects $periph INTERRUPT]
set int_id [::hsi::utils::get_port_intr_id $periph $ethernet_int_signal_name]
puts $file_handle "\#define $canonical_name $int_id"
add_field_to_periph_config_struct $device_id $canonical_name
set addentry 1
} else {
puts $file_handle [format "#define $canonical_name XPAR_FABRIC_%s_INTERRUPT_INTR" $periph_name]
add_field_to_periph_config_struct $device_id $canonical_name
set addentry 1
}
if { $addentry == 0 } {
# No interrupts were connected, so add dummy entry to the config structure
puts $file_handle [format "#define $canonical_name 0xFF"]
add_field_to_periph_config_struct $device_id 0xFF
}
}
proc generate_sgmii_params {drv_handle file_name} {
set file_handle [::hsi::utils::open_include_file $file_name]
set ips [get_cells "*"]
foreach ip $ips {
set periph [get_property IP_NAME $ip]
if { [string compare -nocase $periph "gig_ethernet_pcs_pma"] == 0} {
set PhyStandard [get_property CONFIG.Standard $ip]
}
}
foreach ip $ips {
set periph [get_property IP_NAME $ip]
if { [string compare -nocase $periph "axi_ethernet_buffer"] == 0} {
set phya [is_gige_pcs_pma_ip_present $ip]
if { $phya == 0} {
close $file_handle
return 0
}
if { $PhyStandard == "1000BASEX" } {
puts $file_handle "/* Definitions related to PCS PMA PL IP*/"
puts $file_handle "\#define XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT 1"
puts $file_handle "\#define XPAR_PCSPMA_1000BASEX_PHYADDR $phya"
puts $file_handle "\n/******************************************************************/\n"
} else {
puts $file_handle "/* Definitions related to PCS PMA PL IP*/"
puts $file_handle "\#define XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT 1"
puts $file_handle "\#define XPAR_PCSPMA_SGMII_PHYADDR $phya"
puts $file_handle "\n/******************************************************************/\n"
}
}
}
close $file_handle
}
proc is_gige_pcs_pma_ip_present {slave} {
set port_value 0
set phy_addr 0
set ipconv 0
set ips [get_cells "*"]
set enetipinstance_name [get_property IP_NAME $slave]
foreach ip $ips {
set periph [get_property IP_NAME $ip]
if { [string compare -nocase $periph "gig_ethernet_pcs_pma"] == 0} {
set sgmii_param [get_property CONFIG.c_is_sgmii $ip]
set PhyStandarrd [get_property CONFIG.Standard $ip]
if {$sgmii_param == true || $PhyStandarrd == "1000BASEX"} {
set ipconv $ip
}
break
}
}
if { $ipconv != 0 } {
set port_value [get_pins -of_objects [get_nets -of_objects [get_pins -of_objects $ipconv gmii_txd]]]
if { $port_value != 0 } {
if { [string compare -nocase $enetipinstance_name "axi_ethernet_buffer"] == 0} {
set phyaddr [::hsi::utils::get_param_value $ipconv C_PHYADDR]
set phy_addr [::hsi::utils::convert_binary_to_decimal $phyaddr]
if {[llength $phy_addr] == 0} {
set phy_addr 0
}
}
}
}
return $phy_addr
}

View file

@ -0,0 +1,47 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include "xstatus.h"
#include "xil_types.h"
#include "xparameters.h"
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#else
#define INTC XScuGic
#endif
int AxiEthernetFifoIntrExample(INTC * IntcInstancePtr,
XAxiEthernet * AxiEthernetInstancePtr,
XLlFifo * FifoInstancePtr,
u16 AxiEthernetDeviceId, u16 FifoDeviceId,
u16 AxiEthernetIntrId, u16 FifoIntrId);

View file

@ -0,0 +1,36 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include "xstatus.h"
#include "xil_types.h"
int AxiEthernetPolledExample(u16 AxiEthernetDeviceId, u16 FifoDeviceId);

View file

@ -0,0 +1,49 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include "xstatus.h"
#include "xil_types.h"
#include "xparameters.h"
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#else
#define INTC XScuGic
#endif
int AxiEthernetSgDmaIntrExample(INTC * IntcInstancePtr,
XAxiEthernet * AxiEthernetInstancePtr,
XAxiDma * DmaInstancePtr,
u16 AxiEthernetDeviceId,
u16 AxiDmaDeviceId, u16 AxiEthernetIntrId,
u16 DmaRxIntrId, u16 DmaTxIntrId);

View file

@ -0,0 +1,416 @@
###############################################################################
#
# Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
# MODIFICATION HISTORY:
#
# Ver Who Date Changes
# -------- ------ -------- ----------------------------------------------------
# 1.00.a asa 05/12/10 First Release
# 4.0 adk 10/12/13 Updated as per the New Tcl API's
# 4.1 adk 21/4/14 Fixed the CR:780537 Modified the get_dma_info proc
# logic as appropriate(In case of multiple dma's in the
# system some connected to ethernet some not).
#
###############################################################################
# -----------------------------------------------------------------
# Software Project Types (swproj):
# 0 : MemoryTest - Calls basic memorytest routines from common driver dir
# 1 : PeripheralTest - Calls any existing polled_example and/or selftest
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# TCL Procedures:
# -----------------------------------------------------------------
proc gen_include_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst]
set dmaType [get_dma_type $mhsinst]
if {$ifintr == 1} {
set inc_file_lines {xaxiethernet.h xaxiethernet_example.h}
if {$dmaType == 1} {
append inc_file_lines " xllfifo.h"
append inc_file_lines " axiethernet_header.h"
append inc_file_lines " axiethernet_fifo_intr_header.h"
}
if {$dmaType == 3} {
append inc_file_lines " xaxidma.h"
append inc_file_lines " axiethernet_intr_header.h"
}
} else {
if {$dmaType == 1} {
set inc_file_lines {xaxiethernet.h xaxiethernet_example.h axiethernet_header.h}
} else {
return ""
}
}
return $inc_file_lines
}
}
proc gen_src_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst]
set dmaType [get_dma_type $mhsinst]
if {$ifintr == 1} {
if {$dmaType == 1} {
set inc_file_lines {examples/xaxiethernet_example.h examples/xaxiethernet_example_polled.c examples/xaxiethernet_example_util.c examples/xaxiethernet_example_intr_fifo.c data/axiethernet_header.h data/axiethernet_fifo_intr_header.h}
} elseif {$dmaType == 3} {
set inc_file_lines {examples/xaxiethernet_example.h examples/xaxiethernet_example_util.c examples/xaxiethernet_example_intr_sgdma.c data/axiethernet_intr_header.h}
}
} else {
if {$dmaType == 1} {
set inc_file_lines {examples/xaxiethernet_example.h examples/xaxiethernet_example_polled.c examples/xaxiethernet_example_util.c data/axiethernet_header.h}
} else {
return ""
}
}
return $inc_file_lines
}
}
proc gen_testfunc_def {swproj mhsinst} {
return ""
}
proc gen_init_code {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set ipname [get_property NAME $mhsinst]
set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst]
if {$ifintr == 1} {
set dmaType [get_dma_type $mhsinst]
set decl " static XAxiEthernet ${ipname}_AxiEthernet;"
# FIFO
if {$dmaType == 1} {
set fifo_ipname [get_fifo_info $mhsinst "name"]
append decl "
static XLlFifo ${fifo_ipname}_AxiFifo;
"
}
# DMA
if {$dmaType == 3} {
append decl "
static XAxiDma ${ipname}_AxiDma;
"
}
set inc_file_lines $decl
return $inc_file_lines
}
}
return ""
}
proc gen_testfunc_call {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
set ipname [get_property NAME $mhsinst]
set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
set stdout [get_property CONFIG.STDOUT [get_os]]
if { $stdout == "" || $stdout == "none" } {
set hasStdout 0
} else {
set hasStdout 1
}
set dma [get_dma_type $mhsinst]
set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst]
set fifo_deviceid [get_fifo_info $mhsinst "id"]
set fifo_ipname [get_fifo_info $mhsinst "name"]
set dma_deviceid [get_dma_info $mhsinst "id"]
set dma_ipname [get_dma_info $mhsinst "name"]
if {$ifintr == 1} {
set intr_pin_name [get_pins -of_objects [get_cells $ipname] INTERRUPT]
set intcname [::hsi::utils::get_connected_intr_cntrl $ipname $intr_pin_name]
set intcvar intc
set proc [get_property IP_NAME [get_cells [get_sw_processor]]]
}
if { $dma == 1 } {
set type "Fifo"
}
if { $dma == 3 } {
set type "SgDma"
}
set testfunc_call ""
# BEGIN: FIFO
if { $dma == 1 } {
append testfunc_call "
{
int Status;
"
if {${hasStdout} == 1} {
append testfunc_call "
print(\"\\r\\n Running AxiEthernetPolledExample() for ${ipname}...\\r\\n\");
"
}
append testfunc_call "
Status = AxiEthernetPolledExample( ${deviceid},
${fifo_deviceid} );
"
if {${hasStdout} == 1} {
append testfunc_call "
if (Status == 0) {
print(\"AxiEthernetPolledExample PASSED\\r\\n\");
}
else {
print(\"AxiEthernetPolledExample FAILED\\r\\n\");
}
"
}
append testfunc_call "
}
"
}
# END: FIFO
# BEGIN: DMA
if { $dma == 3 } {
append testfunc_call "
/* AxiEthernetPolledExample does not support AXI DMA */
"
}
# END: DMA
# BEGIN: INTERRUPT
if { ${ifintr} == 1 } {
# AXIETHERNET
if {
$proc == "microblaze"
} then {
set intr_id "XPAR_${intcname}_${ipname}_${intr_pin_name}_INTR"
} else {
set intr_id "XPAR_FABRIC_${ipname}_${intr_pin_name}_INTR"
}
set intr_id [string toupper $intr_id]
# BEGIN: FIFO & INTERRUPT
if {$dma == 1} {
# AXIFIFO
if {
$proc == "microblaze"
} then {
set fifo_intr_id "XPAR_${intcname}_${fifo_ipname}_${intr_pin_name}_INTR"
} else {
set fifo_intr_id "XPAR_FABRIC_${fifo_ipname}_${intr_pin_name}_INTR"
}
set fifo_intr_id [string toupper $fifo_intr_id]
append testfunc_call "
{
int Status;
"
if {${hasStdout} == 1} {
append testfunc_call "
print(\"\\r\\nRunning AxiEthernet${type}IntrExample() for ${ipname}...\\r\\n\");
"
}
append testfunc_call "
Status = AxiEthernet${type}IntrExample(&${intcvar}, &${ipname}_AxiEthernet,
&${fifo_ipname}_AxiFifo,
${deviceid},
${fifo_deviceid},
${intr_id},
${fifo_intr_id});
"
if {${hasStdout} == 1} {
append testfunc_call "
if(Status == 0) {
print(\"AxiEthernet Interrupt Test PASSED.\\r\\n\");
}
else {
print(\"AxiEthernet Interrupt Test FAILED.\\r\\n\");
}
"
}
append testfunc_call "
}
"
}
# END: FIFO & INTERRUPT
# BEGIN: DMA & INTERRUPT
if {$dma == 3} {
# DMA
set dmaDriverInst "${ipname}_AxiDma"
set dmaRxIntrId "XPAR_AXIETHERNET_0_CONNECTED_DMARX_INTR"
set dmaTxIntrId "XPAR_AXIETHERNET_0_CONNECTED_DMATX_INTR"
append testfunc_call "
{
int Status;
"
if {${hasStdout} == 1} {
append testfunc_call "
print(\"\\r\\nRunning AxiEthernet${type}IntrExample() for ${ipname}...\\r\\n\");
"
}
append testfunc_call "
Status = AxiEthernet${type}IntrExample(&${intcvar}, &${ipname}_AxiEthernet,
&${dmaDriverInst},
${deviceid},
${dma_deviceid},
${intr_id},
${dmaRxIntrId},
${dmaTxIntrId});
"
if {${hasStdout} == 1} {
append testfunc_call "
if (Status == 0) {
print(\"AxiEthernet Interrupt Test PASSED.\\r\\n\");
}
else {
print(\"AxiEthernet Interrupt Test FAILED.\\r\\n\");
}
"
}
append testfunc_call "
}"
}
# END: DMA & INTERRUPT
}
# END: INTERRUPT
return $testfunc_call
}
proc get_fifo_info {mhsHandle type} {
set ipinst_list [get_cells $mhsHandle "*"]
foreach ipinst $ipinst_list {
set coreName [get_property IP_NAME $ipinst]
set instName [get_property NAME $ipinst]
if {[string compare -nocase $coreName "axi_fifo_mm_s"] == 0} {
if {[string compare -nocase $type "id"] == 0} {
set deviceid [::hsi::utils::get_ip_param_name $ipinst "DEVICE_ID"]
return $deviceid
}
if {[string compare -nocase $type "name"] == 0} {
return $instName
}
}
}
}
proc get_dma_info {mhsinst type} {
set ipinst_list [get_cells $mhsinst "*"]
set p2p_busifs_i [get_intf_pins -of_objects $mhsinst -filter "TYPE==INITIATOR"]
# Add p2p periphs
foreach p2p_busif $p2p_busifs_i {
set busif_name [string toupper [get_property NAME $p2p_busif]]
set conn_busif_handle [::hsi::utils::get_connected_intf $mhsinst $busif_name]
if { [string compare -nocase $conn_busif_handle ""] == 0} {
continue
} else {
# if there is a single match, we know if it is FIFO or DMA
# no need for further iterations
set conn_busif_name [get_property NAME $conn_busif_handle]
set target_periph [get_cells -of_objects $conn_busif_handle]
set target_periph_type [get_property IP_NAME $target_periph]
if { [string compare -nocase $target_periph_type "tri_mode_ethernet_mac"] == 0 } {
continue
}
set target_periph_name [string toupper [get_property NAME $target_periph]]
set instName [get_property NAME $target_periph]
if {[string compare -nocase $target_periph_type "axi_dma"] == 0} {
if {[string compare -nocase $type "id"] == 0} {
set deviceid [::hsi::utils::get_ip_param_name $target_periph "DEVICE_ID"]
return $deviceid
}
if {[string compare -nocase $type "name"] == 0} {
return $instName
}
}
}
}
}
proc get_dma_type {mhsinst} {
set dma_deviceid [get_dma_info $mhsinst "id"]
if { $dma_deviceid != "" } {
set dma 3
} else {
set dma 1
}
return $dma
}

View file

@ -0,0 +1,5 @@
xaxiethernet_example_polled.c=xemacps_example_util.c,xaxiethernet_example_util.c,xaxiethernet_example.h
xaxiethernet_example_intr_sgdma.c=xemacps_example_util.c,xaxiethernet_example_util.c,xaxiethernet_example.h
xaxiethernet_example_intr_fifo.c=xemacps_example_util.c,xaxiethernet_example_util.c,xaxiethernet_example.h
xaxiethernet_example_extmulticast.c=xemacps_example_util.c,xaxiethernet_example_util.c,xaxiethernet_example.h
xaxiethernet_example_extvlan.c=xemacps_example_util.c,xaxiethernet_example_util.c,xaxiethernet_example.h

View file

@ -0,0 +1,742 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xavb.c
*
* The top level c file for the AVB driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_io.h"
#include "xil_assert.h"
#include "xenv.h"
#include "xavb_hw.h"
#include "xavb.h"
#include "xparameters.h"
#include "stdio.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
extern XAvb_Config XAvb_ConfigTable[];
extern volatile u8 EchoPTPFramesReceived;
/************************** Function Prototypes ******************************/
static void XAvb_StubHandler(void *CallBackRef, u32 TimestampsUncertain);
/*****************************************************************************/
/*
* Mandatory Device Driver Functions
*/
/****************************************************************************/
/**
*
* A function to initialise variables in the data structure records
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
* @param ConfigPtr is the Configuration Pointer
* @param EffectiveAddress is the base address of the Configuration Pointer
*
* @return
* - XST_SUCCESS if initialization was successful
* - XST_DEVICE_NOT_FOUND if device configuration information was not found
* for a device with the supplied device ID.*
* @note None.
*
*****************************************************************************/
XStatus XAvb_CfgInitialize(XAvb *InstancePtr,
XAvb_Config *ConfigPtr,
u32 EffectiveAddress) {
Xil_AssertNonvoid(InstancePtr != NULL);
/** The component is not yet ready to use */
InstancePtr->IsReady = 0;
/** Clear instance memory */
memset(InstancePtr, 0, sizeof(XAvb));
memcpy(&InstancePtr->Config, ConfigPtr, sizeof(XAvb_Config));
/**
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
/**
* Populate Base Address field using the base address value in the
* configuration structure.
*/
InstancePtr->Config.BaseAddress = EffectiveAddress;
/**
* Indicate the component is now ready to use.
*/
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
/**
* Set the callback handler to a stub
*/
InstancePtr->GMDiscHandler = XAvb_StubHandler;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function resets all of the AVB device driver functions to the start-up
* (reset) defaults.
*
* @param InstancePtr is a pointer to the Xavb instance to be worked on.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XAvb_Reset(XAvb * InstancePtr)
{
/** Assert bad arguments and conditions */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/**
* Perform a Software Reset of the AVB Core.
* This will reset both the transmitter and receiver paths.
* The RTC counter is not reset here.
*/
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_SW_RESET_OFFSET,
XAVB_SW_RESET_TX_AND_RX_PATHS);
/**
* Set IEEE specification default values in the device's data structure
*/
xil_printf("\r\n*** XAvb_Reset() : Call XAvb_BecomeRtcMaster() *** \r\n");
XAvb_BecomeRtcMaster(InstancePtr,0);
XAvb_ChangePeerASCapability(InstancePtr, 0);
InstancePtr->PtpIsRunning = 0;
InstancePtr->PtpRecords.LinkDelay = 0;
InstancePtr->SignallingFrameData.SyncIntervalDuration =
XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_SYNC_INTERVAL);
InstancePtr->SignallingFrameData.LinkDelayIntervalDuration =
XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_PDELAY_REQ_INTERVAL);
InstancePtr->SignallingFrameData.AnnounceIntervalDuration =
XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_ANNOUNCE_INTERVAL);
InstancePtr->latestMDSyncReceive.SyncIntervalDuration =
XAvb_ConvertLogMeanToDuration(XAVB_DEFAULT_LOG_MEAN_SYNC_INTERVAL);
/** Update logMeanMessageInterval in the pre-loaded TX SYNC message buffer */
XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress,
XAVB_PTP_TX_SYNC_OFFSET,
InstancePtr->SignallingFrameData.SyncIntervalDuration);
/** Update logMeanMessageInterval in the pre-loaded TX FOLLOW_UP message buffer */
XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress,
XAVB_PTP_TX_FOLLOW_UP_OFFSET,
InstancePtr->SignallingFrameData.SyncIntervalDuration);
/** Update logMeanMessageInterval in the pre-loaded TX PDELAYREQ message buffer */
XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress,
XAVB_PTP_TX_PDELAYREQ_OFFSET,
InstancePtr->SignallingFrameData.LinkDelayIntervalDuration);
/** Update logMeanMessageInterval in the pre-loaded TX ANNOUNCE message buffer */
XAvb_UpdateLogMeanMessageInterval(InstancePtr->Config.BaseAddress,
XAVB_PTP_TX_ANNOUNCE_OFFSET,
InstancePtr->SignallingFrameData.AnnounceIntervalDuration);
/**
* Initialise other driver variables in the device's data structure
*/
InstancePtr->PtpCounters.RxPtpHardPointer = 0;
InstancePtr->PtpCounters.RxPtpSoftPointer = 0xFF;
InstancePtr->PtpCounters.CounterSyncInterval = 0;
InstancePtr->PtpCounters.CounterLinkDelayInterval = 0;
InstancePtr->PtpCounters.CounterAnnounceInterval = 0;
InstancePtr->PtpCounters.CounterSyncEvents = 0;
InstancePtr->StateMachineData.lostResponses = 0;
InstancePtr->StateMachineData.rcvdPDelayResp = 0;
InstancePtr->StateMachineData.rcvdPDelayRespFollowUp = 0;
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\n** XAvb_Reset(): PTP Driver Reset **");
#endif
}
/*
* Device Specific Driver Functions
*/
/*****************************************************************************/
/**
*
* This function will start the PTP drivers running.
*
* @param InstancePtr is a pointer to the Xavb instance to be worked on.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XAvb_Start(XAvb * InstancePtr)
{
/** Assert bad arguments and conditions */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/** Re-run the BMCA algorithm with the current PTP buffer Announce Packet */
XAvb_DecodeTxAnnounceFrame(InstancePtr);
/** Set to PTP running in the PTP data structure */
InstancePtr->PtpIsRunning = 1;
/** Assume that the Peer is not AS capable until it replies to a pDelay_Req
* frame */
XAvb_ChangePeerASCapability(InstancePtr, 0);
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\n** XAvb_Start(): Starting PTP **");
#endif
}
/*****************************************************************************/
/**
*
* This function will stop the PTP drivers from running.
*
* @param InstancePtr is a pointer to the Xavb instance to be worked on.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XAvb_Stop(XAvb * InstancePtr)
{
/** Assert bad arguments and conditions */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\n** XAvb_Stop(): PTP STOPPED **");
#endif
XAvb_Reset(InstancePtr);
}
/****************************************************************************/
/**
*
* The Interrupt subroutine for the "interruptPtpTimer" signal. This interrupt
* fires reguarly on a 1/128 second period (based on the RTC).
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_PtpTimerInterruptHandler(XAvb * InstancePtr) {
/** Clear Interrupt */
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_CLEAR_INT_OFFSET,
XAVB_RTC_CLEAR_INT_MASK);
/** If PTP functions are marked as not running, then take no further action */
if (InstancePtr->PtpIsRunning == 1) {
/** If the Link Partner is not AS capable, then take no further action */
if (InstancePtr->PeerASCapable == 1) {
/** If a Master, then initiate Sync Frames and Announce frames at the
* correct intervals
*/
if (InstancePtr->CurrentBmc.IAmTheRtcMaster == 1) {
/** Master will initiate a Sync Frame when the SyncIntervalDuration
* expires (SyncIntervalDuration is used to count/time the duration)
* - unless a Signalling frame has told us not to send Sync Frames
*/
if ((InstancePtr->SignallingFrameData.SyncIntervalDuration != XAVB_PKT_TYPE_DISABLED) &&
(InstancePtr->PtpCounters.CounterSyncInterval >=
(InstancePtr->SignallingFrameData.SyncIntervalDuration-1))) {
XAvb_MasterSendSync(InstancePtr);
InstancePtr->PtpCounters.CounterSyncInterval = 0;
/** Following a Sync Frame, a Follow Up frame should always be sent
*/
XAvb_MasterSendFollowUp(InstancePtr);
} else {
InstancePtr->PtpCounters.CounterSyncInterval
= InstancePtr->PtpCounters.CounterSyncInterval + 1;
}
/** Master will initiate an Announce Frame when the
* AnnounceIntervalDuration expires (CounterAnnounceInterval is used
* to count/time the duration)
* - unless a Signalling frame has told us not to send Announce Frames
*/
if ((InstancePtr->SignallingFrameData.AnnounceIntervalDuration != XAVB_PKT_TYPE_DISABLED) &&
(InstancePtr->PtpCounters.CounterAnnounceInterval >=
(InstancePtr->SignallingFrameData.AnnounceIntervalDuration-1))) {
XAvb_MasterSendAnnounce(InstancePtr);
InstancePtr->PtpCounters.CounterAnnounceInterval = 0;
} else {
InstancePtr->PtpCounters.CounterAnnounceInterval
= InstancePtr->PtpCounters.CounterAnnounceInterval + 1;
}
/** If a Slave, monitor Announce/Sync Packet reception from the Master */
} else {
/** Timeout for Announce Packet reception: XAVB_ANNOUNCE_RECEIPT_TIMEOUT
* The AnnounceIntervalDuration is stored with the GrandMaster BMCA data
* as it is captured from the last Announce frame that was received.
*/
if (InstancePtr->PtpCounters.CounterAnnounceInterval >=
((InstancePtr->CurrentBmc.AnnounceIntervalDuration-1) *
XAVB_ANNOUNCE_RECEIPT_TIMEOUT) ) {
#ifdef XAVB_DEBUG_LEVEL1
xil_printf("XAVB_ANNOUNCE_RECEIPT_TIMEOUT: Becoming GM! CounterAnnounceInterval = %d\r\n", InstancePtr->PtpCounters.CounterAnnounceInterval);
#endif
InstancePtr->PtpCounters.CounterAnnounceInterval = 0;
/** No Announce received from GM for timeout interval: we become the master */
xil_printf("\r\n*** Announce timeout : Call XAvb_BecomeRtcMaster() *** \r\n");
XAvb_BecomeRtcMaster(InstancePtr,0);
} else {
InstancePtr->PtpCounters.CounterAnnounceInterval
= InstancePtr->PtpCounters.CounterAnnounceInterval + 1;
}
/** Timeout for Sync Packet reception: XAVB_SYNC_RECEIPT_TIMEOUT *
* The SyncIntervalDuration is stored with the Received Sync data
* as it is captured from the last Sync frame that was received.
*/
if( InstancePtr->PtpCounters.CounterSyncInterval >=
((InstancePtr->latestMDSyncReceive.SyncIntervalDuration-1) *
XAVB_SYNC_RECEIPT_TIMEOUT) ) {
#ifdef XAVB_DEBUG_LEVEL1
xil_printf("\r\nXAVB_SYNC_RECEIPT_TIMEOUT: Becoming GM! CounterSyncInterval = %d\r\n", InstancePtr->PtpCounters.CounterSyncInterval);
xil_printf("\r\nXAVB_SYNC_RECEIPT_TIMEOUT: SyncIntervalDuration = %d\r\n", InstancePtr->SignallingFrameData.SyncIntervalDuration);
#endif
InstancePtr->PtpCounters.CounterSyncInterval = 0;
/** No Syncs received from GM for timeout interval: we become
* the master */
xil_printf("\r\n*** Sync Timeout : Call XAvb_BecomeRtcMaster() *** \r\n");
XAvb_BecomeRtcMaster(InstancePtr,0);
} else {
InstancePtr->PtpCounters.CounterSyncInterval
= InstancePtr->PtpCounters.CounterSyncInterval + 1;
}
}
}
/** Both Master and Slave will initiate a link delay measurement when the
* LinkDelayIntervalDuration expires (LinkDelayIntervalDuration is used to
* count/time the duration)
* - unless a Signalling frame has told us not to send PdelayReq Frames
*/
if ((InstancePtr->SignallingFrameData.LinkDelayIntervalDuration != XAVB_PKT_TYPE_DISABLED) &&
(InstancePtr->PtpCounters.CounterLinkDelayInterval >=
(InstancePtr->SignallingFrameData.LinkDelayIntervalDuration-1))) {
/** Check to see if we've received PDelayResp and
* PDelayRespFollowUp messages since the last PDelayReq was
* sent */
if( InstancePtr->StateMachineData.rcvdPDelayResp &&
InstancePtr->StateMachineData.rcvdPDelayRespFollowUp ) {
InstancePtr->StateMachineData.lostResponses = 0;
} else {
InstancePtr->StateMachineData.lostResponses++;
}
if( InstancePtr->StateMachineData.lostResponses >= XAVB_ALLOWED_LOST_RESPONSES ) {
/** the peer is no longer ASCapable */
XAvb_ChangePeerASCapability(InstancePtr, 0);
xil_printf("\r\n** XAvb_PtpTimerInterruptHandler(): The peer is no longer ASCapable **");
xil_printf("\r\n** XAvb_PtpTimerInterruptHandler(): StateMachineData.lostResponses >= %d **",
XAVB_ALLOWED_LOST_RESPONSES);
/** avoid potential overflow */
InstancePtr->StateMachineData.lostResponses = XAVB_ALLOWED_LOST_RESPONSES;
}
XAvb_SendPDelayReq(InstancePtr);
InstancePtr->StateMachineData.rcvdPDelayResp = 0;
InstancePtr->StateMachineData.rcvdPDelayRespFollowUp = 0;
InstancePtr->PtpCounters.CounterLinkDelayInterval = 0;
} else {
InstancePtr->PtpCounters.CounterLinkDelayInterval
= InstancePtr->PtpCounters.CounterLinkDelayInterval + 1;
}
} /** end of 'if (InstancePtr->PtpIsRunning == 1)' */
}
/****************************************************************************/
/**
*
* The Interrupt subroutine for the "interrupt_ptp_rx" signal. This interrupt
* fires whenever a PTP frame has been received. The main function is to
* identify, decode, and act on the type of PTP frame received.
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_PtpRxInterruptHandler(XAvb * InstancePtr) {
#ifdef DEBUG_XAVB_LEVEL1
u32 x = 0;
#endif
u32 MessageType = 0;
u32 PtpFrameBaseAddr = 0;
/** RxPtpHardPointer indicates the bin location of the last frame to be
* received and written into the Rx PTP buffer in hardware. This read will
* also clear the interrupt.*/
InstancePtr->PtpCounters.RxPtpHardPointer
= (XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_PTP_RX_CONTROL_OFFSET)
& XAVB_PTP_RX_PACKET_FIELD_MASK) >> 8;
/** If PTP functions are marked as not running, then take no further action */
if (InstancePtr->PtpIsRunning == 1) {
/** RxPtpSoftPointer indicates the bin location of the last frame to be
* processed in software. */
while ( (InstancePtr->PtpCounters.RxPtpSoftPointer & 0xF)
!= (InstancePtr->PtpCounters.RxPtpHardPointer & 0xF) ) {
/** decode the rx'd frames until RxPtpHardPointer = RxPtpSoftPointer */
InstancePtr->PtpCounters.RxPtpSoftPointer
= InstancePtr->PtpCounters.RxPtpSoftPointer + 1;
/** Set the base address of the current PTP frame in the Buffer */
PtpFrameBaseAddr = XAVB_PTP_RX_BASE_OFFSET
+ ((InstancePtr->PtpCounters.RxPtpSoftPointer & 0xF)
<< 8);
/** Perform very basic sanity checking of the frame : is it a PTP? */
if (XAvb_IsRxFramePTP(InstancePtr, PtpFrameBaseAddr) == 1) {
/** Determine which PTP frame was received. */
MessageType = (XAvb_ReadPtpBuffer(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_TYPE_OFFSET)
& 0x000F0000 ) >> 16;
/** Now act on the received frame */
switch (MessageType) {
/** Sync Frame
* ---------- */
case XAVB_PTP_TYPE_SYNC:
XAvb_DecodeRxSync(InstancePtr, PtpFrameBaseAddr);
break;
/** Follow Up Frame
* --------------- */
case XAVB_PTP_TYPE_FOLLOW_UP:
XAvb_DecodeRxFollowUp(InstancePtr, PtpFrameBaseAddr);
break;
/** PDelayReq Frame
* --------------- */
case XAVB_PTP_TYPE_PDELAYREQ:
/** Send a send PDelayResp frame after receiving a PDelayReq Frame */
XAvb_SendPDelayResp(InstancePtr, PtpFrameBaseAddr);
/** Send a send PDelayRespFollowUp frame after a PDelayResp Frame */
XAvb_SendPDelayRespFollowUp(InstancePtr);
break;
/** PDelayResp Frame
* ---------------- */
case XAVB_PTP_TYPE_PDELAYRESP:
XAvb_DecodeRxPDelayResp(InstancePtr, PtpFrameBaseAddr);
break;
/** PDelayRespFollowUp Frame
* ------------------------ */
case XAVB_PTP_TYPE_PDELAYRESP_FOLLOW_UP:
EchoPTPFramesReceived = 1;
XAvb_DecodeRxPDelayRespFollowUp(InstancePtr, PtpFrameBaseAddr);
break;
/** Announce Frame
* -------------- */
case XAVB_PTP_TYPE_ANNOUNCE:
XAvb_DecodeRxAnnounceFrame(InstancePtr,
PtpFrameBaseAddr);
break;
/** Signaling Frame
* -------------- */
case XAVB_PTP_TYPE_SIGNALING:
XAvb_DecodeRxSignaling(InstancePtr, PtpFrameBaseAddr);
break;
/** Unknown Frame
* -------------- */
default:
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\nXAvb_PtpRxInterruptHandler()");
xil_printf("\r\n** Unknown PTP Frame Rx'd **");
xil_printf("\r\nMessage Type is %x", MessageType);
xil_printf("\r\n-------Unknown Frame -------");
for (x = 0; x < 0x100; x = x + 4) {
xil_printf("\r\n %x %x", x,
(XAvb_ReadPtpBuffer(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
x)));
}
#endif
break;
}
}
}
} else { /* InstancePtr->PtpIsRunning != 1 */
/** PTP is not running so just consume the packets so they are not left in the
* queue and cause problems when we actually start */
/** RxPtpSoftPointer indicates the bin location of the last frame to be
* processed in software. */
while ( (InstancePtr->PtpCounters.RxPtpSoftPointer & 0xF)
!= (InstancePtr->PtpCounters.RxPtpHardPointer & 0xF) ) {
/** decode the rx'd frames until RxPtpHardPointer = RxPtpSoftPointer */
InstancePtr->PtpCounters.RxPtpSoftPointer
= InstancePtr->PtpCounters.RxPtpSoftPointer + 1;
}
}
}
/****************************************************************************
*
* This function provides a stub handler such that if the application does not
* define a handler this function will be called.
*
* @param CallBackRef has no purpose but is necessary to match the
* interface for a handler.
* @param TimestampsUncertain has no purpose but is necessary to match the
* interface for a handler.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
static void XAvb_StubHandler(void *CallBackRef, u32 TimestampsUncertain)
{
/*
* Assert occurs always since this is a stub and should never be called
*/
Xil_AssertVoidAlways();
}
/****************************************************************************/
/**
*
* A function to set the VLAN PCP field for either SR A or B traffic in the
* RX Filtering Control Register - such that AV traffic is correctly filtered
* by the RX Splitter.
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @param VlanPriority contains the 3-bit value to be written to the register
* in the correct bit positions as defined in the address map
*
* @param SrClass is '0' if VLAN Priority (PCP) A is to be updated and is
* '1' if VLAN Priority (PCP) B is to be updated
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_SetupRxFilterControlPcp(XAvb * InstancePtr,
u32 VlanPriority,
u8 SrClass) {
u32 LocalData = 0;
LocalData = XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL);
if (SrClass == 0x0) {
LocalData = LocalData | (VlanPriority & XAVB_RX_AV_VLAN_PRIORITY_A_MASK);
} else {
LocalData = LocalData | (VlanPriority & XAVB_RX_AV_VLAN_PRIORITY_B_MASK);
}
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL,
LocalData);
}
/****************************************************************************/
/**
*
* A function to set the VLAN VID field for either SR A or B traffic in the
* RX Filtering Control Register - such that AV traffic is correctly filtered
* by the RX Splitter.
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @param VlanVid contains the 12-bit value to be written to the register
* in the correct bit positions as defined in the address map
*
* @param SrClass is '0' if VLAN VID A is to be updated and is
* '1' if VLAN VID B is to be updated
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_SetupRxFilterControlVid(XAvb * InstancePtr,
u32 VlanVid,
u8 SrClass) {
u32 LocalData = 0;
LocalData = XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL);
if (SrClass == 0x0) {
LocalData = LocalData | (VlanVid & XAVB_RX_AV_VLAN_VID_A_MASK);
} else {
LocalData = LocalData | (VlanVid & XAVB_RX_AV_VLAN_VID_B_MASK);
}
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL,
LocalData);
}
/****************************************************************************/
/**
*
* A function to set the VLAN Match Mode field for the RX Filtering Control
* Register - such that AV traffic is correctly filtered by the RX Splitter.
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @param VlanMatchMode contains the 1-bit value to be written to the register
* in the correct bit position as defined in the address map
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_SetupRxFilterControlMatchMode(XAvb * InstancePtr,
u32 VlanMatchMode) {
u32 LocalData = 0;
LocalData = XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL);
LocalData = LocalData | (VlanMatchMode & XAVB_RX_AV_VLAN_MATCH_MODE_MASK);
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RX_FILTER_CONTROL,
LocalData);
}

View file

@ -0,0 +1,668 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xavb.h
*
* This header file contains the identifiers and basic driver functions (or
* macros) that can be used to access the device. Other driver functions
* are defined in xavb.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
* 4_0 asa 03/06/14 Fix for CR 740863. The value of XAVB_CLOCK_LOCK_THRESHOLD
* is increased to 1000ns (1 us) to make it more
* meningful and reasonable.
*
* </pre>
*
******************************************************************************/
#ifndef XAVB_H /* prevent circular inclusions */
#define XAVB_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xavb_hw.h"
#include "xstatus.h"
#include "stdio.h"
/************************** Constant Definitions *****************************/
/** @name Define the Debug Level Verbosity for print messages for this driver
* @{
*/
#undef DEBUG_XAVB_LEVEL1 /* Basic messages and PTP frame reception messages */
#undef DEBUG_XAVB_LEVEL2 /* PTP Calculation messages */
#undef DEBUG_XAVB_LEVEL3 /* PTP frame transmission messages */
/** @name MAC Latency Definitions
* @{
*/
#define XAVB_TX_MAC_LATENCY_IN_NS 80
#define XAVB_RX_MAC_LATENCY_IN_NS 80
/* @} */
/** @name PTP Buffer Storage Definitions
* @{
*/
#define XAVB_PTP_TX_SYNC 0x0
#define XAVB_PTP_TX_FOLLOW_UP 0x1
#define XAVB_PTP_TX_PDELAYREQ 0x2
#define XAVB_PTP_TX_PDELAYRESP 0x3
#define XAVB_PTP_TX_PDELAYRESP_FOLLOW_UP 0x4
#define XAVB_PTP_TX_ANNOUNCE 0x5
#define XAVB_PTP_TX_SIGNALING 0x6
/* @} */
/** @name PTP Packet Message Type Definitions
* @{
*/
#define XAVB_PTP_TYPE_SYNC 0x0
#define XAVB_PTP_TYPE_FOLLOW_UP 0x8
#define XAVB_PTP_TYPE_PDELAYREQ 0x2
#define XAVB_PTP_TYPE_PDELAYRESP 0x3
#define XAVB_PTP_TYPE_PDELAYRESP_FOLLOW_UP 0xA
#define XAVB_PTP_TYPE_ANNOUNCE 0xB
#define XAVB_PTP_TYPE_SIGNALING 0xC
/* @} */
/** @name Common PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_PKT_CAPTURED_TIMESTAMP_OFFSET 0x000000FC
/* @} */
/** @name General Tx PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_TX_PKT_SA_UPPER_OFFSET 0x0000000C
#define XAVB_PTP_TX_PKT_SA_LOWER_OFFSET 0x00000010
#define XAVB_PTP_TX_PKT_TYPE_OFFSET 0x00000014
#define XAVB_PTP_TX_PKT_CORRECTION_FIELD_OFFSET 0x00000020
#define XAVB_PTP_TX_PKT_PORTID_UPPER_OFFSET 0x00000028
#define XAVB_PTP_TX_PKT_PORTID_MID_OFFSET 0x0000002C
#define XAVB_PTP_TX_PKT_PORTID_LOWER_OFFSET 0x00000030
#define XAVB_PTP_TX_PKT_SEQUENCEID_OFFSET 0x00000034
#define XAVB_PTP_TX_PKT_TIMESTAMP_UPPER_OFFSET 0x00000038
#define XAVB_PTP_TX_PKT_TIMESTAMP_MID_OFFSET 0x0000003C
#define XAVB_PTP_TX_PKT_TIMESTAMP_LOWER_OFFSET 0x00000040 /* upper 2 bytes */
#define XAVB_PTP_TX_PKT_REQ_PORTID_UPPER_OFFSET 0x00000040 /* lower 2 bytes */
#define XAVB_PTP_TX_PKT_REQ_PORTID_MID_OFFSET 0x00000044
#define XAVB_PTP_TX_PKT_REQ_PORTID_LOWER_OFFSET 0x00000048
/* @} */
/** @name Tx Announce PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_TX_PKT_ANNOUNCE_CURR_UTCOFF_OFFSET 0x00000040
#define XAVB_PTP_TX_PKT_ANNOUNCE_QUAL_LOW_PRI2_GMID_HI_OFFSET 0x00000048
#define XAVB_PTP_TX_PKT_ANNOUNCE_GMID_MID_OFFSET 0x0000004C
#define XAVB_PTP_TX_PKT_ANNOUNCE_GMID_LOW_STEPSREMOVED_HI_OFFSET 0x00000050
#define XAVB_PTP_TX_PKT_ANNOUNCE_STEPSREMOVED_LOW_TIMESRC_OFFSET 0x00000054
#define XAVB_PTP_TX_PKT_ANNOUNCE_TLVLEN_PATHSEQ_START_OFFSET 0x00000058
/* @} */
/** @name PTP frame constant definitions
* @{
*
* Constant value for the control field and LogMeanMessageInterval field for
* pDelayResp and pDelayRespFollowUp PTP frames (defined in IEEE802.1 AS)
*/
#define XAVB_PDELAY_LOG_MEAN_MESSAGE_INT 0x7F050000
/* @} */
/** @name Default LogMeanInterval values
* @{
*/
#define XAVB_DEFAULT_LOG_MEAN_SYNC_INTERVAL (-3) /** 2^(-3) = 125ms */
#define XAVB_DEFAULT_LOG_MEAN_PDELAY_REQ_INTERVAL 0 /** 128/128 = 2^(0) = 1 s */
#define XAVB_DEFAULT_LOG_MEAN_ANNOUNCE_INTERVAL 0 /** 128/128 = 2^(0) = 1 s */
#define XAVB_PKT_TYPE_DISABLED 0xffff
#define XAVB_MAX_SUPPORTED_LOG_MEAN_INTERVAL 8 /** 32768/128 = 256 s */
#define XAVB_MIN_SUPPORTED_LOG_MEAN_INTERVAL (-7) /** 1/128 s */
/* @} */
/** @name Announce / Sync Timeout values
* @{
*/
/** XAVB_ANNOUNCE_RECEIPT_TIMEOUT is the number of announce
* intervals without the receipt of an Announce message from
* the GM that are allowed before the GM is assumed to be no
* longer present and BMCA should be run again
*/
#define XAVB_ANNOUNCE_RECEIPT_TIMEOUT 2
/** XAVB_SYNC_RECEIPT_TIMEOUT is the number of sync intervals
* without the receipt of an Sync message from the GM that are
* allowed before the GM is assumed to be no longer present and
* BMCA should be run again
*/
#define XAVB_SYNC_RECEIPT_TIMEOUT 3
/* @} */
/** @name AS Network Requirements
* @{
*/
/** XAVB_NEIGHBOR_PROP_DELAY_THRESH is the maximum allowed delay (in nanosecs)
* across a full duplex link for which the AVB protocol is allowed to function.
* Although this parameter is defined in the IEEE spec, no default is defined.
*/
#define XAVB_NEIGHBOR_PROP_DELAY_THRESH 5000
/** XAVB_ALLOWED_LOST_RESPONSES is the number of Pdelay_Req
* messages for which a valid response is not received, above
* which the Peer should no longer be considered ASCapable
*/
#define XAVB_ALLOWED_LOST_RESPONSES 3
/* @} */
/** @name General Rx PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_RX_PKT_SA_UPPER_OFFSET 0x00000004
#define XAVB_PTP_RX_PKT_SA_LOWER_OFFSET 0x00000008
#define XAVB_PTP_RX_PKT_TYPE_OFFSET 0x0000000C
#define XAVB_PTP_RX_PKT_CORRECTION_FIELD_OFFSET 0x00000018
#define XAVB_PTP_RX_PKT_PORTID_UPPER_OFFSET 0x00000020
#define XAVB_PTP_RX_PKT_PORTID_MID_OFFSET 0x00000024
#define XAVB_PTP_RX_PKT_PORTID_LOWER_OFFSET 0x00000028
#define XAVB_PTP_RX_PKT_SEQUENCEID_OFFSET 0x0000002C
#define XAVB_PTP_RX_PKT_TIMESTAMP_UPPER_OFFSET 0x00000030
#define XAVB_PTP_RX_PKT_TIMESTAMP_MID_OFFSET 0x00000034
#define XAVB_PTP_RX_PKT_TIMESTAMP_LOWER_OFFSET 0x00000038 /* upper 2 bytes */
#define XAVB_PTP_RX_PKT_REQ_PORTID_UPPER_OFFSET 0x00000038 /* lower 2 bytes */
#define XAVB_PTP_RX_PKT_REQ_PORTID_MID_OFFSET 0x0000003C
#define XAVB_PTP_RX_PKT_REQ_PORTID_LOWER_OFFSET 0x00000040
/* @} */
/** @name Rx Announce PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_RX_PKT_ANNOUNCE_PRI1_QUAL_HI_OFFSET 0x0000003C
#define XAVB_PTP_RX_PKT_ANNOUNCE_QUAL_LOW_PRI2_GMID_HI_OFFSET 0x00000040
#define XAVB_PTP_RX_PKT_ANNOUNCE_GMID_MID_OFFSET 0x00000044
#define XAVB_PTP_RX_PKT_ANNOUNCE_GMID_LOW_STEPSREMOVED_HI_OFFSET 0x00000048
#define XAVB_PTP_RX_PKT_ANNOUNCE_STEPSREMOVED_LOW_TIMESRC_OFFSET 0x0000004C
/* @} */
/** @name Rx Signalling PTP Frame Structure Definitions.
* @{
*/
#define XAVB_PTP_RX_PKT_SIGNALING_DELAY_INTERVAL_OFFSET 0x00000044
/* @} */
/** @name Standard PTP Frame Field Definitions (from IEEE802.1AS specification).
* @{
*/
#define XAVB_PTP_ETHERTYPE 0x88F7
#define XAVB_PTP_VERSION_PTP 2
/* @} */
/** @name Real Time Clock Definitions.
* @{
*/
#define XAVB_ONE_SECOND 1000000000 /**< Value in ns */
#define XAVB_PERIOD_8KHZ 125000 /**< Value in ns */
/* @} */
/** @name Real Time Clock Locked Definitions.
* @{
* If the Slave error is > this threshold then define PTP to be
* unlocked and link not asCapable.
* @note: This threshold is not specified in IEEE 802.1as.
*/
#define XAVB_CLOCK_LOCK_THRESHOLD 1000 /**< Value in ns */
/* @} */
/** @name RTC Increment Value Update Definitions
* @{
* Define how often to re-calculate the RTC Increment This value
* indicates how many good Sync/FollowUp message pairs
* are received before the re-calculation is performed.
*/
#define XAVB_NUM_SYNC_FU_PAIR_CALC_RTC_INCREMENT 2
/* @} */
/**************************** Type Definitions *******************************/
/**
* Callback function. The first argument is a callback reference passed in by
* the upper layer when setting the callback functions, and passed back to the
* upper layer when the callback is invoked.
* The second argument is a '1' if a Grandmaster Discontinuity event has occurred
* otherwise it is '0'.
*/
typedef void (*XAvb_Handler)(void *CallBackRef, u32 TimestampsUncertain);
/**
* This typedef contains configuration information for a device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Register base address */
} XAvb_Config;
/**
* This typedef defines the format for a data structure which stores the Port
* Identity information from received Announce packets
*/
typedef struct
{
u32 ClockIdentityUpper; /**< Upper 4 bytes of ClockIdentity */
u32 ClockIdentityLower; /**< Lower 4 bytes of ClockIdentity*/
u16 PortNumber; /**< PortNumber associated with ClockIdentity*/
} XAvb_PortIdentity;
/**
* This typedef defines the format for a data structure which stores the Clock
* Identity information from received Announce packets
*/
typedef struct
{
u32 ClockIdentityUpper; /**< Upper 4 bytes of ClockIdentity */
u32 ClockIdentityLower; /**< Lower 4 bytes of ClockIdentity*/
} XAvb_ClockIdentity;
/**
* This typedef defines the quality of a clock
*/
typedef struct
{
u8 clockClass; /**< Announce message: clockClass */
u8 clockAccuracy; /**< Announce message: clockAccuracy */
u16 offsetScaledLogVariance; /**< Announce message: offsetScaledLogVariance*/
} XAvb_ClockQuality;
/**
* This typedef defines the format for a data structure which stores the relevant
* fields which are captured from Announce Packets.
*/
typedef struct
{
XAvb_PortIdentity SourcePortIdentity; /**< Announce message: sourcePortIdentity */
XAvb_ClockIdentity GrandmasterIdentity; /**< Announce message: grandmasterIdentity */
u16 stepsRemoved; /**< Announce message: stepsRemoved */
XAvb_ClockQuality ClockQuality; /**< Announce message: grandmasterClockQuality */
u8 GrandmasterPriority1; /**< Announce message: grandmasterPriority1*/
u8 GrandmasterPriority2; /**< Announce message: grandmasterPriority2*/
u8 IAmTheRtcMaster; /**< Boolean: 1 = grandmaster, 0 = slave*/
u16 tlvLengthField; /**< Announce message: lengthField (for TLV)*/
char logMessageInterval; /**< Announce message: logMessageInterval.
* NOTE: 8-bit signed integer */
u16 AnnounceIntervalDuration; /**< Announce Interval in units of 1/128 secs */
} XAvb_BmcData;
/**
* This typedef defines the format for a data structure which stores information
* relating to the 1588 based PTP timing calculations
*/
typedef struct
{
u32 Nanosec; /**< ns value for sync frame tx request */
u32 SlaveSyncTimestamp; /**< The timestamp taken of a rx'd sync */
u32 MasterCorrectionField; /**< Correction Field from rx'd follow-up */
u32 PDelayTimestampT1; /**< T1 :PDelayReq Frame transmission */
u32 PDelayTimestampT2; /**< T2 :PDelayReq rx'd at link partner */
u32 PDelayTimestampT3; /**< T3 :PDelayResp Frame reception */
u32 PDelayTimestampT4; /**< T4 :PDelayResp tx'd by link partner */
u32 LinkDelay; /**< Last calculated value of Link Delay */
u32 NewSlaveTime; /**< RTC ns at slave for last rx'd sync */
u32 NewMasterTime; /**< RTC ns at master for last tx'd sync */
u32 OldSlaveTime; /**< Stored RTC slave ns for past sync rx */
u32 OldMasterTime; /**< Stored RTC master ns for past sync tx*/
u32 NsOffsetForPDelayResp; /**< RTC ns offset at PDelayResp tx time */
} XAvb_PtpStruct;
/**
* This typedef defines the format for a data structure which stores the last
* used sequence ID for all of the PTP timing frames.
*/
typedef struct
{
u16 SyncSequenceId; /**< SequenceId of the latest RX'd Sync message */
u16 FollowUpSequenceId; /**< SequenceId of the latest RX'd FollowUp message */
u16 PDelayReqSequenceId; /**< SequenceId of the latest TX'd PDelayReq message */
u16 PDelayRespSequenceId; /**< SequenceId of the latest RX'd PDelayResp message */
u16 PDelayFollowUpSequenceId; /**< SequenceId of the latest RX'd PDelayRespFollowUp message */
u16 OldSyncSequenceId; /**< SequenceId of the previous RX'd Sync message used
* for XAvb_UpdateRtcIncrement() calculations */
u16 NewSyncSequenceId; /**< SequenceId of the current RX'd Sync message used
* for XAvb_UpdateRtcIncrement() calculations */
} XAvb_SequenceIdStruct;
/**
* The Signalling frame defines the delays to be used between Sync Frames, Link
* Delay measurements and Announce Frame events
*/
typedef struct
{
u16 SyncIntervalDuration; /**< Sync Interval in units of 1/128 seconds */
u16 LinkDelayIntervalDuration; /**< Link Delay Interval in units of 1/128 seconds */
u16 AnnounceIntervalDuration; /**< Announce Interval in units of 1/128 seconds */
} XAvb_SignallingFrameData;
/**
* This typedef defines the various counters which have to maintained for the
* PTP operation.
*/
typedef struct
{
u8 RxPtpHardPointer; /**< The Rx PTP Buffer last written to */
u8 RxPtpSoftPointer; /**< The current software pointer to Rx Buffer */
u16 CounterSyncInterval; /**< To count units of 1/128 seconds */
u16 CounterLinkDelayInterval; /**< To count units of 1/128 seconds */
u16 CounterAnnounceInterval; /**< To count units of 1/128 seconds */
u8 CounterSyncEvents; /**< To count the number of Sync Events */
} XAvb_Counters;
/** Keep track of state machine data to make sure we're fully
* compliant with the spec
*/
typedef struct
{
u8 lostResponses; /**< Keep track of the state machine errors */
u8 rcvdPDelayResp; /**< Received a valid PDelayResp packet since PDelayReq was sent */
u8 rcvdPDelayRespFollowUp; /**< Received a valid PDelayFollowUp packet since PDelayResp was received */
XAvb_PortIdentity respPortIdentity; /**< sourcePortIdentity of the last PDelayResp packet received */
XAvb_PortIdentity respReqPortIdentity; /**< requestingPortIdentity of the last PDelayResp packet received */
} XAvb_StateMachineData;
/** This struct captures information from RX'd Sync/FollowUp message pairs in a format similiar
* to the MDSyncReceive structure described in the IEEE P802.1AS specification.
*/
typedef struct
{
/** The logMessageInterval is the value of the logMessageInterval of the time-synchronization
* event message received by this port. It is the logSyncInterval of the upstream MasterPort
* that sent the event message.*/
u8 logMessageInterval;
/** Convert logMessageInterval into a value we can relate to our 1/128 ns clk pulse */
u16 SyncIntervalDuration;
} XAvb_MDSyncReceive;
/**
* The XAvb driver instance data. The user is required to allocate a
* variable of this type for every AVB device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
/** hardware configuration */
XAvb_Config Config;
/** Device is initialized and ready */
u32 IsReady;
/** Is AVB enabled */
u32 AVBIsEnabled;
/** The PTP algorithm can be started and stopped as requested */
u32 PtpIsRunning;
/** The peer must be AS capable before we start full blown PTP */
u32 PeerASCapable;
/** Current PTP Slave Error is less than XAVB_CLOCK_LOCK_THRESHOLD nsec */
u32 PTPLocked;
/** Store the info from the latest RX'd Sync/Follow message pair */
XAvb_MDSyncReceive latestMDSyncReceive;
/** Contains the local port Identity information */
XAvb_PortIdentity portIdLocal;
/** Create a data structure for the Best Master Clock Algorithm (BMCA) */
XAvb_BmcData CurrentBmc;
/** Create a data structure for the Precise Timing Protocol (PTP) */
XAvb_PtpStruct PtpRecords;
/** Create a data structure to record the PTP frames Sequence ID values */
XAvb_SequenceIdStruct SequenceIdRecords;
/** Create a data structure to store the Signalling frame information */
XAvb_SignallingFrameData SignallingFrameData;
/** Create a data structure to store various PTP counters/timers */
XAvb_Counters PtpCounters;
/** Create a data structure to store state machine flags */
XAvb_StateMachineData StateMachineData;
/** Callback Handler for a GrandMaster discontinuity event */
XAvb_Handler GMDiscHandler;
/** Callback ref for a GrandMaster discontinuity event */
void *GMDiscCallBackRef;
} XAvb;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/*
* Functions in xavb.c
*/
XStatus XAvb_CfgInitialize(XAvb *InstancePtr, \
XAvb_Config *ConfigPtr, \
u32 EffectiveAddress);
XAvb_Config *XAvb_LookupConfig(u16 DeviceId);
void XAvb_Reset(XAvb * InstancePtr);
void XAvb_Start(XAvb * InstancePtr);
void XAvb_Stop(XAvb * InstancePtr);
void XAvb_PtpTimerInterruptHandler(XAvb * InstancePtr);
void XAvb_PtpRxInterruptHandler(XAvb * InstancePtr);
void XAvb_SetupRxFilterControlPcp(XAvb * InstancePtr, \
u32 VlanPriority, \
u8 SrClass);
void XAvb_SetupRxFilterControlVid(XAvb * InstancePtr, \
u32 VlanVid, \
u8 SrClass);
void XAvb_SetupRxFilterControlMatchMode(XAvb * InstancePtr, \
u32 VlanMatchMode);
/*
* Functions in xavb_ptp_packets.c
*/
u32 XAvb_ReorderWord(u32 Data);
u32 XAvb_CompareClockIdentity(u32 BaseAddress, \
XAvb_ClockIdentity Identity1, \
XAvb_ClockIdentity Identity2);
u32 XAvb_ComparePortIdentity(u32 BaseAddress, \
XAvb_PortIdentity Identity1, \
XAvb_PortIdentity Identity2);
void XAvb_WriteToMultipleTxPtpFrames(u32 BaseAddress, \
u32 Address, \
u32 Data, \
u32 DataBitEnable, \
u8 BufferEnable);
u32 XAvb_IncSequenceId(u32 BaseAddress, \
u32 PTPFrameBaseAddress);
void XAvb_GetPortIdentity(u32 BaseAddress, \
u32 PtpFrameBaseAddr, \
u32 PortIdOffset, \
XAvb_PortIdentity *portID);
void XAvb_WaitOnTxPtpQueue(XAvb * InstancePtr);
void XAvb_MasterSendAnnounce(XAvb * InstancePtr);
void XAvb_MasterSendSync(XAvb * InstancePtr);
void XAvb_MasterSendFollowUp(XAvb * InstancePtr);
void XAvb_SendPDelayReq(XAvb * InstancePtr);
void XAvb_SendPDelayResp(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_SendPDelayRespFollowUp(XAvb * InstancePtr);
u32 XAvb_IsRxFramePTP(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_DecodeRxSync(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_DecodeRxFollowUp(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_DecodeRxPDelayResp(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_DecodeRxPDelayRespFollowUp(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_DecodeRxSignaling(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
u16 XAvb_UpdateIntervalDuration(u16 currentIntervalDuration, \
char logMeanVal);
u16 XAvb_ConvertLogMeanToDuration(char logMeanVal);
char XAvb_ConvertDurationToLogMean(u16 fractionalVal);
void XAvb_UpdateLogMeanMessageInterval(u32 BaseAddress, \
u32 PtpFrameBaseAddr, \
u16 intervalDuration);
void XAvb_SetupSourcePortIdentity(XAvb * InstancePtr, \
XAvb_PortIdentity systemIdentity);
/*
* Functions in xavb_ptp_bmca.c
*/
void XAvb_DecodeTxAnnounceFrame(XAvb * InstancePtr);
void XAvb_DecodeRxAnnounceFrame(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_ReadAnnounceFrame(u32 BaseAddress, \
u32 PtpFrameBaseAddr, \
XAvb_BmcData* AnnounceFrame);
void XAvb_ReadAnnounceReceiptTimeout(u32 BaseAddress, \
u32 PtpFrameBaseAddr, \
XAvb_BmcData * AnnounceFrame);
void XAvb_UpdateBmcRecords(XAvb_BmcData* NewMaster, \
XAvb_BmcData* CurrentBmc);
u32 XAvb_BestMasterClockAlgorithm(XAvb_BmcData* AnnounceFrame, \
XAvb_BmcData* CurrentBmc);
void XAvb_BecomeRtcMaster(XAvb * InstancePtr, u8 txAnnounceHasWon);
void XAvb_BecomeRtcSlave(XAvb * InstancePtr);
void XAvb_ChangePTPLockStatus(XAvb * InstancePtr, u8 locked);
void XAvb_ChangePeerASCapability(XAvb *InstancePtr, u8 capable);
void XAvb_SetGMDiscontinuityHandler(XAvb *InstancePtr, \
XAvb_Handler FuncPtr, \
void *CallBackRef);
/*
* Functions in xavb_rtc_sync.c
*/
u32 XAvb_CaptureNanoSec(u32 BaseAddress, \
u32 PtpFrameBaseAddr);
void XAvb_CalcDelay(XAvb * InstancePtr);
void XAvb_CalcRtcOffset(XAvb * InstancePtr, \
u32 PtpFrameBaseAddr);
void XAvb_UpdateRtcIncrement(XAvb * InstancePtr);
void XAvb_Adjust8kClock(u32 BaseAddress, \
u32 NewOffset);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,654 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xavb_example.c
*
* This file implements a simple example to show the usage of Audio Video
* Bridging (AVB) functionality of Axi Ethernet IP in loopback mode.
* The example uses the PTP Timer and the PTP Rx interrupts. A PDelay_Req packet
* is sent and is received back (as we are in loopback mode). .
* After this loop backed PDelay_Req packet is received, a PDelay_Resp and
* PDelay_RespFollowUp packets are sent. These packets are also received.
* Since the source port identity of the received packets matches with our
* systems's own source port identity there is no further processing done.
*
* @note
*
* This code assumes the processor type is Microblaze, Xilinx interrupt
* controller (XIntc) is used in the system , and that no operating
* system is used.
*
* It also assumes that all the relevant AVB interrupts are properly
* connected to the Intc module.
*
* The Ethernet AVB Endpoint functionality should be enabled in the Xilinx
* Axi Ethernet core for this example to work.
*
* The Axi Ethernet is used with a GMII interface. The example initializes
* the GMII interface with 1000 Mbps speed.
*
* IMPORTANT NOTE:
* The user must define the macro XAVB_CLOCK_LOCK_THRESHOLD in xavb.h to
* an appropriate value as relevant for the corresponding use case. Presently
* it is defined to 1000 ns which is typical for telecom industry.
* This macro is used to compare against the slave error as calculated everytime
* after receiving 2 successive sync/followup frames. Slave error is the
* difference between master time duration and slave time duration as calculated
* for the time gap (the time it takes to receive two successive sync/follow up
* frames). If slave error is greater than the value defined in
* XAVB_CLOCK_LOCK_THRESHOLD, then master and slave clocks are unlocked. This
* means the node running this SW assumes that the peer is no more capable of
* processing 802.1as frames. The node running the SW then waits till it successful
* calculates the path delay (which essentially means the peer is again capable
* of processing 802.1as frames.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------------
* 1.00a kag/asa 08/25/10 First release
* 3.00a asa 04/10/12 Disabled enabling of promiscuous mode. This is
* required for AxiEthernet cores with version v3_01_a
* onwards because of a change in the AVB implementation.
* 4.0 asa 03/06/14 Fix for CR 740863. Added a #warning message for
* users of this example to take note of the fact that
* we have just used a typical value for XAVB_CLOCK_LOCK_THRESHOLD
* and users may want to change it as per their requirements.
*
* </pre>
*******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xil_types.h"
#include "xintc.h"
#include "xil_exception.h"
#include "xavb_hw.h"
#include "xavb.h"
#include "xil_cache.h"
#include "xaxiethernet.h" /* defines Axi Ethernet APIs */
/************************** Constant Definitions *****************************/
/**
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define AXIETHERNET_DEVICE_ID XPAR_AXIETHERNET_0_DEVICE_ID
#define AVB_PTP_RX_INTERRUPT_ID \
XPAR_INTC_0_AXIETHERNET_0_AV_INTERRUPT_PTP_RX_VEC_ID /*
* AVB PTP Received
* Frame Interrupt ID
*/
#define AVB_PTP_INTERRUPT_ID \
XPAR_INTC_0_AXIETHERNET_0_AV_INTERRUPT_10MS_VEC_ID /* AVB PTP Timer
* Interrupt ID
*/
/*
* Other constants used in this file.
*/
#define PHY_DETECT_REG 1
#define PHY_DETECT_MASK 0x1808
#define PHY_R0_RESET 0x8000
#define PHY_R0_LOOPBACK 0x4000
#define PHY_R0_DFT_SPD_1000 0x0040
/*
* The source MAC address used in this example. This will also form
* a part of source port identity field in the PTP messages
*/
#define ETH_SYSTEM_ADDRESS_EUI48_HIGH 0x000A35
#define ETH_SYSTEM_ADDRESS_EUI48_LOW 0x010203
/******************************************************************************/
#warning The threshold or tolerance limit for slave error is currently set to \
1000 ns. This can be configured through the macro \
XAVB_CLOCK_LOCK_THRESHOLD in xavb.h. Slave error is the difference \
between measured master time duration and slave time duration over \
two sync-frame intervals. If slave error exceeds the configured \
threshold, the master and slave clocks are unlocked. For usage of the \
macro XAVB_CLOCK_LOCK_THRESHOLD refer to the function \
XAvb_UpdateRtcIncrement in file xavb_rtc_sync.c
/******************************************************************************/
/************************** Function Prototypes ******************************/
static int AvbSetupInterruptSystem(XAvb *InstancePtr);
static int AvbConfigHW(XAxiEthernet *AxiEthernetInstancePtr,XAvb *InstancePtr);
void AvbGMDiscontinuityHandler(void *CallBackRef, u32 TimestampsUncertain);
static int AvbConfigureGmii(XAxiEthernet *InstancePtr, XAvb *AvbInstancePtr);
static int AvbEnterPhyLoopBack(XAxiEthernet *InstancePtr);
static void AvbUtilPhyDelay(unsigned int Seconds);
static void AvbEnablePTPInterrupts(void);
static void AvbUtilPrintMessage(char *Message);
static XAxiEthernet AxiEthernetInstance; /* Instance of Axi Ethernet driver */
static XAvb Avb; /* Instance of AVB driver */
static XIntc InterruptController; /* Instance of INTC driver */
static XAvb_Config AvbConfigStruct;
volatile u8 EchoPTPFramesReceived = 0;
/*****************************************************************************/
/**
*
* This is the main function for the AVB example.
*
* @param None.
*
* @return - XST_SUCCESS to indicate success.
* - XST_FAILURE to indicate failure
*
* @note This example will be in a infinte loop if the HW is not working
* properly and if the interrupts are not received.
*
****************************************************************************/
int main()
{
int Status;
XAxiEthernet_Config *AxiEtherCfgPtr;
XAvb_PortIdentity SystemIdentity;
u32 WriteData;
#if XPAR_MICROBLAZE_USE_ICACHE
Xil_ICacheInvalidate();
Xil_ICacheEnable();
#endif
#if XPAR_MICROBLAZE_USE_DCACHE
Xil_DCacheInvalidate();
Xil_DCacheEnable();
#endif
AvbUtilPrintMessage("\r\n--- Entering main() ---");
/*
* Initialize Axi Ethernet Driver.
*/
AxiEtherCfgPtr = XAxiEthernet_LookupConfig(AXIETHERNET_DEVICE_ID);
Status = XAxiEthernet_CfgInitialize(&AxiEthernetInstance,
AxiEtherCfgPtr,
AxiEtherCfgPtr->BaseAddress);
if (Status != XST_SUCCESS) {
AvbUtilPrintMessage("Failed initializing config for Axi Ethernet\r\n");
AvbUtilPrintMessage("--- Exiting main() ---\r\n");
return XST_FAILURE;
}
/*
* Initialize the AVB Config structure.
*/
AvbConfigStruct.DeviceId = AxiEtherCfgPtr->DeviceId;
AvbConfigStruct.BaseAddress = AxiEtherCfgPtr->BaseAddress;
Status = XAvb_CfgInitialize(&Avb, &AvbConfigStruct, AvbConfigStruct.BaseAddress);
if (Status != XST_SUCCESS) {
AvbUtilPrintMessage("Failed initializing config for AVB\r\n");
AvbUtilPrintMessage("--- Exiting main() ---\r\n");
return XST_FAILURE;
}
/*
* Setup the handler for the AVB that will be called if the PTP drivers
* identify a possible discontinuity in GrandMaster time.
*/
XAvb_SetGMDiscontinuityHandler(&Avb, AvbGMDiscontinuityHandler, &Avb);
/*
* Reset and initialize the AVB driver.
*/
XAvb_Reset(&Avb);
/*
* Perform configuration on the Axi Ethernet and Ethernet AVB Endpoint
* cores
*/
Status = AvbConfigHW(&AxiEthernetInstance, &Avb);
if (Status != XST_SUCCESS) {
AvbUtilPrintMessage("Failed initializing Axi Ethernet and AVB\r\n");
AvbUtilPrintMessage("--- Exiting main() ---\r\n");
return XST_FAILURE;
}
/*
* Initialize Interrupt Controller
*/
Status = AvbSetupInterruptSystem(&Avb);
if (Status != XST_SUCCESS) {
AvbUtilPrintMessage("Failed initializing INTC system\r\n");
AvbUtilPrintMessage("--- Exiting main() ---\r\n");
return XST_FAILURE;
}
/*
* Setup the Source Address and Source Port Identity fields in all
* TX PTP Buffers
*/
SystemIdentity.ClockIdentityUpper = (ETH_SYSTEM_ADDRESS_EUI48_HIGH
<< 8) | 0xFF;
SystemIdentity.ClockIdentityLower = (0xFE << 24) |
(ETH_SYSTEM_ADDRESS_EUI48_LOW);
SystemIdentity.PortNumber = 1;
/*
* Write the SA to all default TX PTP buffers
*/
WriteData = (XAvb_ReorderWord(SystemIdentity.ClockIdentityUpper)) << 16;
XAvb_WriteToMultipleTxPtpFrames(Avb.Config.BaseAddress,
XAVB_PTP_TX_PKT_SA_UPPER_OFFSET,
(WriteData & 0xFFFF0000) ,
0xFFFF0000,
0x7F);
WriteData = (SystemIdentity.ClockIdentityUpper << 16);
WriteData = (WriteData & 0xFF000000);
WriteData = (WriteData | (SystemIdentity.ClockIdentityLower & 0x00FFFFFF));
WriteData = XAvb_ReorderWord(WriteData);
XAvb_WriteToMultipleTxPtpFrames(Avb.Config.BaseAddress,
XAVB_PTP_TX_PKT_SA_LOWER_OFFSET,
WriteData,
0xFFFFFFFF,
0x7F);
/*
* Write sourceportidentity to all default TX PTP buffers
*/
XAvb_SetupSourcePortIdentity(&Avb,SystemIdentity);
/*
* Start AVB and enable the PTP interrupts.
*/
XAvb_Start(&Avb);
AvbEnablePTPInterrupts();
while(1) {
if(EchoPTPFramesReceived) {
AvbUtilPrintMessage("\r\nExample passed\r\n");
AvbUtilPrintMessage("--- Exiting main() ---\r\n");
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function configures Axi Ethernet core and AVB module.
*
* @param AxiEthernetInstancePtr is a pointer to the Axi Ethernet driver
* instance
* @param AvbInstancePtr is a pointer to the AVB instance.
*
* @return -XST_SUCCESS to indicate success
* -XST_FAILURE to indicate failure.
*
* @note None.
*
******************************************************************************/
static int AvbConfigHW(XAxiEthernet *AxiEthernetInstancePtr, XAvb *AvbInstancePtr)
{
u32 ReadData;
int Status;
/*
* Configure MDIO Master in Axi Ethernet - MUST be done before
* any MDIO accesses
*/
XAxiEthernet_WriteReg(AxiEthernetInstancePtr->Config.BaseAddress,
XAE_MDIO_MC_OFFSET,0x0000005D);
/*
* Disable Axi Ethernet Flow Control
*/
XAxiEthernet_WriteReg(AxiEthernetInstancePtr->Config.BaseAddress,
XAE_FCC_OFFSET,0x0);
/*
* Initialise Axi Ethernet by enabling Tx and Rx with VLAN capability
*/
XAxiEthernet_WriteReg(AxiEthernetInstancePtr->Config.BaseAddress,
XAE_TC_OFFSET,XAE_TC_TX_MASK | XAE_TC_VLAN_MASK);
XAxiEthernet_WriteReg(AxiEthernetInstancePtr->Config.BaseAddress,
XAE_RCW1_OFFSET, XAE_RCW1_RX_MASK | XAE_RCW1_VLAN_MASK);
/*
* Initialise RTC reference clock for nominal frequency 125MHz -
* (see xavb_hw.h for value)
*/
XAvb_WriteReg(AvbInstancePtr->Config.BaseAddress,
XAVB_RTC_INCREMENT_OFFSET,
XAVB_RTC_INCREMENT_NOMINAL_RATE);
Status = AvbConfigureGmii(AxiEthernetInstancePtr,AvbInstancePtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function configures the GMII interface and Axi Ethernet registers for
* 1000 Mbps speed configuration.
*
* @param InstancePtr is a pointer to the Axi Ethernet driver instance
* @param AvbInstancePtr is a pointer to the AVB instance.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE, in case of failure...
*
* @note None.
*
******************************************************************************/
static int AvbConfigureGmii(XAxiEthernet *InstancePtr, XAvb *AvbInstancePtr)
{
u32 EmmcReg;
int Status;
/*
* Set PHY to loopback.
*/
Status = AvbEnterPhyLoopBack(InstancePtr);
if(Status != XST_SUCCESS) {
XAvb_Stop(AvbInstancePtr);
return XST_FAILURE;
}
/*
* Get the current contents of the EMAC config register and
* zero out speed bits
*/
EmmcReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
XAE_EMMC_OFFSET);
EmmcReg = EmmcReg & (~XAE_EMMC_LINKSPEED_MASK);
EmmcReg |= XAE_EMMC_LINKSPD_1000;
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
XAE_EMMC_OFFSET,EmmcReg);
/*
* Setting the operating speed of the MAC needs a delay. There
* doesn't seem to be register to poll, so please consider this
* during your application design.
*/
AvbUtilPhyDelay(1);
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function sets the PHY to loopback mode. This works with the marvell PHY
* common on Xilinx evaluation boards. This sets the PHY speed to 1000 Mbps.
*
* @param AxiEthernetInstancePtr is a pointer to the instance of the
* AxiEthernet component.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE, in case of failure..
*
* @note None.
*
******************************************************************************/
static int AvbEnterPhyLoopBack(XAxiEthernet *InstancePtr)
{
u16 PhyReg0;
signed int PhyAddr;
u16 PhyReg;
for (PhyAddr = 31; PhyAddr >= 0; PhyAddr--) {
XAxiEthernet_PhyRead(&AxiEthernetInstance, PhyAddr,
PHY_DETECT_REG, &PhyReg);
if ((PhyReg != 0xFFFF) && ((PhyReg & PHY_DETECT_MASK)
== PHY_DETECT_MASK)) {
/* Found a valid PHY address */
break;
}
}
if(PhyAddr == 0)
return XST_FAILURE;
/*
* Clear the PHY of any existing bits by zeroing this out
*/
PhyReg0 = 0;
PhyReg0 |= PHY_R0_DFT_SPD_1000;
/*
* Set the speed and put the PHY in reset, then put the PHY in loopback
*/
XAxiEthernet_PhyWrite(&AxiEthernetInstance, PhyAddr, 0,
PhyReg0 | PHY_R0_RESET);
AvbUtilPhyDelay(1);
XAxiEthernet_PhyRead(&AxiEthernetInstance, PhyAddr, 0,&PhyReg0);
XAxiEthernet_PhyWrite(&AxiEthernetInstance, PhyAddr, 0,
PhyReg0 | PHY_R0_LOOPBACK);
AvbUtilPhyDelay(1);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function sets up the interrupt system so interrupts can occur for the
* AVB design.
*
* @param InstancePtr contains a pointer to the instance of the AVB
* component which is going to be connected to the interrupt
* controller.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE, in case of failure..
*
* @note None.
*
****************************************************************************/
static int AvbSetupInterruptSystem(XAvb *InstancePtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it can be used.
* XPAR_INTC_0_DEVICE_ID specifies the XINTC device ID that is
* generated in xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, XPAR_INTC_0_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the Ethernet AVB Endpoint's 10 ms interrupt
*/
Status = XIntc_Connect(&InterruptController,
AVB_PTP_INTERRUPT_ID,
(XInterruptHandler)XAvb_PtpTimerInterruptHandler,
InstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the Ethernet AVB Endpoint's PTP Rx interrupt
*/
Status = XIntc_Connect(&InterruptController,
AVB_PTP_RX_INTERRUPT_ID,
(XInterruptHandler)XAvb_PtpRxInterruptHandler,
InstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller so interrupts are enabled for all
* devices that cause interrupts.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable interrupt on Microblaze
*/
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
(void *)&InterruptController);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function enables the PTP Timer interrupt and PTP Rx interrupt in the
* INTC module.
*
* @param None
*
* @return None
*
* @note None.
*
******************************************************************************/
static void AvbEnablePTPInterrupts(void)
{
XIntc_Enable(&InterruptController, AVB_PTP_RX_INTERRUPT_ID);
XIntc_Enable(&InterruptController, AVB_PTP_INTERRUPT_ID);
return;
}
/****************************************************************************/
/**
*
* This function is the handler which will be called if the PTP drivers
* identify a possible discontinuity in GrandMaster time.
*
* This handler provides an example of how to handle this situation -
* but this function is application specific.
*
*
* @param CallBackRef contains a callback reference from the driver, in
* this case it is the instance pointer for the AVB driver.
* @param TimestampsUncertain - a value of 1 indicates that there is a
* possible discontinuity in GrandMaster time. A value of 0
* indicates that Timestamps are no longer uncertain.
*
* @return None.
*
* @note This Handler ned to be defined otherwise the XAvb_StubHandler
* will generate an error
*
****************************************************************************/
void AvbGMDiscontinuityHandler(void *CallBackRef, u32 TimestampsUncertain)
{
xil_printf("\r\nGMDiscontinuityHandler: Timestamps are now %s\r\n",
TimestampsUncertain ? "uncertain" : "certain");
}
/******************************************************************************/
/**
*
* For Microblaze we use an assembly loop that is roughly the same regardless of
* optimization level, although caches and memory access time can make the delay
* vary. Just keep in mind that after resetting or updating the PHY modes,
* the PHY typically needs time to recover.
*
* @return None
*
* @note None
*
******************************************************************************/
static void AvbUtilPhyDelay(unsigned int Seconds)
{
static int WarningFlag = 0;
/* If MB caches are disabled or do not exist, this delay loop could
* take minutes instead of seconds (e.g., 30x longer). Print a warning
* message for the user (once). If only MB had a built-in timer!
*/
if (((mfmsr() & 0x20) == 0) && (!WarningFlag)) {
WarningFlag = 1;
}
#define ITERS_PER_SEC (XPAR_CPU_CORE_CLOCK_FREQ_HZ / 6)
asm volatile ("\n"
"1: \n\t"
"addik r7, r0, %0 \n\t"
"2: \n\t"
"addik r7, r7, -1 \n\t"
"bneid r7, 2b \n\t"
"or r0, r0, r0 \n\t"
"bneid %1, 1b \n\t"
"addik %1, %1, -1 \n\t"
:: "i"(ITERS_PER_SEC), "d" (Seconds));
}
/******************************************************************************/
/**
*
* This function is called by example code to display a console message
*
* @param Message is the text explaining the error
*
* @return None
*
* @note None
*
******************************************************************************/
static void AvbUtilPrintMessage(char *Message)
{
#ifdef STDOUT_BASEADDRESS
xil_printf("%s\r\n", Message);
#endif
}

View file

@ -0,0 +1,164 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xavb_hw.c
*
* The xavb_hw driver. Functions in this file are the minimum required functions
* for this driver. See xavb_hw.h for a detailed description of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_io.h"
#include "xavb_hw.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/****************************************************************************/
/**
*
* This function reads the given Ethernet Statistic Register
*
* @param BaseAddress is the base address of the device
* @param CounterID is the Statistic Counter to be read
* @param Value a pointer to the read value of the 64-bit value of the counter
* and it is updated by this function
*
* @return None.
*
* @note The CounterID's defined here are the same as the Statistic Counter
* Addresses as used with the TEMAC core. Since each counter is 8-bytes
* wide, we must multiply these Counter ID's by 8 (or a left shift of 3)
* when mapping this into the PLB memory map. The 64-bit counter value
* is read as two separate 32-bit accesses.
*
*****************************************************************************/
void XAvbMac_ReadStats(u32 BaseAddress,
u32 CounterId,
XAvb_Uint64* Value)
{
Value->Upper = Xil_In32(BaseAddress + ((CounterId & 0x00ff) << 3) + 0x4);
Value->Lower = Xil_In32(BaseAddress + ((CounterId & 0x00ff) << 3));
}
/****************************************************************************/
/**
*
* This function reads the current Real Time Counter (RTC) value
*
* @param BaseAddress is the base address of the device
* @param RtcValue is a pointer to a struct in which to store the value read
* from the RTC (The RTC 48-bit seconds field and the 32-bit ns field
* of this struct are updated).
*
* @return None
*
* @note This is provided as a basic function since the ns field MUST be read
* before the seconds/epoch registers (reading the ns samples the entire
* RTC in hardware).
*
*****************************************************************************/
void XAvb_ReadRtc(u32 BaseAddress,
XAvb_RtcFormat* RtcValue)
{
RtcValue->NanoSeconds =
Xil_In32(BaseAddress + XAVB_RTC_NANOSEC_VALUE_OFFSET)
& XAVB_RTC_NS_MASK;
RtcValue->SecondsLower =
Xil_In32(BaseAddress + XAVB_RTC_SEC_LOWER_VALUE_OFFSET)
& XAVB_RTC_SEC_LOWER_MASK;
RtcValue->SecondsUpper =
Xil_In32(BaseAddress + XAVB_RTC_SEC_UPPER_VALUE_OFFSET)
& XAVB_RTC_SEC_UPPER_MASK;
}
/****************************************************************************/
/**
*
* This function writes to the Real Time Counter (RTC) Offset Registers
*
* @param BaseAddress is the base address of the device
* @param RtcValue is the nanoseconds and seconds offset values that should
* be written to the RTC.
*
* @return None
*
* @note This is provided as a basic function since the ns field MUST be
* written after the seconds/epoch offset registers (writing to the ns
* offset registers samples the entire RTC offset in hardware).
*
*****************************************************************************/
void XAvb_WriteRtcOffset(u32 BaseAddress, XAvb_RtcFormat* RtcValue)
{
Xil_Out32((BaseAddress + XAVB_RTC_SEC_UPPER_OFFSET),
(RtcValue->SecondsUpper & XAVB_RTC_SEC_UPPER_MASK));
Xil_Out32((BaseAddress + XAVB_RTC_SEC_LOWER_OFFSET),
(RtcValue->SecondsLower & XAVB_RTC_SEC_LOWER_MASK));
Xil_Out32((BaseAddress + XAVB_RTC_NANOSEC_OFFSET),
(RtcValue->NanoSeconds & XAVB_RTC_NS_MASK));
}

View file

@ -0,0 +1,504 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xavb_hw.h
*
* This header file contains the identifiers and basic driver functions (or
* macros) that can be used to access the device. Other driver functions
* are defined in xavb.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
* 3_01a asa 04/10/12 The AVB core is now brought inside the AxiEthernet
* core. Because of this there are changes in the
* register map.
*
* </pre>
*
******************************************************************************/
#ifndef XAVB_HW_H /* prevent circular inclusions */
#define XAVB_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_io.h"
/************************** Constant Definitions *****************************/
/** @name Register offsets for the Tri-Mode Ethernet MAC. Each register is 32
* bits. The MAC is addressable through the Ethernet AVB Endpoint core.
* @{
*/
#define XAVB_MAC_RX_REG0_OFFSET 0x00000400 /**< MAC Rx Config Register 0 */
#define XAVB_MAC_RX_REG1_OFFSET 0x00000404 /**< MAC Rx Config Register 1 */
#define XAVB_MAC_TX_REG_OFFSET 0x00000408 /**< MAC Tx Config Register */
#define XAVB_MAC_FC_REG_OFFSET 0x0000040c /**< MAC Flow Control Register */
#define XAVB_MAC_SPD_REG_OFFSET 0x00000410 /**< MAC Speed Control Register */
//#define XAVB_MAC_MGMT_REG_OFFSET 0x0000050C /**< MAC MDIO Management Register*/
/* @} */
/** @name Register offsets for the Ethernet Audio Video Endpoint. Each register
* is 32 bits.
* @{
*/
#define XAVB_PTP_TX_CONTROL_OFFSET 0x00012000 /**< Tx PTP Control Reg */
#define XAVB_PTP_RX_CONTROL_OFFSET 0x00012004 /**< Rx PTP Control Reg */
#define XAVB_RX_FILTER_CONTROL 0x00012008 /**< Rx Filter Control Reg */
#define XAVB_TX_SENDSLOPE 0x0001200C /**< Tx rate sendSlope Reg */
#define XAVB_TX_IDLESLOPE 0x00012010 /**< Tx rate idleSlope Reg */
#define XAVB_TX_HILIMIT 0x00012014 /**< Tx rate hiLimit Reg */
#define XAVB_TX_LOLIMIT 0x00012018 /**< Tx rate loLimit Reg */
#define XAVB_RTC_NANOSEC_OFFSET 0x00012800 /**< RTC ns offset Reg */
#define XAVB_RTC_SEC_LOWER_OFFSET 0x00012808 /**< RTC sec[31:0] offset */
#define XAVB_RTC_SEC_UPPER_OFFSET 0x0001280C /**< RTC sec[47:32] offset */
#define XAVB_RTC_INCREMENT_OFFSET 0x00012810 /**< RTC Increment Reg */
#define XAVB_RTC_NANOSEC_VALUE_OFFSET 0x00012814 /**< RTC ns value Reg */
#define XAVB_RTC_SEC_LOWER_VALUE_OFFSET 0x00012818 /**< RTC sec[31:0] value */
#define XAVB_RTC_SEC_UPPER_VALUE_OFFSET 0x0001281C /**< RTC sec[47:32] value */
#define XAVB_RTC_CLEAR_INT_OFFSET 0x00012820 /**< RTC Interrupt Clear */
#define XAVB_RTC_8K_OFFSET_OFFSET 0x00012824 /**< RTC 8k phase offset */
#define XAVB_SW_RESET_OFFSET 0x00012828 /**< S/W Reset Reg */
/* @} */
/** @name Packet base address offsets for the Ethernet Audio Video Endpoint Tx
* Precise Timing Protocol (PTP) frame buffer. Each PTP frames is
* stored in 256-byte chunks of BRAM. This BRAM can store 8 PTP frames
* of which only 6 are currently in use.
* @{
*/
#define XAVB_PTP_TX_SYNC_OFFSET 0x00011000
#define XAVB_PTP_TX_FOLLOW_UP_OFFSET 0x00011100
#define XAVB_PTP_TX_PDELAYREQ_OFFSET 0x00011200
#define XAVB_PTP_TX_PDELAYRESP_OFFSET 0x00011300
#define XAVB_PTP_TX_PDELAYRESP_FOLLOW_UP_OFFSET 0x00011400
#define XAVB_PTP_TX_ANNOUNCE_OFFSET 0x00011500
/* @} */
/** @name Base address offset for the Ethernet Audio Video Endpoint Rx
* Precise Timing Protocol (PTP) frame buffer. These PTP frames are
* stored in 256-byte chunks of BRAM. This BRAM can store 16 PTP frames.
* @{
*/
#define XAVB_PTP_RX_BASE_OFFSET 0x00010000
/* @} */
/** @name AVB Tx PTP Control Register
* @{
*/
#define XAVB_PTP_TX_SEND_SYNC_FRAME_MASK 0x00000001
#define XAVB_PTP_TX_SEND_FOLLOWUP_FRAME_MASK 0x00000002
#define XAVB_PTP_TX_SEND_PDELAYREQ_FRAME_MASK 0x00000004
#define XAVB_PTP_TX_SEND_PDELAYRESP_FRAME_MASK 0x00000008
#define XAVB_PTP_TX_SEND_PDELAYRESPFOLLOWUP_FRAME_MASK 0x00000010
#define XAVB_PTP_TX_SEND_ANNOUNCE_FRAME_MASK 0x00000020
#define XAVB_PTP_TX_SEND_FRAME6_BIT_MASK 0x00000040
#define XAVB_PTP_TX_SEND_FRAME7_BIT_MASK 0x00000080
#define XAVB_PTP_TX_WAIT_SYNC_FRAME_MASK 0x00000100
#define XAVB_PTP_TX_WAIT_FOLLOWUP_FRAME_MASK 0x00000200
#define XAVB_PTP_TX_WAIT_PDELAYREQ_FRAME_MASK 0x00000400
#define XAVB_PTP_TX_WAIT_PDELAYRESP_FRAME_MASK 0x00000800
#define XAVB_PTP_TX_WAIT_PDELAYRESPFOLLOWUP_FRAME_MASK 0x00001000
#define XAVB_PTP_TX_WAIT_ANNOUNCE_FRAME_MASK 0x00002000
#define XAVB_PTP_TX_WAIT_FRAME6_BIT_MASK 0x00004000
#define XAVB_PTP_TX_WAIT_FRAME7_BIT_MASK 0x00008000
#define XAVB_PTP_TX_WAIT_ALL_FRAMES_MASK 0x0000FF00
#define XAVB_PTP_TX_PACKET_FIELD_MASK 0x00070000
/* @} */
/** @name AVB Rx PTP Control Register
* @{
*/
#define XAVB_PTP_RX_CLEAR_BIT_MASK 0x00000001
#define XAVB_PTP_RX_PACKET_FIELD_MASK 0x00000F00
/* @} */
/** @name AVB Rx Filter Control Register
* @{
*/
#define XAVB_RX_AV_VLAN_PRIORITY_A_MASK 0x00000007
#define XAVB_RX_AV_VLAN_VID_A_MASK 0x00007FF8
#define XAVB_RX_AV_VLAN_MATCH_MODE_MASK 0x00008000
#define XAVB_RX_AV_VLAN_PRIORITY_B_MASK 0x00070000
#define XAVB_RX_AV_VLAN_VID_B_MASK 0x7FF80000
#define XAVB_RX_LEGACY_PROMISCUOUS_MODE_MASK 0x80000000
/* @} */
/** @name AVB Tx rate control sendSlope
* @{
*/
#define XAVB_TX_SENDSLOPE_MASK 0X000FFFFF
/* @} */
/** @name AVB Tx rate control idleSlope
* @{
*/
#define XAVB_TX_IDLESLOPE_MASK 0X000FFFFF
/* @} */
/** @name AVB Tx rate control hiLimit
* @{
*/
#define XAVB_TX_HILIMIT_MASK 0X01FFFFFF
/* @} */
/** @name AVB Tx rate control loLimit
* @{
*/
#define XAVB_TX_LOLIMIT_MASK 0X01FFFFFF
/* @} */
/** @name RTC field Registers
* @{
*/
#define XAVB_RTC_NS_MASK 0x3FFFFFFF
#define XAVB_RTC_SEC_LOWER_MASK 0xFFFFFFFF
#define XAVB_RTC_SEC_UPPER_MASK 0x0000FFFF
/* @} */
/** @name RTC Increment Register
* @{
*/
#define XAVB_RTC_INCREMENT_VALUE_MASK 0x03FFFFFF
/** This value assumes a 125MHz rtc_clock */
#define XAVB_RTC_INCREMENT_NOMINAL_RATE 0x00800000
/** Add some rails so that recovery is possible after a
* string of bad pDelay values. The RTC should be able to lock
* to within 100ppm of the slowest allowable clock (25 MHz).
* This equates to +/-4ps. Let's arbitrarily set the rails to
* 400ppm (+/-16ps) just in case someone decides to use a
* particularly bad oscillator. The lowest 20 bits of
* NewIncrement are fractions of a nanosecond, which equates
* to +/- 0x04189 */
#define XAVB_RTC_400PPM_OFFSET 0x00004189
/* @} */
/** @name RTC Interrupt Clear Register
* @{
*/
#define XAVB_RTC_INCREMENT_VALUE_MASK 0x03FFFFFF
/* @} */
/** @name RTC Interrupt Clear Register
* @{
*/
#define XAVB_RTC_CLEAR_INT_MASK 0x00000000
/* @} */
/** @name RTC 8k phase offset Register
* @{
*/
#define XAVB_RTC_8K_PHASE_OFFSET_MASK 0x3FFFFFFF
/* @} */
/** @name S/W Reset Register
* @{
*/
#define XAVB_SW_RESET_TX_AND_RX_PATHS 0x00000003
/* @} */
/** @name AVB MAC MDIO register address space.
* @{
*/
#define XAVB_MAC_MDIO_BASE_OFFSET 0x00006000
/* @} */
/** @name MDIO valid data mask (MDIO registers are all 16-bits).
* @{
*/
#define XAVB_MAC_MDIO_DATA_MASK 0x0000FFFF
/* @} */
/** @name MAC Statistic Counter names and CounterID.
* @{
*/
#define XAVB_STATS_BYTES_TRANSMITTED 0x00000000
#define XAVB_STATS_BYTES_RECEIVED 0x00000001
#define XAVB_STATS_UNDERSIZED_FRAMES_RECEIVED 0x00000002
#define XAVB_STATS_FRAGMENT_FRAMES_RECEIVED 0x00000003
#define XAVB_STATS_64_BYTE_FRAMES_RECEIVED_OK 0x00000004
#define XAVB_STATS_65_TO_127_BYTE_FRAMES_RECEIVED_OK 0x00000005
#define XAVB_STATS_128_TO_255_BYTE_FRAMES_RECEIVED_OK 0x00000006
#define XAVB_STATS_256_TO_511_BYTE_FRAMES_RECEIVED_OK 0x00000007
#define XAVB_STATS_512_TO_1023_BYTE_FRAMES_RECEIVED_OK 0x00000008
#define XAVB_STATS_1024_TO_1518_BYTE_FRAMES_RECEIVED_OK 0x00000009
#define XAVB_STATS_OVERSIZED_FRAMES_RECEIVED_OK 0x0000000A
#define XAVB_STATS_64_BYTE_FRAMES_TRANSMITTED_OK 0x0000000B
#define XAVB_STATS_65_TO_127_BYTE_FRAMES_TRANSMITTED_OK 0x0000000C
#define XAVB_STATS_128_TO_255_BYTE_FRAMES_TRANSMITTED_OK 0x0000000D
#define XAVB_STATS_256_TO_511_BYTE_FRAMES_TRANSMITTED_OK 0x0000000E
#define XAVB_STATS_512_TO_1023_BYTE_FRAMES_TRANSMITTED_OK 0x0000000F
#define XAVB_STATS_1024_TO_1518_BYTE_FRAMES_TRANSMITTED_OK 0x00000010
#define XAVB_STATS_OVERSIZE_FRAMES_TRANSMITTED_OK 0x00000011
#define XAVB_STATS_FRAMES_RECEIVED_OK 0x00000012
#define XAVB_STATS_FCS_ERRORS 0x00000013
#define XAVB_STATS_BROADCAST_FRAMES_RECEIVED_OK 0x00000014
#define XAVB_STATS_MULTICAST_FRAMES_RECEIVED_OK 0x00000015
#define XAVB_STATS_CONTROL_FRAMES_RECEIVED_OK 0x00000016
#define XAVB_STATS_LENGTH_TYPE_OUT_OF_RANGE 0x00000017
#define XAVB_STATS_VLAN_TAGGED_FRAMES_RECEIVED_OK 0x00000018
#define XAVB_STATS_PAUSE_FRAMES_RECEIVED_OK 0x00000019
#define XAVB_STATS_CONTROL_FRAMES_WITH_UNSUPPORTED_OPCODE 0x0000001A
#define XAVB_STATS_FRAMES_TRANSMITTED 0x0000001B
#define XAVB_STATS_BROADCAST_FRAMES_TRANSMITTED 0x0000001C
#define XAVB_STATS_MULTICAST_FRAMES_TRANSMITTED 0x0000001D
#define XAVB_STATS_UNDERRUN_ERRORS 0x0000001E
#define XAVB_STATS_CONTROL_FRAMES_TRANSMITTED_OK 0x0000001F
#define XAVB_STATS_VLAN_TAGGED_FRAMES_TRANSMITTED_OK 0x00000020
#define XAVB_STATS_PAUSE_FRAMES_TRANSMITTED_OK 0x00000021
#define XAVB_STATS_SINGLE_COLLISION_FRAMES 0x00000022
#define XAVB_STATS_MULTI_COLLISION_FRAMES 0x00000023
#define XAVB_STATS_DEFERRAL_FRAMES 0x00000024
#define XAVB_STATS_LATE_COLLISION_FRAMES 0x00000025
#define XAVB_STATS_EXCESS_COLLISION_FRAMES 0x00000026
#define XAVB_STATS_EXCESS_DEFERRAL_FRAMES 0x00000027
#define XAVB_STATS_CARRIER_SENSE_ERRORS 0x00000028
#define XAVB_STATS_ALIGNMENT_ERRORS 0x00000029
/* @} */
/**************************** Type Definitions *******************************/
/**
* This typedef defines the format for the Real Time Clock (RTC). The RTC
* contains a 48-bit seconds field (split into upper and lower sections) and
* a 32-bit nano-seconds field.
*/
typedef struct
{
u16 SecondsUpper; /**< Upper 16-bits of seconds field */
u32 SecondsLower; /**< Lower 32-bits of seconds field */
u32 NanoSeconds; /**< 32-bit nanoseconds field */
} XAvb_RtcFormat;
/**
* This typedef descibes a 64-bit un-signed integer in terms of 2 u32s
*/
typedef struct
{
u32 Upper; /**< Upper 32 bits */
u32 Lower; /**< Lower 32 bits */
} XAvb_Uint64;
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/**
*
* This macro reads from the given AVB core register.
*
* @param BaseAddress is the base address of the device
* @param RegOffset is the register offset to be read
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define XAvb_ReadReg(BaseAddress, RegOffset) \
Xil_In32((BaseAddress) + (RegOffset))
/****************************************************************************/
/**
*
* This macro writes to the given AVB core register.
*
* @param BaseAddress is the base address of the device
* @param RegOffset is the register offset to be written
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define XAvb_WriteReg(BaseAddress, RegOffset, Data) \
Xil_Out32((BaseAddress) + (RegOffset), (Data))
/****************************************************************************/
/**
*
* This macro reads from the given PTP frame buffer.
*
* @param BaseAddress is the base address of the device
* @param PtpPacketBaseAddress is the base address of the frame in the PTP
* BRAM packet buffer
@param PtpPacketOffset is the offset address within the PTP frame
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define XAvb_ReadPtpBuffer(BaseAddress, PtpPacketBaseAddress, PtpPacketOffset)\
Xil_In32(BaseAddress + PtpPacketBaseAddress + PtpPacketOffset)
/****************************************************************************/
/**
*
* This macro writes to the given PTP frame buffer.
*
* @param BaseAddress is the base address of the device
* @param PtpPacketBaseAddress is the base address of the frame in the PTP
* packet buffer
@param PtpPacketOffset is the offset address within the PTP frame
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define XAvb_WritePtpBuffer(BaseAddress, PtpPacketBaseAddress, \
PtpPacketOffset, Data) \
Xil_Out32(BaseAddress + PtpPacketBaseAddress + PtpPacketOffset, (Data))
/****************************************************************************/
/**
*
* This macro reads from the given TEMAC Configuration Register.
*
* @param BaseAddress is the base address of the device
* @param RegOffset is the register offset to be read
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define XAvbMac_ReadConfig(BaseAddress, RegOffset) \
Xil_In32((BaseAddress) + (RegOffset))
/****************************************************************************/
/**
*
* This macro writes to the given TEMAC Configuration Register.
*
* @param BaseAddress is the base address of the device
* @param RegOffset is the register offset to be written
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define XAvbMac_WriteConfig(BaseAddress, RegOffset, Data) \
Xil_Out32((BaseAddress) + (RegOffset), (Data))
/****************************************************************************/
/**
*
* This macro reads from the given MDIO Register using the TEMAC
*
* @param BaseAddress is the base address of the device
* @param Phyad is the Physical Address of the PHY
* @param Regad is the Address of the MDIO register within the addressed PHY
*
* @return The 32-bit value of the register (upper 16-bits will be all 0's)
*
* @note None.
*
*****************************************************************************/
#define XAvbMac_ReadMdio(BaseAddress, Phyad, Regad) \
Xil_In32((BaseAddress) + XAVB_MAC_MDIO_BASE_OFFSET \
+ (((Phyad) & 0x1F) << 8) \
+ (((Regad) & 0x1F) << 3))
/****************************************************************************/
/**
*
* This macro writes to the given MDIO Register using the TEMAC
*
* @param BaseAddress is the base address of the device
* @param Phyad is the Physical Address of the PHY
* @param Regad is the Address of the MDIO register within the addressed PHY
* @param Data is the 32-bit value to write
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define XAvbMac_WriteMdio(BaseAddress, Phyad, Regad, Data) \
Xil_Out32(BaseAddress + XAVB_MAC_MDIO_BASE_OFFSET \
+ (((Phyad) & 0x1F) << 8) \
+ (((Regad) & 0x1F) << 3), \
(Data & XAVB_MAC_MDIO_DATA_MASK))
/************************** Function Prototypes ******************************/
/*
* Functions in xavb_hw.c
*/
void XAvbMac_ReadStats(u32 BaseAddress, u32 CounterId, XAvb_Uint64* Value);
void XAvb_ReadRtc(u32 BaseAddress, XAvb_RtcFormat* RtcValue);
void XAvb_WriteRtcOffset(u32 BaseAddress, XAvb_RtcFormat* RtcValue);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,819 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xavb_ptp_bmca.c
*
* The XAvb driver. Functions in this file all relate to the Best Master Clock
* Algorithm (BMCA) which is performed on the AVB network to select a network
* Grand Master Clock.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xavb_hw.h"
#include "xavb.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/****************************************************************************/
/**
*
* A New Announce Packet has been written to this device to transmit. We need to
* decode it and rerun the Best Master Clock Algorithm (BMCA)
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @return None. But an updated True/False decision as to whether this device
* should operate as a clock master or a slave is written into the
* CurrentBmc data structure.
*
* @note None.
*
*****************************************************************************/
void XAvb_DecodeTxAnnounceFrame(XAvb * InstancePtr) {
u32 NewMaster = 0;
XAvb_BmcData TxAnnounceFrame;
/** Read the attributes for the new Announce frame in the Tx PTP buffer */
XAvb_ReadAnnounceFrame(InstancePtr->Config.BaseAddress,
(XAVB_PTP_TX_ANNOUNCE_OFFSET + 8),
&TxAnnounceFrame);
/** Compare the clock attributes between then new Announce frame and the
* current master */
NewMaster = XAvb_BestMasterClockAlgorithm(&TxAnnounceFrame,
&InstancePtr->CurrentBmc);
if ((NewMaster == 1) | (InstancePtr->CurrentBmc.IAmTheRtcMaster == 1)) {
/** Update records with the NEW best master */
XAvb_UpdateBmcRecords(&TxAnnounceFrame,
&InstancePtr->CurrentBmc);
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\nXAvb_DecodeTxAnnounceFrame()");
xil_printf("\r\n* BMC : I am the MASTER");
xil_printf("\r\n-----------------------");
xil_printf("\r\nLocal Announce Frame");
xil_printf("\r\n-----------------------");
xil_printf("\r\nGM ID upper %x",
InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityUpper);
xil_printf("\r\nGM ID lower %x",
InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityLower);
xil_printf("\r\nPriority1 %x",
InstancePtr->CurrentBmc.GrandmasterPriority1);
xil_printf("\r\nclockClass %x",
InstancePtr->CurrentBmc.ClockQuality.clockClass);
xil_printf("\r\nPriority2 %x",
InstancePtr->CurrentBmc.GrandmasterPriority2);
#endif
/** Our new Tx Announce Packet has won - so this device must be the
* master */
xil_printf("\r\n*** XAvb_DecodeTxAnnounceFrame() : Call XAvb_BecomeRtcMaster() *** \r\n");
XAvb_BecomeRtcMaster(InstancePtr,1);
}
}
/****************************************************************************/
/**
*
* A New Announce Packet has been received. We need to decode it and rerun the
* Best Master Clock Algorithm (BMCA)
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
* @param PtpFrameBaseAddr is the base address of the received Announce Packet
* in the Rx PTP Packet Buffer
*
* @return None. But an updated True/False decision as to whether this device
* should operate as a clock master or a slave is written into the
* CurrentBmc data structure.
*
* @note None.
*
*****************************************************************************/
void XAvb_DecodeRxAnnounceFrame(XAvb * InstancePtr,
u32 PtpFrameBaseAddr) {
u32 NewMaster = 0;
XAvb_BmcData RxAnnounceFrame;
/** Read the attributes for the new Announce frame received */
XAvb_ReadAnnounceFrame(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
&RxAnnounceFrame);
/** If the received packet's clockIdentity matches our
* clockIdentity, ignore the packet */
if( XAvb_ComparePortIdentity(InstancePtr->Config.BaseAddress,
InstancePtr->portIdLocal,
RxAnnounceFrame.SourcePortIdentity) ) {
xil_printf("Got an announce from myself.. ignoring\r\n");
return;
}
/** If the received packet's stepsRemoved field is >= 255,
* ignore the packet */
if( RxAnnounceFrame.stepsRemoved >= 255 ) {
xil_printf("Got an announce with stepsRemoved > 255.. ignoring\r\n");
return;
}
/** If the Announce packet's GMID matches that of our current GM
* record, then update its records based on the current packet,
* just in case something (such as priority) has changed. */
if( XAvb_CompareClockIdentity(InstancePtr->Config.BaseAddress,
RxAnnounceFrame.GrandmasterIdentity,
InstancePtr->CurrentBmc.GrandmasterIdentity) ) {
/** update timeout information */
InstancePtr->PtpCounters.CounterAnnounceInterval = 0;
XAvb_UpdateBmcRecords(&RxAnnounceFrame,
&InstancePtr->CurrentBmc);
/** Compare against this device's information to see if we should be GM */
XAvb_DecodeTxAnnounceFrame(InstancePtr);
} else if( InstancePtr->CurrentBmc.IAmTheRtcMaster ) {
/** run BMCA on this announce to see if it is better than me */
NewMaster = XAvb_BestMasterClockAlgorithm(&RxAnnounceFrame,
&InstancePtr->CurrentBmc);
if (NewMaster == 1) {
/** Update records with the NEW best master */
XAvb_UpdateBmcRecords(&RxAnnounceFrame,
&InstancePtr->CurrentBmc);
/** Capture the Announce Receipt Timeout Interval.
* Reset the announce receipt timeout interval to use the new value.
*/
XAvb_ReadAnnounceReceiptTimeout(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
&RxAnnounceFrame);
InstancePtr->CurrentBmc.AnnounceIntervalDuration =
XAvb_ConvertLogMeanToDuration(RxAnnounceFrame.logMessageInterval);
#ifdef DEBUG_XAVB_LEVEL1
xil_printf("\r\r\nXAvb_DecodeRxAnnounceFrame()");
xil_printf("\r\n-----------------------");
xil_printf("\r\nWinning Announce Frame");
xil_printf("\r\n-----------------------");
xil_printf("\r\nGM ID upper %x",
InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityUpper);
xil_printf("\r\nGM ID lower %x",
InstancePtr->CurrentBmc.GrandmasterIdentity.ClockIdentityLower);
xil_printf("\r\nPriority1 %x",
InstancePtr->CurrentBmc.GrandmasterPriority1);
xil_printf("\r\nclockClass %x",
InstancePtr->CurrentBmc.ClockQuality.clockClass);
xil_printf("\r\nPriority2 %x",
InstancePtr->CurrentBmc.GrandmasterPriority2);
#endif
/** New Rx Announce Packet has won - so this device cannot be a master */
xil_printf("\r\n* XAvb_DecodeRxAnnounceFrame()::BMC : I am a SLAVE");
XAvb_BecomeRtcSlave(InstancePtr);
}
}
}
/****************************************************************************/
/**
*
* A New Announce Packet is to be analyzed. This function will read in the
* packet, decode it, and extract the relevent information fields to the
* "AnnounceFrame" data pointer.
*
* @param BaseAddress is the base address of the device
* @param PtpFrameBaseAddr is the base address of the received Announce Packet
* in the Rx PTP Packet Buffer
* @param AnnounceFrame is a pointer to a suitable data structure, designed to
* record the useful fields from the received Announce Packet
*
* @return The AnnounceFrame data structure is updated.
*
* @note None.
*
*****************************************************************************/
void XAvb_ReadAnnounceFrame(u32 BaseAddress,
u32 PtpFrameBaseAddr,
XAvb_BmcData * AnnounceFrame) {
u32 ReadWord;
AnnounceFrame->SourcePortIdentity.ClockIdentityLower = 0;
AnnounceFrame->SourcePortIdentity.ClockIdentityUpper = 0;
/** Get the Source Port Identity of the port sending the Announce Packet */
XAvb_GetPortIdentity(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_PORTID_UPPER_OFFSET, &AnnounceFrame->SourcePortIdentity);
/** Read priority1 and top half of ClockQuality */
ReadWord = XAvb_ReorderWord(XAvb_ReadPtpBuffer(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_ANNOUNCE_PRI1_QUAL_HI_OFFSET));
AnnounceFrame->GrandmasterPriority1 = (ReadWord >> 16);
AnnounceFrame->ClockQuality.clockClass = (ReadWord >> 8);
AnnounceFrame->ClockQuality.clockAccuracy = ReadWord;
/** Read bottom half of ClockQuality, priority2, and top byte of GMID */
ReadWord = XAvb_ReorderWord(XAvb_ReadPtpBuffer(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_ANNOUNCE_QUAL_LOW_PRI2_GMID_HI_OFFSET));
AnnounceFrame->ClockQuality.offsetScaledLogVariance = (ReadWord >> 16);
AnnounceFrame->GrandmasterPriority2 = (ReadWord >> 8);
AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper = (ReadWord << 24);
/** Read bytes 4-7 of GMID */
ReadWord = XAvb_ReorderWord(XAvb_ReadPtpBuffer(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_ANNOUNCE_GMID_MID_OFFSET));
AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper |= (ReadWord >> 8);
AnnounceFrame->GrandmasterIdentity.ClockIdentityLower = (ReadWord << 24);
/** Read bytes 1-3 of GMID and high byte of stepsRemoved */
ReadWord = XAvb_ReorderWord(XAvb_ReadPtpBuffer(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_ANNOUNCE_GMID_LOW_STEPSREMOVED_HI_OFFSET));
AnnounceFrame->GrandmasterIdentity.ClockIdentityLower |= (ReadWord >> 8);
AnnounceFrame->stepsRemoved = (ReadWord << 8);
/** Read low byte of stepsRemoved */
ReadWord = XAvb_ReorderWord(XAvb_ReadPtpBuffer(BaseAddress, PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_ANNOUNCE_STEPSREMOVED_LOW_TIMESRC_OFFSET));
AnnounceFrame->stepsRemoved |= (ReadWord >> 24);
}
/****************************************************************************/
/**
*
* This function reads the logMessageinteval from an RX PTP Buffer and updates
* the AnnounceFrame struct with the value read.
*
* @param BaseAddress is the base address of the device
* @param PtpFrameBaseAddr is the base address of the received Announce Packet
* in the Rx PTP Packet Buffer
* @param AnnounceFrame is a pointer to a suitable data structure, designed to
* record the useful fields from the received Announce Packet
*
* @return The AnnounceFrame data structure is updated.
*
* @note None.
*
*****************************************************************************/
void XAvb_ReadAnnounceReceiptTimeout(u32 BaseAddress,
u32 PtpFrameBaseAddr,
XAvb_BmcData * AnnounceFrame) {
u32 ReadWord;
u8 logMessageInterval;
ReadWord = XAvb_ReorderWord((XAvb_ReadPtpBuffer(BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_SEQUENCEID_OFFSET)) &
0xFF000000);
logMessageInterval = ReadWord;
/* Implicit convert from unsigned (u8) to signed (char) */
AnnounceFrame->logMessageInterval = logMessageInterval;
}
/****************************************************************************/
/**
*
* This function will accept the data pointer to the current BMCA records, accept
* a pointer to an equivalent data structure for the new Announce Packet. The
* Best Master Clock Algorithm (BMCA) is then performed on these two data
* structures by comparing the data fields
*
* @param CurrentBmc is a pointer to a suitable data structure, designed to
* record the current fields from the current Grand Master's Announce
* Packet.
* @param AnnounceFrame is a pointer to a suitable data structure, designed to
* record the useful fields from the received Announce Packet
*
* @return An updated True/False decision as to whether there is to be a change
* of Grand Master in the network.
*
* @note None.
*
*****************************************************************************/
u32 XAvb_BestMasterClockAlgorithm(XAvb_BmcData * AnnounceFrame,
XAvb_BmcData * CurrentBmc) {
u32 NewMaster = 0;
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("*** Performing BMCA ***\r\n");
#endif
/** Priority1 takes precedence over all over priorites */
if (AnnounceFrame->GrandmasterPriority1 < CurrentBmc->GrandmasterPriority1) {
/** we have found a better master! */
NewMaster = 1;
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on priority1: AnnPri1 (%d) < BmcPri1 (%d)\r\n",
AnnounceFrame->GrandmasterPriority1,
CurrentBmc->GrandmasterPriority1);
#endif
} else if (AnnounceFrame->GrandmasterPriority1 ==
CurrentBmc->GrandmasterPriority1) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: priority1 equal moving on: (%d)\r\n",
AnnounceFrame->GrandmasterPriority1);
#endif
/** convert structs to u32 values for easy comparison */
u32 AnnClockQualityInteger;
u32 BmcClockQualityInteger;
AnnClockQualityInteger = (AnnounceFrame->ClockQuality.clockClass << 24) |
(AnnounceFrame->ClockQuality.clockAccuracy << 16) |
(AnnounceFrame->ClockQuality.offsetScaledLogVariance);
BmcClockQualityInteger = (CurrentBmc->ClockQuality.clockClass << 24) |
(CurrentBmc->ClockQuality.clockAccuracy << 16) |
(CurrentBmc->ClockQuality.offsetScaledLogVariance);
/** ClockQuality has the next priority */
if (AnnClockQualityInteger < BmcClockQualityInteger ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on clockQuality: Ann (0x%08x) < Bmc (0x%08x)\r\n",
AnnClockQualityInteger,
BmcClockQualityInteger);
#endif
/** we have found a better master! */
NewMaster = 1;
} else if ( AnnClockQualityInteger == BmcClockQualityInteger ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: clockQuality equal moving on: (0x%08x)\r\n",
AnnClockQualityInteger);
#endif
/** Priority2 provides fine grained ordering amongst otherwise equal
* clocks */
if (AnnounceFrame->GrandmasterPriority2 <
CurrentBmc->GrandmasterPriority2) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on priority2: AnnPri1 (%d) < BmcPri1 (%d)\r\n",
AnnounceFrame->GrandmasterPriority2,
CurrentBmc->GrandmasterPriority2);
#endif
/** we have found a better master! */
NewMaster = 1;
/** Next compare the Clock Identities */
} else if (AnnounceFrame->GrandmasterPriority2
== CurrentBmc->GrandmasterPriority2) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: priority2 equal moving on: (%d)\r\n",
AnnounceFrame->GrandmasterPriority2);
#endif
if (AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper <
CurrentBmc->GrandmasterIdentity.ClockIdentityUpper) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on GMIDClockIDUp: Ann (0x%08x) < Bmc (0x%08x)\r\n",
AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper,
CurrentBmc->GrandmasterIdentity.ClockIdentityUpper);
#endif
/** we have found a better master! */
NewMaster = 1;
} else if (AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper
== CurrentBmc->GrandmasterIdentity.ClockIdentityUpper) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: GMIDclockIDUp equal moving on: (0x%08x)\r\n",
AnnounceFrame->GrandmasterIdentity.ClockIdentityUpper);
#endif
if (AnnounceFrame->GrandmasterIdentity.ClockIdentityLower <
CurrentBmc->GrandmasterIdentity.ClockIdentityLower) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on GMIDClockIDLow: Ann (0x%08x) < Bmc (0x%08x)\r\n",
AnnounceFrame->GrandmasterIdentity.ClockIdentityLower,
CurrentBmc->GrandmasterIdentity.ClockIdentityLower);
#endif
/** we have found a better master! */
NewMaster = 1;
/** Next compare stepsRemoved */
} else if( AnnounceFrame->GrandmasterIdentity.ClockIdentityLower
== CurrentBmc->GrandmasterIdentity.ClockIdentityLower ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: GMIDclockIDLo equal moving on: (0x%08x)\r\n",
AnnounceFrame->GrandmasterIdentity.ClockIdentityLower);
#endif
if( AnnounceFrame->stepsRemoved < CurrentBmc->stepsRemoved ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on stepsRemoved: Ann (%d) < Bmc (%d)\r\n",
AnnounceFrame->stepsRemoved,
CurrentBmc->stepsRemoved);
#endif
/** we have found a better master! */
NewMaster = 1;
/** Next compare SourcePortIdentity */
} else if( AnnounceFrame->stepsRemoved == CurrentBmc->stepsRemoved ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: stepsRemoved equal moving on: (%d)\r\n",
AnnounceFrame->stepsRemoved);
#endif
if( AnnounceFrame->SourcePortIdentity.ClockIdentityUpper <
CurrentBmc->SourcePortIdentity.ClockIdentityUpper) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on sourceIDClockIDupper: Ann (0x%08x) < Bmc (0x%08x)\r\n",
AnnounceFrame->SourcePortIdentity.ClockIdentityUpper,
CurrentBmc->SourcePortIdentity.ClockIdentityUpper);
#endif
/** we have found a better master! */
NewMaster = 1;
} else if( AnnounceFrame->SourcePortIdentity.ClockIdentityUpper
== CurrentBmc->SourcePortIdentity.ClockIdentityUpper ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: sourceIDportUp equal moving on: (0x%08x)\r\n",
CurrentBmc->SourcePortIdentity.ClockIdentityUpper);
#endif
if( AnnounceFrame->SourcePortIdentity.ClockIdentityLower <
CurrentBmc->SourcePortIdentity.ClockIdentityLower ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on sourceIDClockIDlow: Ann (0x%08x) < Bmc (0x%08x)\r\n",
AnnounceFrame->SourcePortIdentity.ClockIdentityLower,
CurrentBmc->SourcePortIdentity.ClockIdentityLower);
#endif
/** we have found a better master! */
NewMaster = 1;
/** If all else fails, the SourcePortIdentity Port Number must
* act as the tie-breaker */
} else if( AnnounceFrame->SourcePortIdentity.PortNumber <
CurrentBmc->SourcePortIdentity.PortNumber ) {
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("BMCA: Found new GM on sourceIDportNum: AnnPort (0x%08x) < BmcPort (0x%08x)\r\n",
AnnounceFrame->SourcePortIdentity.PortNumber,
CurrentBmc->SourcePortIdentity.PortNumber);
#endif
/** A new master has won on the tie-break! */
NewMaster = 1;
}
}
}
}
}
}
}
}
#ifdef XAVB_DEBUG_LEVEL2
xil_printf("*** END BMCA ***\r\n");
#endif
return NewMaster;
}
/****************************************************************************/
/**
*
* This function will accept the data pointer to the current BMCA records, accept
* an equivalent pointer to a new (winning) Grand Masters Announce Packet
* information. The CurrentBmc data structure is then updated with the
* information from the NewMaster.
*
* @param NewMaster is a pointer to a suitable data structure which has recorded
* the relevent Announce Packet fields of the new (winning) Grand Master.
* @param CurrentBmc is a pointer to a suitable data structure which has
* recorded the current fields of the current Grand Master's Announce
* Packet.
*
* @return The CurrentBmc data structure is updated.
*
* @note None.
*
*****************************************************************************/
void XAvb_UpdateBmcRecords(XAvb_BmcData* NewMaster,
XAvb_BmcData* CurrentBmc) {
CurrentBmc->SourcePortIdentity.ClockIdentityUpper =
NewMaster->SourcePortIdentity.ClockIdentityUpper;
CurrentBmc->SourcePortIdentity.ClockIdentityLower =
NewMaster->SourcePortIdentity.ClockIdentityLower;
CurrentBmc->SourcePortIdentity.PortNumber =
NewMaster->SourcePortIdentity.PortNumber;
CurrentBmc->GrandmasterIdentity.ClockIdentityUpper =
NewMaster->GrandmasterIdentity.ClockIdentityUpper;
CurrentBmc->GrandmasterIdentity.ClockIdentityLower =
NewMaster->GrandmasterIdentity.ClockIdentityLower;
CurrentBmc->stepsRemoved = NewMaster->stepsRemoved;
CurrentBmc->ClockQuality = NewMaster->ClockQuality;
CurrentBmc->GrandmasterPriority1 = NewMaster->GrandmasterPriority1;
CurrentBmc->GrandmasterPriority2 = NewMaster->GrandmasterPriority2;
}
/****************************************************************************/
/**
*
* This function will make any adjustments needed when the node becomes the Grand
* Master, including resetting the RTC to its nominal value
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @param txAnnounceHasWon indicates that this function has been called from
* the function XAvb_DecodeTxAnnounceFrame(). Is this is set then this
* function has no need to repeat actions that have been already performed.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_BecomeRtcMaster(XAvb *InstancePtr,
u8 txAnnounceHasWon) {
XAvb_BmcData deviceData;
if (txAnnounceHasWon == 0) {
/**
* Update the BMCA records to this device's information
*/
/** Read the attributes in the Tx PTP buffer */
XAvb_ReadAnnounceFrame(InstancePtr->Config.BaseAddress,
(XAVB_PTP_TX_ANNOUNCE_OFFSET + 8),
&deviceData);
/** Update records */
XAvb_UpdateBmcRecords(&deviceData,
&InstancePtr->CurrentBmc);
}
/** reset the RTC to a nominal value */
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_INCREMENT_OFFSET,
XAVB_RTC_INCREMENT_NOMINAL_RATE);
/** set timestamp uncertainty if new status */
if( !InstancePtr->CurrentBmc.IAmTheRtcMaster ) {
xil_printf("\r\n*** I am now the Grand Master ***");
xil_printf("\r\nNOTICE: timestamps are now certain\r\n");
InstancePtr->GMDiscHandler(InstancePtr->GMDiscCallBackRef,
0);
}
/** inform the rest of the system */
InstancePtr->CurrentBmc.IAmTheRtcMaster = 1;
}
/****************************************************************************/
/**
*
* This function will make any adjustments needed when the node becomes a PTP slave
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_BecomeRtcSlave(XAvb *InstancePtr) {
/** set timestamp uncertainty if new status */
if( InstancePtr->CurrentBmc.IAmTheRtcMaster ) {
xil_printf("\r\n*** I am now a PTP slave ***");
xil_printf("\r\nNOTICE: timestamps are now uncertain\r\n");
InstancePtr->GMDiscHandler(InstancePtr->GMDiscCallBackRef,
1);
}
/* Reset the syncReceiptTimeoutTimeInterval counter as this has now changed purpose
*/
InstancePtr->PtpCounters.CounterSyncInterval = 0;
/* inform the rest of the system */
InstancePtr->CurrentBmc.IAmTheRtcMaster = 0;
}
/****************************************************************************/
/**
*
* Operations needed when PTP locks or unlocks
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
* @param locked is 1 if changing to locked status, zero if unlocked
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_ChangePTPLockStatus(XAvb *InstancePtr, u8 locked) {
u32 lockedOld;
u32 tu = 0;
lockedOld = InstancePtr->PTPLocked;
/** set status variable */
InstancePtr->PTPLocked = locked;
/** set timestamp uncertainty if necessary */
if( InstancePtr->PTPLocked != lockedOld ) {
XAvb_ChangePeerASCapability(InstancePtr, locked);
#ifdef XAVB_DEBUG_LEVEL2
if (locked == 0) {
xil_printf("\r\nXAvb_ChangePTPLockStatus():The peer is no longer ASCapable ");
xil_printf("\r\nXAvb_ChangePTPLockStatus():locked = %d\r\n",locked);
}
#endif
tu = InstancePtr->PTPLocked ? 0 : 1;
xil_printf("\r\nXAvb_ChangePTPLockStatus()::");
xil_printf("\r\nNOTICE: timestamps are now %s\r\n", tu ? "uncertain" : "certain");
InstancePtr->GMDiscHandler(InstancePtr->GMDiscCallBackRef,
tu);
}
}
/****************************************************************************/
/**
*
* Operations needed when the peer's AS capability changes
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
* @param capable is 1 if the peer is ASCapable, 0 otherwise
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_ChangePeerASCapability(XAvb *InstancePtr, u8 capable) {
u32 capableOld;
capableOld = InstancePtr->PeerASCapable;
/* set status variable */
InstancePtr->PeerASCapable = capable;
if( capable != capableOld ) {
if( capable ) {
xil_printf("\r\nThe Peer is now AS Capable\r\n");
} else {
xil_printf("\r\nThe Peer is no longer AS Capable\r\n");
}
}
}
/****************************************************************************/
/**
*
* This function sets the handler that will be called when a GM discontinuity
* event is identified by the driver. The purpose of the handler is to allow
* application specific processing to be performed.
*
* @param InstancePtr is a pointer to the XAvb instance.
* @param FuncPtr is the pointer to the callback function.
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
*
* @return None.
*
* @note There is no assert on the CallBackRef since the driver doesn't
* know what it is (nor should it)
*
*****************************************************************************/
void XAvb_SetGMDiscontinuityHandler(XAvb *InstancePtr,
XAvb_Handler FuncPtr, void *CallBackRef)
{
/*
* Assert validates the input arguments
* CallBackRef not checked, no way to know what is valid
*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(FuncPtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
InstancePtr->GMDiscHandler = FuncPtr;
InstancePtr->GMDiscCallBackRef = CallBackRef;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,640 @@
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/***
*
* @file xavb_rtc_sync.c
*
* The XAvb driver. Functions in this file all contain calculations which are
* essential for the AVB (1588 based) Real Time Clock (RTC) Sychronisation. In
* here are functions to measure the Link Delay (Master and Slave); to measure
* and correct the current RTC error (Slave); to measure and correct the current
* RTC increment rate error.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a mbr 09/19/08 First release
* 1.01a mbr 06/24/09 PTP frame format updates for IEEE802.1 AS draft 5-0
* 2_02a mbr 09/16/09 Updates for programmable PTP timers
* 2_04a kag 07/23/10 PTP frame format updates for IEEE802.1 AS draft 6-7
* 3_01a kag 08/29/11 Added new APIs to update the RX Filter Control Reg.
* Fix for CR:572539. Updated bit map for Rx Filter
* control reg.
*
* </pre>
*
******************************************************************************/
/****************************** Include Files *********************************/
#include "xil_types.h"
#include "xavb_hw.h"
#include "xavb.h"
/*************************** Constant Definitions *****************************/
/***************************** Type Definitions *******************************/
/****************** Macros (Inline Functions) Definitions *********************/
/*************************** Variable Definitions *****************************/
/*************************** Function Prototypes ******************************/
/******************************************************************************/
/*****************************************************************************/
/***
*
* A function to capture the nanosecond timestamp field from a received PTP frame
*
* @param BaseAddress is the base address of the device
* @param PtpFrameBaseAddr is the base address of the received Announce Packet
* in the Rx PTP Packet Buffer
*
* @return The Nanoseconds Timestamp field, captured from an Rx PTP frame
*
* @note None.
*
*****************************************************************************/
u32 XAvb_CaptureNanoSec(u32 BaseAddress, u32 PtpFrameBaseAddr) {
u32 Timestamp = 0;
u32 BufferWordA = 0;
u32 BufferWordB = 0;
/** The timestamp is located over several 32-bit Words of the PTP frame buffer
* Read the relevant Words containing the ns timestamp: */
BufferWordA = XAvb_ReadPtpBuffer(BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_TIMESTAMP_MID_OFFSET);
BufferWordB = XAvb_ReadPtpBuffer(BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_TIMESTAMP_LOWER_OFFSET);
/** Now re-arrange the data from the Words to obtain the required ns Timestamp
* in binrary format */
Timestamp = (XAvb_ReorderWord(BufferWordA)<<16) |
(XAvb_ReorderWord(BufferWordB)>>16);
return Timestamp;
}
/*****************************************************************************/
/***
*
* A function to Measure the Link Delay of the local full-duplex Ethernet link
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XAvb_CalcDelay(XAvb * InstancePtr) {
u32 T4MinusT1 = 0;
u32 T3MinusT2 = 0;
u32 Delay = 0;
/** Since we are only using the nanoseconds field here we need to account for
* wrap. So we add one second to the T4 and T3 terms to ensure that the
* T4MinusT1 and T3MinusT2 results cannot be negative. These two additional
* seconds then cancel each other out in the T4MinusT1 - T3MinusT2 equation.
*/
#ifdef DEBUG_XAVB_LEVEL2
xil_printf("\r\nXAvb_CalcDelay()");
xil_printf("\r\nt1 %x ", InstancePtr->PtpRecords.PDelayTimestampT1);
xil_printf("\r\nt2 %x ", InstancePtr->PtpRecords.PDelayTimestampT2);
xil_printf("\r\nt3 %x ", InstancePtr->PtpRecords.PDelayTimestampT3);
xil_printf("\r\nt4 %x ", InstancePtr->PtpRecords.PDelayTimestampT4);
#endif
/** If the nanoseconds count has wrapped, add on 1 second to ensure we get the right answer*/
if (InstancePtr->PtpRecords.PDelayTimestampT4 < InstancePtr->PtpRecords.PDelayTimestampT1) {
T4MinusT1 = (InstancePtr->PtpRecords.PDelayTimestampT4 + XAVB_ONE_SECOND)
- InstancePtr->PtpRecords.PDelayTimestampT1;
} else {
T4MinusT1 = InstancePtr->PtpRecords.PDelayTimestampT4
- InstancePtr->PtpRecords.PDelayTimestampT1;
}
/** If the nanoseconds count has wrapped, add on 1 second to ensure we get the right answer*/
if (InstancePtr->PtpRecords.PDelayTimestampT3 < InstancePtr->PtpRecords.PDelayTimestampT2) {
T3MinusT2 = (InstancePtr->PtpRecords.PDelayTimestampT3 + XAVB_ONE_SECOND)
- InstancePtr->PtpRecords.PDelayTimestampT2;
} else {
T3MinusT2 = InstancePtr->PtpRecords.PDelayTimestampT3
- InstancePtr->PtpRecords.PDelayTimestampT2;
}
Delay = (T4MinusT1 - T3MinusT2) >> 1;
/** For now we are simply going to throw out any absurdly large link delays.*/
if (Delay < XAVB_NEIGHBOR_PROP_DELAY_THRESH ) {
InstancePtr->PtpRecords.LinkDelay = Delay;
/** The peer has responded to the pDelay_Req and the measured delay is
* within tolerance: the peer is deemed to be AS capable */
XAvb_ChangePeerASCapability(InstancePtr, 1);
} else {
xil_printf("\r\n Bad Link Delay %d ", Delay);
#ifdef DEBUG_XAVB_LEVEL2
xil_printf("\r\nXAvb_CalcDelay()");
xil_printf("\r\nt1 %x ", InstancePtr->PtpRecords.PDelayTimestampT1);
xil_printf("\r\nt2 %x ", InstancePtr->PtpRecords.PDelayTimestampT2);
xil_printf("\r\nt3 %x ", InstancePtr->PtpRecords.PDelayTimestampT3);
xil_printf("\r\nt4 %x ", InstancePtr->PtpRecords.PDelayTimestampT4);
xil_printf("\r\nLinkDelay %x ", InstancePtr->PtpRecords.LinkDelay);
#endif
}
}
/*****************************************************************************/
/***
*
* A function to calculate the Slave Offset from the GrandMaster time
*
* @param InstancePtr is a pointer to the XAvb instance to be worked on
* @param PtpFrameBaseAddr is the base address of the received Announce Packet
* in the Rx PTP Packet Buffer
*
* @return The PtpRecords data structure is updated with the calculated RTC
* Offset value.
*
* @note None.
*
*****************************************************************************/
void XAvb_CalcRtcOffset (XAvb * InstancePtr,
u32 PtpFrameBaseAddr) {
u32 MasterNanosec = 0;
u32 MasterSeconds = 0;
u32 MasterEpoch = 0;
u32 SyncRouteDelay = 0;
u32 MasterNsCorrected = 0;
u32 MasterNsHasWrapped = 0;
u32 SlaveNsTimestamp = 0;
XAvb_RtcFormat RtcError;
u32 BufferWordA = 0;
u32 BufferWordB = 0;
XAvb_RtcFormat SlaveRtc;
/** Capture the Slave Time
* ----------------------------
* We do this immediately to get the slave time ASAP (since processing
* time is uncertain and the RTC does not stand still). */
XAvb_ReadRtc(InstancePtr->Config.BaseAddress, &SlaveRtc);
/** Capture the Master Origin Timestamp (from received FollowUp Frame)
* ---------------------------- */
MasterNanosec = XAvb_CaptureNanoSec(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr);
/** read the Words from the PTP frame buffer containing the RTC seconds field
*/
BufferWordA = XAvb_ReadPtpBuffer(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_TIMESTAMP_UPPER_OFFSET);
BufferWordB = XAvb_ReadPtpBuffer(InstancePtr->Config.BaseAddress,
PtpFrameBaseAddr,
XAVB_PTP_RX_PKT_TIMESTAMP_MID_OFFSET);
/** Now re-arrange the required data from the Words to obtain the required
* seconds field timestamp in binary format */
MasterSeconds = (XAvb_ReorderWord(BufferWordA) << 16) |
(XAvb_ReorderWord(BufferWordB) >> 16);
MasterEpoch = XAvb_ReorderWord(BufferWordA) >> 16;
/** Correct the Nanoseconds
* ----------------------------
* NOTE: we are trying to compare the value of the slave RTC nano-
* seconds field timestamp with the nano-seconds value of the Masters
* RTC nanosecond field at exactly that time.
*
*
* Sync Frame routing delay is equal to the value of the correction
* field (sum of correction fields in Sync and FollowUp frames) plus
* the link delay measurement made by this slave.
*/
SyncRouteDelay = InstancePtr->PtpRecords.MasterCorrectionField
+ InstancePtr->PtpRecords.LinkDelay;
/** MasterNsCorrected time here is the calculated time that the
* master will be at the point in time when the sync frame is received
* (and timestamped) at the slave. This is calculated from the
* originTimeStamp (from the FollowUpframe), plus the Sync Frame
* routing delay. A direct comparison can then be made between master
* and slave.
*/
MasterNsCorrected = MasterNanosec + SyncRouteDelay;
/** Check for ns wrap-around condition */
if (MasterNsCorrected >= XAVB_ONE_SECOND) {
MasterNsCorrected = MasterNsCorrected - XAVB_ONE_SECOND;
MasterNsHasWrapped = 1;
}
/** Make the Master and Slave comparison and discover the difference! */
RtcError.NanoSeconds = MasterNsCorrected
- InstancePtr->PtpRecords.SlaveSyncTimestamp;
/** Check for ns wrap-around condition */
if (RtcError.NanoSeconds >= XAVB_ONE_SECOND) {
RtcError.NanoSeconds = RtcError.NanoSeconds + XAVB_ONE_SECOND;
}
/** Return these comparison figures in the form of a pointer (RTC
* increment rate adjust function also needs to know this information) */
InstancePtr->PtpRecords.NewSlaveTime
= InstancePtr->PtpRecords.SlaveSyncTimestamp;
InstancePtr->PtpRecords.NewMasterTime = MasterNsCorrected;
/** Adjust the 8k clock logic (if necessary) */
XAvb_Adjust8kClock(InstancePtr->Config.BaseAddress, RtcError.NanoSeconds);
/** Correct the Seconds and Epoch
* -----------------------------
* NOTE: we are trying to compare the value of the slave RTC seconds
* field at the exact time when the timestamp was taken with the
* RTC seconds value of the Master at that time.
*
*
* We need to know the value of the slaves synchronised nano-seconds
* field at the time when the timestamp was taken (since timestamps
* use the syntonised time). So we add the current nanosecond field
* offset value:
*/
SlaveNsTimestamp = InstancePtr->PtpRecords.SlaveSyncTimestamp
+ XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_NANOSEC_OFFSET);
/** Check for ns wrap-around condition */
if (SlaveNsTimestamp >= XAVB_ONE_SECOND) {
SlaveNsTimestamp = SlaveNsTimestamp - XAVB_ONE_SECOND;
}
/** Even though we read the slave RTC value at the beginning of this
* function, there would have been processing delay between the
* actual reception (and timestamping) of the FollowUp frame and the
* start of this function. During this time, the slave RTC seconds
* field could have wrapped around. We need to detect this and if it
* has done, the slave seconds field would also have incremented (so
* it needs to be set back).
*/
if (SlaveRtc.NanoSeconds < SlaveNsTimestamp) {
/** slave_nanosec has wrapped since timestamp so decrement the
* seconds field */
if (SlaveRtc.SecondsLower == 0x00000000) {
SlaveRtc.SecondsUpper = SlaveRtc.SecondsUpper - 0x1;
}
SlaveRtc.SecondsLower = SlaveRtc.SecondsLower - 0x1;
}
/** If the Master nano seconds field wrapped during the Sync frame
* routing delay, then we need to increment the seconds field.
*/
if (MasterNsHasWrapped == 1) {
if (MasterSeconds == 0xFFFFFFFF) {
MasterEpoch = MasterEpoch + 0x1;
}
MasterSeconds = MasterSeconds + 0x1;
}
/** Calculate the slave RTC error: the master time minus the timestamp
* taken by this slave for Sync Frame reception. */
RtcError.SecondsLower = MasterSeconds - SlaveRtc.SecondsLower;
RtcError.SecondsUpper = MasterEpoch - SlaveRtc.SecondsUpper;
#ifdef DEBUG_XAVB_LEVEL2
if (RtcError.SecondsLower != 0) {
xil_printf("\r\nXAvb_CalcRtcOffset()");
xil_printf("\r\n-- Seconds Field Correction");
xil_printf("\r\nSlaveNsTimestamp : %x" , SlaveNsTimestamp);
xil_printf("\r\nslave_ns : %x", SlaveRtc.NanoSeconds);
xil_printf("\r\n--");
xil_printf("\r\nread slave seconds : %x",
XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_SEC_LOWER_VALUE_OFFSET));
xil_printf("\r\ncalc slave secs : %x", SlaveRtc.SecondsLower);
xil_printf("\r\n--");
xil_printf("\r\nmaster sec wrap : %x" , MasterNsHasWrapped);
xil_printf("\r\ncalc master_secs : %x" , MasterSeconds);
xil_printf("\r\nrtc_sec_error : %x" , RtcError.SecondsLower);
xil_printf("\r\n--");
}
#endif
/** Write the results to the RTC Offset registers
* --------------------------------------------- */
XAvb_WriteRtcOffset(InstancePtr->Config.BaseAddress, &RtcError);
}
/*****************************************************************************/
/***
*
* A function to Adjust the phase offset of the 8k clock
*
* @param InstancePtr->BaseAddress is the base address of the device
* @param NewOffset is the newly calculated RTC Offset value
*
* @return None. But the devices RTC Phase Adjustment Register is updated
*
* @note None.
*
*****************************************************************************/
void XAvb_Adjust8kClock (u32 BaseAddress, u32 NewOffset) {
u32 PreviousOffset = 0;
u32 OffsetChange = 0;
u32 ChangeIn8kPeriods = 0;
#ifdef DEBUG_XAVB_LEVEL2
u32 Clock8kOffset = 0;
#endif
/** Read the previous offset */
PreviousOffset = XAvb_ReadReg(BaseAddress, XAVB_RTC_NANOSEC_OFFSET);
/** Calculate the change in the previous and current RTC ns offset */
if (PreviousOffset > NewOffset) {
OffsetChange = PreviousOffset - NewOffset;
} else {
OffsetChange = NewOffset - PreviousOffset;
}
/** Is the adjustment "large"? "large" is chosen here to be one 8k
* clock period which is a somewhat arbitrary figure */
if (OffsetChange > XAVB_PERIOD_8KHZ) {
#ifdef DEBUG_XAVB_LEVEL2
Clock8kOffset = XAvb_ReadReg(BaseAddress, XAVB_RTC_8K_OFFSET_OFFSET);
xil_printf("\r\nXAvb_Adjust8kClock()");
xil_printf("\r\nold ns offset: %x" , PreviousOffset);
xil_printf("\r\nold Clk8kOffset: %x", Clock8kOffset);
#endif
/** The value XAVB_PERIOD_8KHZ is one 8k clock period in ns. We divide the
* RTC ns offset change by this to get the offset change in a
* multiple of 8k clock periods, the add 1 so that we always round
* up. Then multiply this by XAVB_PERIOD_8KHZ again so that we are always
* phased aligned to the RTC master (only evey adjust in a multiple
* of 8k periods.
*/
ChangeIn8kPeriods = NewOffset / XAVB_PERIOD_8KHZ;
OffsetChange = (ChangeIn8kPeriods + 1) * XAVB_PERIOD_8KHZ;
/** Write the results to the 8K clock logic Offset register */
XAvb_WriteReg(BaseAddress, XAVB_RTC_8K_OFFSET_OFFSET, OffsetChange);
#ifdef DEBUG_XAVB_LEVEL2
xil_printf("\r\nXAvb_Adjust8kClock()");
xil_printf("\r\nnew ns offset: %x" , NewOffset);
xil_printf("\r\nnew Clk8kOffset: %x", OffsetChange);
#endif
}
}
/*****************************************************************************/
/***
*
* A function to calculate the RTC increment value based on the Slave Error
*
* @return None. But the devices RTC Increment Value Control Register is updated
*
* @note None.
*
*****************************************************************************/
void XAvb_UpdateRtcIncrement(XAvb * InstancePtr) {
u32 LoopCount = 31;
u8 SlaveIsFast = 0;
u32 SlaveTimeDuration = 0;
u32 MasterTimeDuration = 0;
u32 SlaveError = 0;
u32 ScaledError = 0;
u32 NormalisedError = 0;
u32 IncrementAdjust = 0;
u32 OldIncrement = 0;
u32 NewIncrement = 0;
/** Sanity Check that Sync Frames were n apart. This safeguards the
* calculation against the ethernet cable being pulled out and then
* replaced, etc. */
if ( ((InstancePtr->SequenceIdRecords.OldSyncSequenceId +
XAVB_NUM_SYNC_FU_PAIR_CALC_RTC_INCREMENT) & 0xFFFF) ==
InstancePtr->SequenceIdRecords.NewSyncSequenceId ) {
#ifdef DEBUG_XAVB_LEVEL2
xil_printf("\r\nXAvb_UpdateRtcIncrement(): Debug...(a)");
xil_printf("\r\nNewMasterTime : %x, %d" , InstancePtr->PtpRecords.NewMasterTime, InstancePtr->PtpRecords.NewMasterTime);
xil_printf("\r\nOldMasterTime : %x, %d" , InstancePtr->PtpRecords.OldMasterTime, InstancePtr->PtpRecords.OldMasterTime);
xil_printf("\r\nNewSlaveTime : %x, %d" , InstancePtr->PtpRecords.NewSlaveTime, InstancePtr->PtpRecords.NewSlaveTime);
xil_printf("\r\nOldSlaveTime : %x, %d\r\n" , InstancePtr->PtpRecords.OldSlaveTime, InstancePtr->PtpRecords.OldSlaveTime);
#endif
/** Measure the time duration, as measured by the RTC master of the
* M sync delay measurment period. */
MasterTimeDuration = (InstancePtr->PtpRecords.NewMasterTime
- InstancePtr->PtpRecords.OldMasterTime);
if (MasterTimeDuration >= XAVB_ONE_SECOND) {
MasterTimeDuration = MasterTimeDuration + XAVB_ONE_SECOND;
}
/** Measure the time duration, as measured by the RTC slave of the
* M sync delay measurment period. */
SlaveTimeDuration = (InstancePtr->PtpRecords.NewSlaveTime
- InstancePtr->PtpRecords.OldSlaveTime);
if (SlaveTimeDuration >= XAVB_ONE_SECOND) {
SlaveTimeDuration = SlaveTimeDuration + XAVB_ONE_SECOND;
}
/** Therefore calculate the slave error (in ns) */
SlaveError = MasterTimeDuration - SlaveTimeDuration;
/** If the slave error is zero, skip the remainder of function.
* (Note : a zero error would otherwise get stuck in the while loop
* further down this function). */
if (SlaveError != 0) {
/** Analyse msb of error signal to see which clock is running fastest */
if (SlaveError & 0x80000000) {
SlaveIsFast = 1;
SlaveError = SlaveTimeDuration - MasterTimeDuration;
} else {
SlaveIsFast = 0;
}
/** This check is in addition to the checks described in IEEE802.1as.
* If the SlaveError is unexpectedly large, then set asCapable to 0.
*/
if (SlaveError < XAVB_CLOCK_LOCK_THRESHOLD) {
XAvb_ChangePTPLockStatus(InstancePtr, 1);
} else {
XAvb_ChangePTPLockStatus(InstancePtr, 0);
}
/** SlaveError signal is 32-bits (ns). This can indicate > 4 sec of
* error: this is too large for 100 ms measurement period. So we
* expect upper bits to be zero.
*
* This function will shift the 1st none zero bit of SlaveError up
* to bit 31, so that forthcoming calculation uses maximum accuracy.
*
* This shift is equivalent to a multiply (of the error signal). A
* shift the opposite way (equivalent to a divide) will follow at
* end of full calculation. */
while ( !(SlaveError & (0x1 << LoopCount)) ) {
LoopCount = LoopCount - 1;
}
LoopCount = 31 - LoopCount;
ScaledError = (SlaveError << LoopCount);
/** Calculate the relative error: can be thought of as a scaled ratio
* of error per time unit */
NormalisedError = ScaledError / MasterTimeDuration;
/** Obtain the current increment value */
OldIncrement = (XAvb_ReadReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_INCREMENT_OFFSET)
& XAVB_RTC_INCREMENT_VALUE_MASK);
/** Calculate the increment adjustment: multiply NormalisedError by
* the increment time unit. Then shift back the other way to
* correct the calculation (restore to ns). */
IncrementAdjust = (NormalisedError * OldIncrement) >> LoopCount;
/** Now calculate the new increment value */
if (SlaveIsFast) {
NewIncrement = OldIncrement - IncrementAdjust;
} else {
NewIncrement = OldIncrement + IncrementAdjust;
}
/** Add some rails so that recovery is possible after a
* string of bad pDelay values. The RTC should be able to lock
* to within 100ppm of the slowest allowable clock (25 MHz).
* This equates to +/-4ps. Let's arbitrarily set the rails to
* 400ppm (+/-16ps) just in case someone decides to use a
* particularly bad oscillator. The lowest 20 bits of
* NewIncrement are fractions of a nanosecond, which equates
* to +/- 0x04189
*/
if( NewIncrement > (XAVB_RTC_INCREMENT_NOMINAL_RATE + XAVB_RTC_400PPM_OFFSET) ) {
xil_printf("\r\nRTC Exceeded 400ppm offset: Railing to 400ppm\r\n");
NewIncrement = XAVB_RTC_INCREMENT_NOMINAL_RATE + XAVB_RTC_400PPM_OFFSET;
}
if( NewIncrement < (XAVB_RTC_INCREMENT_NOMINAL_RATE - XAVB_RTC_400PPM_OFFSET) ) {
xil_printf("\r\nRTC Exceeded 400ppm offset: Railing to 400ppm\r\n");
NewIncrement = XAVB_RTC_INCREMENT_NOMINAL_RATE - XAVB_RTC_400PPM_OFFSET;
}
/** And write the new increment value! */
XAvb_WriteReg(InstancePtr->Config.BaseAddress,
XAVB_RTC_INCREMENT_OFFSET,
NewIncrement);
#ifdef DEBUG_XAVB_LEVEL2
xil_printf("\r\nXAvb_UpdateRtcIncrement(): Debug...");
xil_printf("\r\nM Time : %x" , MasterTimeDuration);
xil_printf("\r\nS Time : %x" , SlaveTimeDuration);
xil_printf("\r\nErr : %x %x" , SlaveIsFast, SlaveError);
xil_printf("\r\nScaled : %x" , ScaledError);
xil_printf("\r\nNorm : %x" , NormalisedError);
xil_printf("\r\nAdjust : %x" , IncrementAdjust);
xil_printf("\r\nNew Inc: %x" , NewIncrement);
#endif
}
} else {
xil_printf("\r\nXAvb_UpdateRtcIncrement()");
xil_printf("\r\nERROR: Syncs not %d apart - %d\r\n",
XAVB_NUM_SYNC_FU_PAIR_CALC_RTC_INCREMENT,
InstancePtr->SequenceIdRecords.NewSyncSequenceId -
InstancePtr->SequenceIdRecords.OldSyncSequenceId);
}
if (SlaveError > 0x2700) {
xil_printf("\r\nXAvb_UpdateRtcIncrement(): Large Error over 100ms");
xil_printf("\r\nM Time : %x" , MasterTimeDuration);
xil_printf("\r\nS Time : %x" , SlaveTimeDuration);
xil_printf("\r\nErr : %x %x" , SlaveIsFast, SlaveError);
xil_printf("\r\nScaled : %x" , ScaledError);
xil_printf("\r\nNorm : %x" , NormalisedError);
xil_printf("\r\nAdjust : %x" , IncrementAdjust);
xil_printf("\r\nNew Inc: %x" , NewIncrement);
}
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver axiethernet_v4_2 </h1>
<HR>
<ul>
<li>xaxiethernet_example_extvlan.c <a href="xaxiethernet_example_extvlan.c">(source)</a> </li>
<li>xaxiethernet_example_extmulticast.c <a href="xaxiethernet_example_extmulticast.c">(source)</a> </li>
<li>xaxiethernet_example_intr_fifo.c <a href="xaxiethernet_example_intr_fifo.c">(source)</a> </li>
<li>xaxiethernet_example_intr_sgdma.c <a href="xaxiethernet_example_intr_sgdma.c">(source)</a> </li>
<li>xaxiethernet_example_polled.c <a href="xaxiethernet_example_polled.c">(source)</a> </li>
<li>xaxiethernet_example_util.c <a href="xaxiethernet_example_util.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 1995-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,124 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xaxiethernet_example.h
*
* Defines common data types, prototypes, and includes the proper headers
* for use with the Axi Ethernet example code residing in this directory.
*
* This file along with xaxiethernet_example_util.c are utilized with the
* specific example code in the other source code files provided.
*
* These examples are designed to be compiled and utilized within the EDK
* standalone BSP development environment. The readme file contains more
* information on build requirements needed by these examples.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa 4/30/10 First release based on the ll temac driver
* 3.02a srt 4/26/13 Added function prototype for *_ConfigureInternalPhy().
*
* </pre>
*
******************************************************************************/
#ifndef XAXIETHERNET_EXAMPLE_H
#define XAXIETHERNET_EXAMPLE_H
/***************************** Include Files *********************************/
#include "xparameters.h" /* defines XPAR values */
#include "xaxiethernet.h" /* defines Axi Ethernet APIs */
#include "stdio.h" /* stdio */
/************************** Constant Definitions ****************************/
#define AXIETHERNET_LOOPBACK_SPEED 100 /* 100Mb/s for Mii */
#define AXIETHERNET_LOOPBACK_SPEED_1G 1000 /* 1000Mb/s for GMii */
#define AXIETHERNET_PHY_DELAY_SEC 4 /*
* Amount of time to delay waiting on
* PHY to reset.
*/
#define MAX_MULTICAST_ADDR (1<<23) /*
* Maximum number of multicast ethernet
* mac addresses.
*/
/***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions ******************************/
/*
* Define an aligned data type for an ethernet frame. This declaration is
* specific to the GNU compiler
*/
typedef unsigned char EthernetFrame[XAE_MAX_JUMBO_FRAME_SIZE] __attribute__ ((aligned(64)));
/************************** Function Prototypes *****************************/
/*
* Utility functions implemented in xaxiethernet_example_util.c
*/
void AxiEthernetUtilSetupUart(void);
void AxiEthernetUtilFrameHdrFormatMAC(EthernetFrame * FramePtr,
char *DestAddr);
void AxiEthernetUtilFrameHdrFormatType(EthernetFrame * FramePtr,
u16 FrameType);
void AxiEthernetUtilFrameSetPayloadData(EthernetFrame * FramePtr,
int PayloadSize);
void AxiEthernetUtilFrameHdrVlanFormatVid(EthernetFrame * FramePtr,
u32 VlanNumber,u32 Vid);
void AxiEthernetUtilFrameHdrVlanFormatType(EthernetFrame * FramePtr,
u16 FrameType,u32 VlanNumber);
void AxiEthernetUtilFrameSetVlanPayloadData(EthernetFrame * FramePtr,
int PayloadSize,u32 VlanNumber);
int AxiEthernetUtilFrameVerify(EthernetFrame * CheckFrame,
EthernetFrame * ActualFrame);
void AxiEthernetUtilFrameMemClear(EthernetFrame * FramePtr);
int AxiEthernetUtilEnterLoopback(XAxiEthernet * AxiEthernetInstancePtr,
int Speed);
void AxiEthernetUtilErrorTrap(char *Message);
void AxiEthernetUtilPhyDelay(unsigned int Seconds);
int AxiEthernetUtilConfigureInternalPhy(XAxiEthernet *AxiEthernetInstancePtr,
int Speed);
/************************** Variable Definitions ****************************/
extern char AxiEthernetMAC[]; /* Local MAC address */
#endif /* XAXIETHERNET_EXAMPLE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,805 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xaxiethernet_example_polled.c
*
* Implements examples that utilize the Axi Ethernet's FIFO direct frame transfer
* mode in a polled fashion to send and receive frames.
*
* These examples demonstrate:
*
* - How to perform simple polling send and receive.
* - Advanced frame processing
* - Error handling
*
* Functional guide to example:
*
* - AxiEthernetSingleFramePolledExample() demonstrates the simplest way to send
* and receive frames in polled mode.
*
* - AxiEthernetMultipleFramesPolledExample() demonstrates how to transmit a
* "burst" of frames by queueing up several in the packet FIFO prior to
* transmission.
*
* - AxiEthernetPollForTxStatus() demonstrates how to poll for transmit complete
* status and how to handle error conditions.
*
* - AxiEthernetPollForRxStatus() demonstrates how to poll for receive status and
* how to handle error conditions.
*
* - AxiEthernetResetDevice() demonstrates how to reset the driver/HW without
* losing all configuration settings.
*
* Note that the advanced frame processing algorithms shown here are not limited
* to polled mode operation. The same techniques can be used for FIFO direct
* interrupt driven mode as well.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa 4/30/10 First release based on the ll temac driver
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xaxiethernet_example.h"
#include "xllfifo.h"
#include "xil_cache.h"
#ifdef XPAR_XUARTNS550_NUM_INSTANCES
#include "xuartns550_l.h"
#endif
/************************** Constant Definitions ****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#ifndef TESTAPP_GEN
#define AXIETHERNET_DEVICE_ID XPAR_AXIETHERNET_0_DEVICE_ID
#define FIFO_DEVICE_ID XPAR_AXI_FIFO_0_DEVICE_ID
#endif
/************************** Variable Definitions ****************************/
EthernetFrame TxFrame; /* Transmit frame buffer */
EthernetFrame RxFrame; /* Receive frame buffer */
XAxiEthernet AxiEthernetInstance;
XLlFifo FifoInstance;
/************************** Function Prototypes *****************************/
int AxiEthernetPolledExample(u16 AxiEthernetDeviceId, u16 FifoDeviceId);
int AxiEthernetSingleFramePolledExample();
int AxiEthernetMultipleFramesPolledExample();
int AxiEthernetPollForTxStatus();
int AxiEthernetPollForRxStatus();
int AxiEthernetResetDevice();
/*****************************************************************************/
/**
*
* This is the main function for the AxiEthernet example. This function is not
* included if the example is generated from the TestAppGen test tool.
*
* @param None.
*
* @return -XST_SUCCESS to indicate success
* -XST_FAILURE to indicate failure
*
*
* @note None.
*
****************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
#ifdef XPAR_XUARTNS550_NUM_INSTANCES
XUartNs550_SetBaud(STDIN_BASEADDRESS, XPAR_XUARTNS550_CLOCK_HZ, 9600);
XUartNs550_SetLineControlReg(STDIN_BASEADDRESS, XUN_LCR_8_DATA_BITS);
#endif
#if XPAR_MICROBLAZE_USE_ICACHE
Xil_ICacheInvalidate();
Xil_ICacheEnable();
#endif
#if XPAR_MICROBLAZE_USE_DCACHE
Xil_DCacheInvalidate();
Xil_DCacheEnable();
#endif
AxiEthernetUtilErrorTrap("\r\n--- Enter main() ---");
AxiEthernetUtilErrorTrap("This test may take several minutes to finish");
/*
* Call the AxiEthernet polled example , specify the Device ID
* generated in xparameters.h
*/
Status = AxiEthernetPolledExample(AXIETHERNET_DEVICE_ID, FIFO_DEVICE_ID);
if (Status != XST_SUCCESS) {
AxiEthernetUtilErrorTrap("Failed test poll mode fifo");
return XST_FAILURE;
}
AxiEthernetUtilErrorTrap("Test passed");
AxiEthernetUtilErrorTrap("--- Exiting main() ---");
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function demonstrates the usage of the Axi Ethernet by sending and
* receiving frames in polled mode.
*
*
* @param AxiEthernetDeviceId is device ID of the AxiEthernet Device ,
* typically XPAR_<AXIETHERNET_instance>_DEVICE_ID value from
* xparameters.h
* @param FifoDeviceId is device ID of the Fifo device taken from
* xparameters.h
*
* @return -XST_SUCCESS to indicate success
* -XST_FAILURE to indicate failure
*
* @note AxiFifo hardware must be initialized before initializing
* AxiEthernet. Since AxiFifo reset line is connected to the
* AxiEthernet reset line, a reset of AxiFifo hardware during its
* initialization would reset AxiEthernet.
*
******************************************************************************/
int AxiEthernetPolledExample(u16 AxiEthernetDeviceId, u16 FifoDeviceId)
{
int Status;
XAxiEthernet_Config *MacCfgPtr;
int LoopbackSpeed;
/*************************************/
/* Setup device for first-time usage */
/*************************************/
/*
* Get the configuration of AxiEthernet hardware.
*/
MacCfgPtr = XAxiEthernet_LookupConfig(AxiEthernetDeviceId);
/*
* Check whether AXIFIFO is present or not
*/
if(MacCfgPtr->AxiDevType != XPAR_AXI_FIFO) {
AxiEthernetUtilErrorTrap
("Device HW not configured for FIFO mode\r\n");
return XST_FAILURE;
}
/*
* Initialize AXIFIFO hardware. AXIFIFO must be initialized before
* AxiEthernet. During AXIFIFO initialization, AXIFIFO hardware is
* reset, and since AXIFIFO reset line is connected to AxiEthernet,
* this would ensure a reset of AxiEthernet.
*/
XLlFifo_Initialize(&FifoInstance, MacCfgPtr->AxiDevBaseAddress);
/*
* Initialize AxiEthernet hardware.
*/
Status = XAxiEthernet_CfgInitialize(&AxiEthernetInstance, MacCfgPtr,
MacCfgPtr->BaseAddress);
if (Status != XST_SUCCESS) {
AxiEthernetUtilErrorTrap("Error in initialize");
return XST_FAILURE;
}
/*
* Set the MAC address
*/
Status = XAxiEthernet_SetMacAddress(&AxiEthernetInstance,
(u8 *) AxiEthernetMAC);
if (Status != XST_SUCCESS) {
AxiEthernetUtilErrorTrap("Error setting MAC address");
return XST_FAILURE;
}
/*
* Set PHY to loopback, speed depends on phy type.
* MII is 100 and all others are 1000.
*/
if (XAxiEthernet_GetPhysicalInterface(&AxiEthernetInstance) ==
XAE_PHY_TYPE_MII) {
LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED;
} else {
LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED_1G;
}
Status = AxiEthernetUtilEnterLoopback(&AxiEthernetInstance,
LoopbackSpeed);
if (Status != XST_SUCCESS) {
AxiEthernetUtilErrorTrap("Error setting the PHY loopback");
return XST_FAILURE;
}
/*
* Set PHY<-->MAC data clock
*/
Status = XAxiEthernet_SetOperatingSpeed(&AxiEthernetInstance,
(u16)LoopbackSpeed);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setting the operating speed of the MAC needs a delay. There
* doesn't seem to be register to poll, so please consider this
* during your application design.
*/
AxiEthernetUtilPhyDelay(2);
/****************************/
/* Run through the examples */
/****************************/
/*
* Run the Single Frame polled example
*/
Status = AxiEthernetSingleFramePolledExample();
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Run the Multiple Frames polled example
*/
Status = AxiEthernetMultipleFramesPolledExample();
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function demonstrates the usage of the Axi Ethernet by sending and
* receiving a single frame in polled mode.
*
* @param None.
*
* @return -XST_SUCCESS to indicate success
* -XST_FAILURE to indicate failure
*
* @note None.
*
******************************************************************************/
int AxiEthernetSingleFramePolledExample(void)
{
u32 FifoFreeBytes;
int PayloadSize = 100;
u32 TxFrameLength;
u32 RxFrameLength;
/*
* Start the Axi Ethernet device
*/
XAxiEthernet_Start(&AxiEthernetInstance);
/*
* Setup the packet to be transmitted
*/
AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC);
AxiEthernetUtilFrameHdrFormatType(&TxFrame, PayloadSize);
AxiEthernetUtilFrameSetPayloadData(&TxFrame, PayloadSize);
/*
* Clear out the receive packet memory area
*/
AxiEthernetUtilFrameMemClear(&RxFrame);
/*
* Calculate frame length (not including FCS)
*/
TxFrameLength = XAE_HDR_SIZE + PayloadSize;
/*******************/
/* Send the packet */
/*******************/
/*
* Wait for enough room in FIFO to become available
*/
do {
FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance);
} while (FifoFreeBytes < TxFrameLength);
/*
* Write the frame data to FIFO
*/
XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength);
/*
* Initiate transmit
*/
XLlFifo_TxSetLen(&FifoInstance, TxFrameLength);
/*
* Wait for status of the transmitted packet
*/
switch (AxiEthernetPollForTxStatus()) {
case XST_SUCCESS:/* Got a sucessfull transmit status */
break;
case XST_NO_DATA: /* Timed out */
AxiEthernetUtilErrorTrap("Tx timeout");
return XST_FAILURE;
default: /* Some other error */
return XST_FAILURE;
}
/**********************/
/* Receive the packet */
/**********************/
/*
* Wait for packet Rx
*/
switch (AxiEthernetPollForRxStatus()) {
case XST_SUCCESS:/* Got a sucessfull receive status */
break;
case XST_NO_DATA: /* Timed out */
AxiEthernetUtilErrorTrap("Rx timeout");
return XST_FAILURE;
default: /* Some other error */
return XST_FAILURE;
}
while(XLlFifo_RxOccupancy(&FifoInstance)) {
/*
* A packet as arrived, get its length
*/
RxFrameLength = XLlFifo_RxGetLen(&FifoInstance);
/*
* Read the received packet data
*/
XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength);
/*
* Verify the received frame length
*/
if ((RxFrameLength) != TxFrameLength) {
AxiEthernetUtilErrorTrap("Receive length incorrect");
return XST_FAILURE;
}
/*
* Validate frame data
*/
if (AxiEthernetUtilFrameVerify(&TxFrame, &RxFrame) != 0) {
AxiEthernetUtilErrorTrap("Receive Data mismatch");
return XST_FAILURE;
}
}
/*
* Stop device
*/
XAxiEthernet_Stop(&AxiEthernetInstance);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This example uses polled mode to queue up multiple frames in the packet
* FIFOs before sending them in a single burst. Receive packets are handled in
* a similar way.
*
* @param None.
*
* @return -XST_SUCCESS to indicate success
* -XST_FAILURE to indicate failure
*
* @note None.
*
******************************************************************************/
int AxiEthernetMultipleFramesPolledExample(void)
{
u32 FramesToLoopback;
u32 PayloadSize;
u32 TxFrameLength;
u32 RxFrameLength;
u32 FifoFreeBytes;
u32 Index;
/*
* Start the Axi Ethernet device
*/
XAxiEthernet_Start(&AxiEthernetInstance);
/*
* Setup the number of frames to loopback (FramesToLoopback) and the
* size of the frame (PayloadSize) to loopback. The default settings
* should work for every case. Modifying the settings can cause
* problems, see discussion below:
*
* If PayloadSize is set small and FramesToLoopback high, then it is
* possible to cause the transmit status FIFO to overflow.
*
* If PayloadSize is set large and FramesToLoopback high, then it is
* possible to cause the transmit packet FIFO to overflow.
*
* Either of these scenarios may be worth trying out to observe how
* the driver reacts. The exact values to cause these types of errors
* will vary due to the sizes of the FIFOs selected at hardware build
* time. But the following settings should create problems for all
* FIFO sizes:
*
* Transmit status FIFO overflow
* PayloadSize = 1
* FramesToLoopback = 1000
*
* Transmit packet FIFO overflow
* PayloadSize = 1500
* FramesToLoopback = 16
*
* These values should always work without error
* PayloadSize = 100
* FramesToLoopback = 5
*/
PayloadSize = 100;
FramesToLoopback = 5;
/*
* Calculate Tx frame length (not including FCS)
*/
TxFrameLength = XAE_HDR_SIZE + PayloadSize;
/*
* Setup the packet to be transmitted
*/
AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC);
AxiEthernetUtilFrameHdrFormatType(&TxFrame, PayloadSize);
AxiEthernetUtilFrameSetPayloadData(&TxFrame, PayloadSize);
/****************/
/* Send packets */
/****************/
/*
* Since we may be interested to see what happens when FIFOs overflow,
* don't check for room in the transmit packet FIFO prior to writing
* to it.
*/
/*
* Write frame data to FIFO
* Fifo core only allows loading and sending one frame at a time.
*/
for (Index = 0; Index < FramesToLoopback; Index++) {
/* Make sure there is room in the FIFO */
do {
FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance);
} while (FifoFreeBytes < TxFrameLength);
XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength);
XLlFifo_TxSetLen(&FifoInstance, TxFrameLength);
switch (AxiEthernetPollForTxStatus()) {
case XST_SUCCESS: /* Got a sucessfull transmit status */
break;
case XST_NO_DATA: /* Timed out */
AxiEthernetUtilErrorTrap("Tx timeout");
return XST_FAILURE;
break;
default: /* Some other error */
AxiEthernetResetDevice();
return XST_FAILURE;
}
}
/**********************/
/* Receive the packet */
/**********************/
/*
* Wait for the packets to arrive
* The Fifo core only allows us to pull out one frame at a time.
*/
for (Index = 0; Index < FramesToLoopback; ) {
/*
* Wait for packet Rx
*/
switch (AxiEthernetPollForRxStatus()) {
case XST_SUCCESS: /* Got a successfull receive status */
break;
case XST_NO_DATA: /* Timed out */
AxiEthernetUtilErrorTrap("Rx timeout");
return XST_FAILURE;
break;
default: /* Some other error */
AxiEthernetResetDevice();
return XST_FAILURE;
}
while(XLlFifo_RxOccupancy(&FifoInstance)) {
/*
* A packet has arrived, get its length
*/
RxFrameLength = XLlFifo_RxGetLen(&FifoInstance);
/*
* Verify the received frame length
*/
if ((RxFrameLength) != TxFrameLength) {
AxiEthernetUtilErrorTrap("Receive length incorrect");
return XST_FAILURE;
}
/*
* Read the received packet data
*/
XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength);
if (AxiEthernetUtilFrameVerify
(&TxFrame, &RxFrame) != 0) {
AxiEthernetUtilErrorTrap("Receive Data Mismatch");
return XST_FAILURE;
}
Index++;
}
}
/*
* Stop device
*/
XAxiEthernet_Stop(&AxiEthernetInstance);
return XST_SUCCESS;
}
/******************************************************************************/
/**
* This functions polls the Tx status and waits for an indication that a frame
* has been transmitted successfully or a transmit related error has occurred.
* If an error is reported, it handles all the possible error conditions.
*
* @param None.
*
* @return - XST_SUCCESS, Tx has completed
* - XST_NO_DATA, Timeout. Tx failure.
* - XST_FIFO_ERROR, Error in the FIFO.
*
* @note None.
*
******************************************************************************/
int AxiEthernetPollForTxStatus(void)
{
int Status = XST_NO_DATA;
int Attempts = 100000; /*
* Number of attempts to get status before
* giving up
*/
/*
* Wait for transmit complete indication
*/
do {
if (--Attempts <= 0)
break; /* Give up? */
if (XLlFifo_Status(&FifoInstance) & XLLF_INT_TC_MASK) {
XLlFifo_IntClear(&FifoInstance, XLLF_INT_TC_MASK);
Status = XST_SUCCESS;
}
if (XLlFifo_Status(&FifoInstance) & XLLF_INT_ERROR_MASK) {
Status = XST_FIFO_ERROR;
}
} while (Status == XST_NO_DATA);
switch (Status) {
case XST_SUCCESS: /* Frame sent without error */
case XST_NO_DATA: /* Timeout */
break;
case XST_FIFO_ERROR:
AxiEthernetUtilErrorTrap("FIFO error");
AxiEthernetResetDevice();
break;
default:
AxiEthernetUtilErrorTrap("Driver returned unknown transmit status");
break;
}
return (Status);
}
/******************************************************************************/
/**
* This functions polls the Rx status and waits for an indication that a frame
* has arrived or a receive related error has occurred. If an error is reported,
* handle all the possible error conditions.
*
* @param None.
*
* @return - XST_SUCCESS, a frame has been received
* - XST_NO_DATA, Timeout. Rx failure.
* - XST_FIFO_ERROR, Error in the FIFO.
* - XST_DATA_LOST, a frame has been dropped
*
* @note None.
*
******************************************************************************/
int AxiEthernetPollForRxStatus(void)
{
int Status = XST_NO_DATA;
int Attempts = 1000000; /* Number of times to get a status before
* giving up
*/
/*
* There are two ways to poll for a received frame:
*
* XAxiEthernet_Recv() can be used and repeatedly called until it
* returns a length, but this method does not provide any error
* detection.
*
* XAxiEthernet_FifoQueryRecvStatus() can be used and this function
* provides more information to handle error conditions.
*/
/*
* Wait for something to happen
*/
do {
if (--Attempts <= 0)
break; /* Give up? */
if (XLlFifo_Status(&FifoInstance) & XLLF_INT_RC_MASK) {
Status = XST_SUCCESS;
}
if (XLlFifo_Status(&FifoInstance) & XLLF_INT_ERROR_MASK) {
Status = XST_FIFO_ERROR;
}
if (XAxiEthernet_GetIntStatus(&AxiEthernetInstance) &
XAE_INT_RXRJECT_MASK) {
Status = XST_DATA_LOST;
}
/* When the RXFIFOOVR bit is set, the RXRJECT bit also
* gets set
*/
if (XAxiEthernet_GetIntStatus(&AxiEthernetInstance) &
XAE_INT_RXFIFOOVR_MASK) {
Status = XST_DATA_LOST;
}
} while (Status == XST_NO_DATA);
switch (Status) {
case XST_SUCCESS: /* Frame has arrived */
case XST_NO_DATA: /* Timeout */
break;
case XST_DATA_LOST:
AxiEthernetUtilErrorTrap("Frame was dropped");
break;
case XST_FIFO_ERROR:
AxiEthernetUtilErrorTrap("FIFO error");
AxiEthernetResetDevice();
break;
default:
AxiEthernetUtilErrorTrap("Driver returned invalid transmit status");
break;
}
return (Status);
}
/******************************************************************************/
/**
* This function resets the device but preserves the options set by the user.
*
* @param None.
*
* @return -XST_SUCCESS if reset is successful
* -XST_FAILURE. if reset is not successful
*
* @note None.
*
******************************************************************************/
int AxiEthernetResetDevice(void)
{
int Status;
u8 MacSave[6];
u32 Options;
/*
* Stop device
*/
XAxiEthernet_Stop(&AxiEthernetInstance);
/*
* Save the device state
*/
XAxiEthernet_GetMacAddress(&AxiEthernetInstance, MacSave);
Options = XAxiEthernet_GetOptions(&AxiEthernetInstance);
/*
* Stop and reset both the fifo and the AxiEthernet the devices
*/
XLlFifo_Reset(&FifoInstance);
XAxiEthernet_Reset(&AxiEthernetInstance);
/*
* Restore the state
*/
Status = XAxiEthernet_SetMacAddress(&AxiEthernetInstance, MacSave);
Status |= XAxiEthernet_SetOptions(&AxiEthernetInstance, Options);
Status |= XAxiEthernet_ClearOptions(&AxiEthernetInstance, ~Options);
if (Status != XST_SUCCESS) {
AxiEthernetUtilErrorTrap("Error restoring state after reset");
return XST_FAILURE;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,54 @@
xaxiethernet_example_readme.txt
-------------------------------
The examples in this directory are provided to give the user some idea of
how the Axi Ethernet and its driver are intended to be used.
SYSTEM REQUIREMENTS
The system containing the Axi Ethernet should have the following capabilities:
- An interrupt controller
- An external memory controller with at least 200KB of RAM available
- A UART to display messages
- The reset line of the device connected to the AxiEthernet AXI4-Stream
interface (AXIDMA or AXIFIFO) must be connected to the reset line of AxiEthernet.
(By default for BSB generated systems this is the case.)
FILES
1. xaxiethernet_example.h - Top level include for all examples.
2. xaxiethernet_example_util.c - Provide various utilities for debugging, and
ethernet frame construction.
3. xaxiethernet_example_polled.c - Examples using the L1 API found in xaxiethernet.h
in polled mode. HW must be setup for FIFO direct mode.
4. xaxiethernet_example_intr_fifo.c - Examples using the L1 API found in
xaxiethernet.h in interrupt driven FIFO direct mode. HW must be setup for
FIFO direct mode.
5. xaxiethernet_example_intr_sgdma.c - Examples using the L1 API found in
xaxiethernet.h in interrupt driven scatter-gather DMA mode. HW must be setup
for SGDMA mode. HW must be setup for checksum offloading for that
specific example to properly execute.
INCLUDING EXAMPLES IN EDK
Each example is independent from the others except for common code found in
xaxiethernet_example_util.c. When including source code files in an EDK SW
application, select xaxiethernet_example_util.c along with one other example
source code file.
IMPORTANT NOTES
* Included HW features are critical as to which examples will run properly.
* The device connected to the AXI4-Stream interface (AXIFIFO or AXIDMA)
of the AxiEthernet must be initialized before AxiEthernet initialization.
Since the reset line of AXIFIFO or AXIDMA is connected to the reset line
of AxiEthernet, AXIDMA/AXIFIFO initialization would reset AxiEthernet.
AxiEthernet hardware initialization routines in the AxiEthernet driver do
not reset the AxiEthernet hardware.

View file

@ -0,0 +1,789 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xaxiethernet_example_util.c
*
* This file implements the utility functions for the Axi Ethernet example code.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa 6/30/10 First release based on the ll temac driver
* 3.01a srt 02/03/13 Added support for SGMII mode (CR 676793).
* 02/14/13 Added support for Zynq (CR 681136).
* 3.02a srt 04/24/13 Modified parameter *_SGMII_PHYADDR to *_PHYADDR, the
* config parameter C_PHYADDR applies to SGMII/1000BaseX
* modes of operation and added support for 1000BaseX mode
* (CR 704195). Added function *_ConfigureInternalPhy()
* for this purpose.
* 04/24/13 Added support for RGMII mode.
* 3.02a srt 08/06/13 Fixed CR 717949:
* Configures external Marvel 88E1111 PHY based on the
* axi ethernet physical interface type and allows to
* operate in specific interface mode without changing
* jumpers on the Microblaze board.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xaxiethernet_example.h"
#if !defined (__MICROBLAZE__) && !defined(__PPC__)
#include "sleep.h"
#endif
/************************** Variable Definitions ****************************/
/*
* Local MAC address
*/
char AxiEthernetMAC[6] = { 0x00, 0x0A, 0x35, 0x01, 0x02, 0x03 };
/******************************************************************************/
/**
*
* Set the MAC addresses in the frame.
*
* @param FramePtr is the pointer to the frame.
* @param DestAddr is the Destination MAC address.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameHdrFormatMAC(EthernetFrame *FramePtr, char *DestAddr)
{
char *Frame = (char *) FramePtr;
char *SourceAddress = AxiEthernetMAC;
int Index;
/*
* Destination address
*/
for (Index = 0; Index < XAE_MAC_ADDR_SIZE; Index++) {
*Frame++ = *DestAddr++;
}
/*
* Source address
*/
for (Index = 0; Index < XAE_MAC_ADDR_SIZE; Index++) {
*Frame++ = *SourceAddress++;
}
}
/******************************************************************************/
/**
*
* Set the frame type for the specified frame.
*
* @param FramePtr is the pointer to the frame.
* @param FrameType is the Type to set in frame.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameHdrFormatType(EthernetFrame *FramePtr, u16 FrameType)
{
char *Frame = (char *) FramePtr;
/*
* Increment to type field
*/
Frame = Frame + 12;
FrameType = Xil_Htons(FrameType);
/*
* Set the type
*/
*(u16 *) Frame = FrameType;
}
/******************************************************************************/
/**
* This function places a pattern in the payload section of a frame. The pattern
* is a 8 bit incrementing series of numbers starting with 0.
* Once the pattern reaches 256, then the pattern changes to a 16 bit
* incrementing pattern:
* <pre>
* 0, 1, 2, ... 254, 255, 00, 00, 00, 01, 00, 02, ...
* </pre>
*
* @param FramePtr is a pointer to the frame to change.
* @param PayloadSize is the number of bytes in the payload that will be
* set.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameSetPayloadData(EthernetFrame *FramePtr,
int PayloadSize)
{
unsigned BytesLeft = PayloadSize;
u8 *Frame;
u16 Counter = 0;
/*
* Set the frame pointer to the start of the payload area
*/
Frame = (u8 *) FramePtr + XAE_HDR_SIZE;
/*
* Insert 8 bit incrementing pattern
*/
while (BytesLeft && (Counter < 256)) {
*Frame++ = (u8) Counter++;
BytesLeft--;
}
/*
* Switch to 16 bit incrementing pattern
*/
while (BytesLeft) {
*Frame++ = (u8) (Counter >> 8); /* high */
BytesLeft--;
if (!BytesLeft)
break;
*Frame++ = (u8) Counter++; /* low */
BytesLeft--;
}
}
/******************************************************************************/
/**
*
* Set the frame VLAN info for the specified frame.
*
* @param FramePtr is the pointer to the frame.
* @param VlanNumber is the VlanValue insertion position to set in frame.
* @param Vid is the 4 bytes Vlan value (TPID, Priority, CFI, VID)
* to be set in frame.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameHdrVlanFormatVid(EthernetFrame *FramePtr,
u32 VlanNumber, u32 Vid)
{
char *Frame = (char *) FramePtr;
/*
* Increment to type field
*/
Frame = Frame + 12 + (VlanNumber * 4);
Vid = Xil_Htonl(Vid);
/*
* Set the type
*/
*(u32 *) Frame = Vid;
}
/******************************************************************************/
/**
*
* Set the frame type for the specified frame.
*
* @param FramePtr is the pointer to the frame.
* @param FrameType is the Type to set in frame.
* @param VlanNumber is the VLAN friendly adjusted insertion position to
* set in frame.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameHdrVlanFormatType(EthernetFrame *FramePtr,
u16 FrameType, u32 VlanNumber)
{
char *Frame = (char *) FramePtr;
/*
* Increment to type field
*/
Frame = Frame + 12 + (VlanNumber * 4);
FrameType = Xil_Htons(FrameType);
/*
* Set the type
*/
*(u16 *) Frame = FrameType;
}
/******************************************************************************/
/**
* This function places a pattern in the payload section of a frame. The pattern
* is a 8 bit incrementing series of numbers starting with 0.
* Once the pattern reaches 256, then the pattern changes to a 16 bit
* incrementing pattern:
* <pre>
* 0, 1, 2, ... 254, 255, 00, 00, 00, 01, 00, 02, ...
* </pre>
*
* @param FramePtr is a pointer to the frame to change.
* @param PayloadSize is the number of bytes in the payload that will be set.
* @param VlanNumber is the VLAN friendly adjusted insertion position to
* set in frame.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameSetVlanPayloadData(EthernetFrame *FramePtr,
int PayloadSize, u32 VlanNumber)
{
unsigned BytesLeft = PayloadSize;
u8 *Frame;
u16 Counter = 0;
/*
* Set the frame pointer to the start of the payload area
*/
Frame = (u8 *) FramePtr + XAE_HDR_SIZE + (VlanNumber * 4);
/*
* Insert 8 bit incrementing pattern
*/
while (BytesLeft && (Counter < 256)) {
*Frame++ = (u8) Counter++;
BytesLeft--;
}
/*
* Switch to 16 bit incrementing pattern
*/
while (BytesLeft) {
*Frame++ = (u8) (Counter >> 8); /* high */
BytesLeft--;
if (!BytesLeft)
break;
*Frame++ = (u8) Counter++; /* low */
BytesLeft--;
}
}
/******************************************************************************/
/**
* This function verifies the frame data against a CheckFrame.
*
* Validation occurs by comparing the ActualFrame to the header of the
* CheckFrame. If the headers match, then the payload of ActualFrame is
* verified for the same pattern Util_FrameSetPayloadData() generates.
*
* @param CheckFrame is a pointer to a frame containing the 14 byte header
* that should be present in the ActualFrame parameter.
* @param ActualFrame is a pointer to a frame to validate.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE in case of failure.
*
* @note None.
*
******************************************************************************/
int AxiEthernetUtilFrameVerify(EthernetFrame * CheckFrame,
EthernetFrame * ActualFrame)
{
unsigned char *CheckPtr = (unsigned char *) CheckFrame;
unsigned char *ActualPtr = (unsigned char *) ActualFrame;
u16 BytesLeft;
u16 Counter;
int Index;
/*
* Compare the headers
*/
for (Index = 0; Index < XAE_HDR_SIZE; Index++) {
if (CheckPtr[Index] != ActualPtr[Index]) {
return XST_FAILURE;
}
}
Index = 0;
BytesLeft = *(u16 *) &ActualPtr[12];
BytesLeft = Xil_Ntohs(BytesLeft);
/*
* Get the length of the payload, do not use VLAN TPID here.
* TPID needs to be verified.
*/
while ((0x8100 == BytesLeft) || (0x88A8 == BytesLeft) ||
(0x9100 == BytesLeft) || (0x9200 == BytesLeft)) {
Index++;
BytesLeft = *(u16 *) &ActualPtr[12+(4*Index)];
BytesLeft = Xil_Ntohs(BytesLeft);
}
/*
* Validate the payload
*/
Counter = 0;
ActualPtr = &ActualPtr[14+(4*Index)];
/*
* Check 8 bit incrementing pattern
*/
while (BytesLeft && (Counter < 256)) {
if (*ActualPtr++ != (u8) Counter++) {
return XST_FAILURE;
}
BytesLeft--;
}
/*
* Check 16 bit incrementing pattern
*/
while (BytesLeft) {
if (*ActualPtr++ != (u8) (Counter >> 8)) { /* high */
return XST_FAILURE;
}
BytesLeft--;
if (!BytesLeft)
break;
if (*ActualPtr++ != (u8) Counter++) { /* low */
return XST_FAILURE;
}
BytesLeft--;
}
return XST_SUCCESS;
}
/******************************************************************************/
/**
* This function sets all bytes of a frame to 0.
*
* @param FramePtr is a pointer to the frame itself.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void AxiEthernetUtilFrameMemClear(EthernetFrame * FramePtr)
{
u32 *Data32Ptr = (u32 *) FramePtr;
u32 WordsLeft = sizeof(EthernetFrame) / sizeof(u32);
/*
* Frame should be an integral number of words
*/
while (WordsLeft--) {
*Data32Ptr++ = 0;
}
}
/******************************************************************************/
/**
*
* This function detects the PHY address by looking for successful MII status
* register contents (PHY register 1). It looks for a PHY that supports
* auto-negotiation and 10Mbps full-duplex and half-duplex. So, this code
* won't work for PHYs that don't support those features, but it's a bit more
* general purpose than matching a specific PHY manufacturer ID.
*
* Note also that on some (older) Xilinx ML4xx boards, PHY address 0 does not
* properly respond to this query. But, since the default is 0 and asssuming
* no other address responds, then it seems to work OK.
*
* @param The Axi Ethernet driver instance
*
* @return The address of the PHY (defaults to 0 if none detected)
*
* @note None.
*
******************************************************************************/
/* Use MII register 1 (MII status register) to detect PHY */
#define PHY_DETECT_REG 1
/* Mask used to verify certain PHY features (or register contents)
* in the register above:
* 0x1000: 10Mbps full duplex support
* 0x0800: 10Mbps half duplex support
* 0x0008: Auto-negotiation support
*/
#define PHY_DETECT_MASK 0x1808
u32 AxiEthernetDetectPHY(XAxiEthernet * AxiEthernetInstancePtr)
{
u16 PhyReg;
int PhyAddr;
for (PhyAddr = 31; PhyAddr >= 0; PhyAddr--) {
XAxiEthernet_PhyRead(AxiEthernetInstancePtr, PhyAddr,
PHY_DETECT_REG, &PhyReg);
if ((PhyReg != 0xFFFF) &&
((PhyReg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
/* Found a valid PHY address */
return PhyAddr;
}
}
return 0; /* Default to zero */
}
/******************************************************************************/
/**
* Set PHY to loopback mode. This works with the marvell PHY common on ML40x
* evaluation boards
*
* @param Speed is the loopback speed 10, 100, or 1000 Mbit
*
******************************************************************************/
/* IEEE PHY Specific definitions */
#define PHY_R0_CTRL_REG 0
#define PHY_R3_PHY_IDENT_REG 3
#define PHY_R0_RESET 0x8000
#define PHY_R0_LOOPBACK 0x4000
#define PHY_R0_ANEG_ENABLE 0x1000
#define PHY_R0_DFT_SPD_MASK 0x2040
#define PHY_R0_DFT_SPD_10 0x0000
#define PHY_R0_DFT_SPD_100 0x2000
#define PHY_R0_DFT_SPD_1000 0x0040
#define PHY_R0_ISOLATE 0x0400
/* Marvel PHY 88E1111 Specific definitions */
#define PHY_R20_EXTND_CTRL_REG 20
#define PHY_R27_EXTND_STS_REG 27
#define PHY_R20_DFT_SPD_10 0x20
#define PHY_R20_DFT_SPD_100 0x50
#define PHY_R20_DFT_SPD_1000 0x60
#define PHY_R20_RX_DLY 0x80
#define PHY_R27_MAC_CONFIG_GMII 0x000F
#define PHY_R27_MAC_CONFIG_MII 0x000F
#define PHY_R27_MAC_CONFIG_RGMII 0x000B
#define PHY_R27_MAC_CONFIG_SGMII 0x0004
/* Marvel PHY 88E1116R Specific definitions */
#define PHY_R22_PAGE_ADDR_REG 22
#define PHY_PG2_R21_CTRL_REG 21
#define PHY_REG21_10 0x0030
#define PHY_REG21_100 0x2030
#define PHY_REG21_1000 0x0070
/* Marvel PHY flags */
#define MARVEL_PHY_88E1111_MODEL 0xC0
#define MARVEL_PHY_88E1116R_MODEL 0x240
#define PHY_MODEL_NUM_MASK 0x3F0
/******************************************************************************/
/**
*
* This function sets the PHY to loopback mode. This works with the marvell PHY
* common on ML40x evaluation boards.
*
* @param AxiEthernetInstancePtr is a pointer to the instance of the
* AxiEthernet component.
* @param Speed is the loopback speed 10, 100, or 1000 Mbit.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE, in case of failure..
*
* @note None.
*
******************************************************************************/
int AxiEthernetUtilEnterLoopback(XAxiEthernet *AxiEthernetInstancePtr,
int Speed)
{
u16 PhyReg0;
signed int PhyAddr;
u8 PhyType;
u16 PhyModel;
u16 PhyReg20; /* Extended PHY specific Register (Reg 20)
of Marvell 88E1111 PHY */
u16 PhyReg21; /* Control Register MAC (Reg 21)
of Marvell 88E1116R PHY */
/* Get the Phy Interface */
PhyType = XAxiEthernet_GetPhysicalInterface(AxiEthernetInstancePtr);
/* Detect the PHY address */
if (PhyType != XAE_PHY_TYPE_1000BASE_X) {
PhyAddr = AxiEthernetDetectPHY(AxiEthernetInstancePtr);
} else {
PhyAddr = XPAR_AXIETHERNET_0_PHYADDR;
}
XAxiEthernet_PhyRead(AxiEthernetInstancePtr, PhyAddr,
PHY_R3_PHY_IDENT_REG, &PhyModel);
PhyModel = PhyModel & PHY_MODEL_NUM_MASK;
/* Clear the PHY of any existing bits by zeroing this out */
PhyReg0 = PhyReg20 = PhyReg21 = 0;
switch (Speed) {
case XAE_SPEED_10_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_10;
PhyReg20 |= PHY_R20_DFT_SPD_10;
PhyReg21 |= PHY_REG21_10;
break;
case XAE_SPEED_100_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_100;
PhyReg20 |= PHY_R20_DFT_SPD_100;
PhyReg21 |= PHY_REG21_100;
break;
case XAE_SPEED_1000_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_1000;
PhyReg20 |= PHY_R20_DFT_SPD_1000;
PhyReg21 |= PHY_REG21_1000;
break;
default:
AxiEthernetUtilErrorTrap("Intg_LinkSpeed not 10, 100, or 1000 mbps");
return XST_FAILURE;
}
/* RGMII mode Phy specific registers initialization */
if ((PhyType == XAE_PHY_TYPE_RGMII_2_0) ||
(PhyType == XAE_PHY_TYPE_RGMII_1_3)) {
if (PhyModel == MARVEL_PHY_88E1111_MODEL) {
PhyReg20 |= PHY_R20_RX_DLY;
/*
* Adding Rx delay. Configuring loopback speed.
*/
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr, PHY_R20_EXTND_CTRL_REG,
PhyReg20);
} else if (PhyModel == MARVEL_PHY_88E1116R_MODEL) {
/*
* Switching to PAGE2
*/
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr,
PHY_R22_PAGE_ADDR_REG, 2);
/*
* Adding Tx and Rx delay. Configuring loopback speed.
*/
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr,
PHY_PG2_R21_CTRL_REG, PhyReg21);
/*
* Switching to PAGE0
*/
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr,
PHY_R22_PAGE_ADDR_REG, 0);
}
PhyReg0 &= (~PHY_R0_ANEG_ENABLE);
}
/* Configure interface modes */
if (PhyModel == MARVEL_PHY_88E1111_MODEL) {
if ((PhyType == XAE_PHY_TYPE_RGMII_2_0) ||
(PhyType == XAE_PHY_TYPE_RGMII_1_3)) {
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr, PHY_R27_EXTND_STS_REG,
PHY_R27_MAC_CONFIG_RGMII);
} else if (PhyType == XAE_PHY_TYPE_SGMII) {
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr, PHY_R27_EXTND_STS_REG,
PHY_R27_MAC_CONFIG_SGMII);
} else if ((PhyType == XAE_PHY_TYPE_GMII) ||
(PhyType == XAE_PHY_TYPE_MII)) {
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr,
PhyAddr, PHY_R27_EXTND_STS_REG,
PHY_R27_MAC_CONFIG_GMII );
}
}
/* Set the speed and put the PHY in reset, then put the PHY in loopback */
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr, PhyAddr,
PHY_R0_CTRL_REG,
PhyReg0 | PHY_R0_RESET);
AxiEthernetUtilPhyDelay(AXIETHERNET_PHY_DELAY_SEC);
XAxiEthernet_PhyRead(AxiEthernetInstancePtr,PhyAddr,
PHY_R0_CTRL_REG, &PhyReg0);
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr, PhyAddr,
PHY_R0_CTRL_REG,
PhyReg0 | PHY_R0_LOOPBACK);
if ((PhyType == XAE_PHY_TYPE_SGMII) ||
(PhyType == XAE_PHY_TYPE_1000BASE_X)) {
AxiEthernetUtilConfigureInternalPhy(AxiEthernetInstancePtr, Speed);
}
AxiEthernetUtilPhyDelay(1);
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function is called by example code when an error is detected. It
* can be set as a breakpoint with a debugger or it can be used to print out the
* given message if there is a UART or STDIO device.
*
* @param Message is the text explaining the error
*
* @return None
*
* @note None
*
******************************************************************************/
void AxiEthernetUtilErrorTrap(char *Message)
{
static int Count = 0;
Count++;
#ifdef STDOUT_BASEADDRESS
xil_printf("%s\r\n", Message);
#endif
}
/******************************************************************************/
/**
*
* For Microblaze we use an assembly loop that is roughly the same regardless of
* optimization level, although caches and memory access time can make the delay
* vary. Just keep in mind that after resetting or updating the PHY modes,
* the PHY typically needs time to recover.
*
* @return None
*
* @note None
*
******************************************************************************/
void AxiEthernetUtilPhyDelay(unsigned int Seconds)
{
#if defined (__MICROBLAZE__) || defined(__PPC__)
static int WarningFlag = 0;
/* If MB caches are disabled or do not exist, this delay loop could
* take minutes instead of seconds (e.g., 30x longer). Print a warning
* message for the user (once). If only MB had a built-in timer!
*/
if (((mfmsr() & 0x20) == 0) && (!WarningFlag)) {
WarningFlag = 1;
}
#define ITERS_PER_SEC (XPAR_CPU_CORE_CLOCK_FREQ_HZ / 6)
asm volatile ("\n"
"1: \n\t"
"addik r7, r0, %0 \n\t"
"2: \n\t"
"addik r7, r7, -1 \n\t"
"bneid r7, 2b \n\t"
"or r0, r0, r0 \n\t"
"bneid %1, 1b \n\t"
"addik %1, %1, -1 \n\t"
:: "i"(ITERS_PER_SEC), "d" (Seconds));
#else
sleep(Seconds);
#endif
}
/******************************************************************************/
/**
*
* This function configures the internal phy for SGMII and 1000baseX modes.
* *
* @param AxiEthernetInstancePtr is a pointer to the instance of the
* AxiEthernet component.
* @param Speed is the loopback speed 10, 100, or 1000 Mbit.
*
* @return - XST_SUCCESS if successful.
* - XST_FAILURE, in case of failure..
*
* @note None.
*
******************************************************************************/
int AxiEthernetUtilConfigureInternalPhy(XAxiEthernet *AxiEthernetInstancePtr,
int Speed)
{
u16 PhyReg0;
signed int PhyAddr;
PhyAddr = XPAR_AXIETHERNET_0_PHYADDR;
/* Clear the PHY of any existing bits by zeroing this out */
PhyReg0 = 0;
XAxiEthernet_PhyRead(AxiEthernetInstancePtr, PhyAddr,
PHY_R0_CTRL_REG, &PhyReg0);
PhyReg0 &= (~PHY_R0_ANEG_ENABLE);
PhyReg0 &= (~PHY_R0_ISOLATE);
switch (Speed) {
case XAE_SPEED_10_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_10;
break;
case XAE_SPEED_100_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_100;
break;
case XAE_SPEED_1000_MBPS:
PhyReg0 |= PHY_R0_DFT_SPD_1000;
break;
default:
AxiEthernetUtilErrorTrap(
"Intg_LinkSpeed not 10, 100, or 1000 mbps\n\r");
return XST_FAILURE;
}
AxiEthernetUtilPhyDelay(1);
XAxiEthernet_PhyWrite(AxiEthernetInstancePtr, PhyAddr,
PHY_R0_CTRL_REG, PhyReg0);
return XST_SUCCESS;
}

View file

@ -0,0 +1,27 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
INCLUDEFILES=xaxiethernet.h xaxiethernet_hw.h xdebug.h
LIBSOURCES=*.c
OUTS = *.o
libs:
echo "Compiling axiethernet"
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS}
make clean
include:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OUTS}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include "xparameters.h"
#include "xaxiethernet.h"
/*
* The configuration table for devices
*/
XAxiEthernet_Config XAxiEthernet_ConfigTable[] = {
{
XPAR_AXIETHERNET_0_DEVICE_ID,
XPAR_AXIETHERNET_0_BASEADDR,
XPAR_AXIETHERNET_0_TEMAC_TYPE,
XPAR_AXIETHERNET_0_TXCSUM,
XPAR_AXIETHERNET_0_RXCSUM,
XPAR_AXIETHERNET_0_PHY_TYPE,
XPAR_AXIETHERNET_0_TXVLAN_TRAN,
XPAR_AXIETHERNET_0_RXVLAN_TRAN,
XPAR_AXIETHERNET_0_TXVLAN_TAG,
XPAR_AXIETHERNET_0_RXVLAN_TAG,
XPAR_AXIETHERNET_0_TXVLAN_STRP,
XPAR_AXIETHERNET_0_RXVLAN_STRP,
XPAR_AXIETHERNET_0_MCAST_EXTEND,
XPAR_AXIETHERNET_0_STATS,
XPAR_AXIETHERNET_0_AVB,
XPAR_AXIETHERNET_0_ENABLE_SGMII_OVER_LVDS,
XPAR_AXIETHERNET_0_INTR,
XPAR_AXIETHERNET_0_CONNECTED_TYPE,
XPAR_AXIETHERNET_0_CONNECTED_BASEADDR,
XPAR_AXIETHERNET_0_CONNECTED_FIFO_INTR,
0xFF,
0xFF
}
};

View file

@ -0,0 +1,960 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xaxiethernet_hw.h
*
* This header file contains identifiers and macros that can be used to access
* the Axi Ethernet device. The driver APIs/functions are defined in
* xaxiethernet.h.
*
* @note
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a asa 6/30/10 First release for Axi Ethernet driver
* 1.02a asa 2/16/11 Changes the value of XAE_LOOPS_TO_COME_OUT_OF_RST to
* 10000.
* 2.00a asa 8/29/11 Added defines for Ability Reg, Identification Reg, Rx max
* Frame and Tx Max Frame registers.
* Changed define for TEMAC RGMII/SGMII Config (PHYC) Reg.
* </pre>
******************************************************************************/
#ifndef XAXIETHERNET_HW_H /* prevent circular inclusions */
#define XAXIETHERNET_HW_H /* by using protection macros */
/***************************** Include Files *********************************/
#include "xdebug.h"
#include "xil_io.h"
#include "xil_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/************************** Constant Definitions *****************************/
/*
* Register offset definitions. Unless otherwise noted, register access is
* 32 bit.
*/
/** @name Axi Ethernet registers offset
* @{
*/
#define XAE_RAF_OFFSET 0x00000000 /**< Reset and Address filter */
#define XAE_TPF_OFFSET 0x00000004 /**< Tx Pause Frame */
#define XAE_IFGP_OFFSET 0x00000008 /**< Tx Inter-frame gap adjustment*/
#define XAE_IS_OFFSET 0x0000000C /**< Interrupt status */
#define XAE_IP_OFFSET 0x00000010 /**< Interrupt pending */
#define XAE_IE_OFFSET 0x00000014 /**< Interrupt enable */
#define XAE_TTAG_OFFSET 0x00000018 /**< Tx VLAN TAG */
#define XAE_RTAG_OFFSET 0x0000001C /**< Rx VLAN TAG */
#define XAE_UAWL_OFFSET 0x00000020 /**< Unicast address word lower */
#define XAE_UAWU_OFFSET 0x00000024 /**< Unicast address word upper */
#define XAE_TPID0_OFFSET 0x00000028 /**< VLAN TPID0 register */
#define XAE_TPID1_OFFSET 0x0000002C /**< VLAN TPID1 register */
/*
* Statistics Counter Registers are from offset 0x200 to 0x3FF
* They are defined from offset 0x200 to 0x34C in this device.
* The offsets from 0x350 to 0x3FF are reserved.
* The counters are 64 bit.
* The Least Significant Word (LSW) are stored in one 32 bit register and
* the Most Significant Word (MSW) are stored in one 32 bit register
*/
/* Start of Statistics Counter Registers Definitions */
#define XAE_RXBL_OFFSET 0x00000200 /**< Received Bytes, LSW */
#define XAE_RXBU_OFFSET 0x00000204 /**< Received Bytes, MSW */
#define XAE_TXBL_OFFSET 0x00000208 /**< Transmitted Bytes, LSW */
#define XAE_TXBU_OFFSET 0x0000020C /**< Transmitted Bytes, MSW */
#define XAE_RXUNDRL_OFFSET 0x00000210 /**< Count of undersize(less than
* 64 bytes) frames received,
* LSW
*/
#define XAE_RXUNDRU_OFFSET 0x00000214 /**< Count of undersize(less than
* 64 bytes) frames received,
* MSW
*/
#define XAE_RXFRAGL_OFFSET 0x00000218 /**< Count of undersized(less
* than 64 bytes) and bad FCS
* frames received, LSW
*/
#define XAE_RXFRAGU_OFFSET 0x0000021C /**< Count of undersized(less
* than 64 bytes) and bad FCS
* frames received, MSW
*/
#define XAE_RX64BL_OFFSET 0x00000220 /**< Count of 64 bytes frames
* received, LSW
*/
#define XAE_RX64BU_OFFSET 0x00000224 /**< Count of 64 bytes frames
* received, MSW
*/
#define XAE_RX65B127L_OFFSET 0x00000228 /**< Count of 65-127 bytes
* Frames received, LSW
*/
#define XAE_RX65B127U_OFFSET 0x0000022C /**< Count of 65-127 bytes
* Frames received, MSW
*/
#define XAE_RX128B255L_OFFSET 0x00000230 /**< Count of 128-255 bytes
* Frames received, LSW
*/
#define XAE_RX128B255U_OFFSET 0x00000234 /**< Count of 128-255 bytes
* frames received, MSW
*/
#define XAE_RX256B511L_OFFSET 0x00000238 /**< Count of 256-511 bytes
* Frames received, LSW
*/
#define XAE_RX256B511U_OFFSET 0x0000023C /**< Count of 256-511 bytes
* frames received, MSW
*/
#define XAE_RX512B1023L_OFFSET 0x00000240 /**< Count of 512-1023 bytes
* frames received, LSW
*/
#define XAE_RX512B1023U_OFFSET 0x00000244 /**< Count of 512-1023 bytes
* frames received, MSW
*/
#define XAE_RX1024BL_OFFSET 0x00000248 /**< Count of 1024-MAX bytes
* frames received, LSW
*/
#define XAE_RX1024BU_OFFSET 0x0000024C /**< Count of 1024-MAX bytes
* frames received, MSW
*/
#define XAE_RXOVRL_OFFSET 0x00000250 /**< Count of oversize frames
* received, LSW
*/
#define XAE_RXOVRU_OFFSET 0x00000254 /**< Count of oversize frames
* received, MSW
*/
#define XAE_TX64BL_OFFSET 0x00000258 /**< Count of 64 bytes frames
* transmitted, LSW
*/
#define XAE_TX64BU_OFFSET 0x0000025C /**< Count of 64 bytes frames
* transmitted, MSW
*/
#define XAE_TX65B127L_OFFSET 0x00000260 /**< Count of 65-127 bytes
* frames transmitted, LSW
*/
#define XAE_TX65B127U_OFFSET 0x00000264 /**< Count of 65-127 bytes
* frames transmitted, MSW
*/
#define XAE_TX128B255L_OFFSET 0x00000268 /**< Count of 128-255 bytes
* frames transmitted, LSW
*/
#define XAE_TX128B255U_OFFSET 0x0000026C /**< Count of 128-255 bytes
* frames transmitted, MSW
*/
#define XAE_TX256B511L_OFFSET 0x00000270 /**< Count of 256-511 bytes
* frames transmitted, LSW
*/
#define XAE_TX256B511U_OFFSET 0x00000274 /**< Count of 256-511 bytes
* frames transmitted, MSW
*/
#define XAE_TX512B1023L_OFFSET 0x00000278 /**< Count of 512-1023 bytes
* frames transmitted, LSW
*/
#define XAE_TX512B1023U_OFFSET 0x0000027C /**< Count of 512-1023 bytes
* frames transmitted, MSW
*/
#define XAE_TX1024L_OFFSET 0x00000280 /**< Count of 1024-MAX bytes
* frames transmitted, LSW
*/
#define XAE_TX1024U_OFFSET 0x00000284 /**< Count of 1024-MAX bytes
* frames transmitted, MSW
*/
#define XAE_TXOVRL_OFFSET 0x00000288 /**< Count of oversize frames
* transmitted, LSW
*/
#define XAE_TXOVRU_OFFSET 0x0000028C /**< Count of oversize frames
* transmitted, MSW
*/
#define XAE_RXFL_OFFSET 0x00000290 /**< Count of frames received OK,
* LSW
*/
#define XAE_RXFU_OFFSET 0x00000294 /**< Count of frames received OK,
* MSW
*/
#define XAE_RXFCSERL_OFFSET 0x00000298 /**< Count of frames received with
* FCS error and at least 64
* bytes, LSW
*/
#define XAE_RXFCSERU_OFFSET 0x0000029C /**< Count of frames received with
* FCS error and at least 64
* bytes,MSW
*/
#define XAE_RXBCSTFL_OFFSET 0x000002A0 /**< Count of broadcast frames
* received, LSW
*/
#define XAE_RXBCSTFU_OFFSET 0x000002A4 /**< Count of broadcast frames
* received, MSW
*/
#define XAE_RXMCSTFL_OFFSET 0x000002A8 /**< Count of multicast frames
* received, LSW
*/
#define XAE_RXMCSTFU_OFFSET 0x000002AC /**< Count of multicast frames
* received, MSW
*/
#define XAE_RXCTRFL_OFFSET 0x000002B0 /**< Count of control frames
* received, LSW
*/
#define XAE_RXCTRFU_OFFSET 0x000002B4 /**< Count of control frames
* received, MSW
*/
#define XAE_RXLTERL_OFFSET 0x000002B8 /**< Count of frames received
* with length error, LSW
*/
#define XAE_RXLTERU_OFFSET 0x000002BC /**< Count of frames received
* with length error, MSW
*/
#define XAE_RXVLANFL_OFFSET 0x000002C0 /**< Count of VLAN tagged
* frames received, LSW
*/
#define XAE_RXVLANFU_OFFSET 0x000002C4 /**< Count of VLAN tagged frames
* received, MSW
*/
#define XAE_RXPFL_OFFSET 0x000002C8 /**< Count of pause frames received,
* LSW
*/
#define XAE_RXPFU_OFFSET 0x000002CC /**< Count of pause frames received,
* MSW
*/
#define XAE_RXUOPFL_OFFSET 0x000002D0 /**< Count of control frames
* received with unsupported
* opcode, LSW
*/
#define XAE_RXUOPFU_OFFSET 0x000002D4 /**< Count of control frames
* received with unsupported
* opcode, MSW
*/
#define XAE_TXFL_OFFSET 0x000002D8 /**< Count of frames transmitted OK,
* LSW
*/
#define XAE_TXFU_OFFSET 0x000002DC /**< Count of frames transmitted OK,
* MSW
*/
#define XAE_TXBCSTFL_OFFSET 0x000002E0 /**< Count of broadcast frames
* transmitted OK, LSW
*/
#define XAE_TXBCSTFU_OFFSET 0x000002E4 /**< Count of broadcast frames
* transmitted, MSW
*/
#define XAE_TXMCSTFL_OFFSET 0x000002E8 /**< Count of multicast frames
* transmitted, LSW
*/
#define XAE_TXMCSTFU_OFFSET 0x000002EC /**< Count of multicast frames
* transmitted, MSW
*/
#define XAE_TXUNDRERL_OFFSET 0x000002F0 /**< Count of frames transmitted
* underrun error, LSW
*/
#define XAE_TXUNDRERU_OFFSET 0x000002F4 /**< Count of frames transmitted
* underrun error, MSW
*/
#define XAE_TXCTRFL_OFFSET 0x000002F8 /**< Count of control frames
* transmitted, LSW
*/
#define XAE_TXCTRFU_OFFSET 0x000002FC /**< Count of control frames,
* transmitted, MSW
*/
#define XAE_TXVLANFL_OFFSET 0x00000300 /**< Count of VLAN tagged frames
* transmitted, LSW
*/
#define XAE_TXVLANFU_OFFSET 0x00000304 /**< Count of VLAN tagged
* frames transmitted, MSW
*/
#define XAE_TXPFL_OFFSET 0x00000308 /**< Count of pause frames
* transmitted, LSW
*/
#define XAE_TXPFU_OFFSET 0x0000030C /**< Count of pause frames
* transmitted, MSW
*/
#define XAE_TXSCL_OFFSET 0x00000310 /**< Single Collision Frames
* Transmitted OK, LSW
*/
#define XAE_TXSCU_OFFSET 0x00000314 /**< Single Collision Frames
* Transmitted OK, MSW
*/
#define XAE_TXMCL_OFFSET 0x00000318 /**< Multiple Collision Frames
* Transmitted OK, LSW
*/
#define XAE_TXMCU_OFFSET 0x0000031C /**< Multiple Collision Frames
* Transmitted OK, MSW
*/
#define XAE_TXDEFL_OFFSET 0x00000320 /**< Deferred Tx Frames, LSW */
#define XAE_TXDEFU_OFFSET 0x00000324 /**< Deferred Tx Frames, MSW */
#define XAE_TXLTCL_OFFSET 0x00000328 /**< Frames transmitted with late
* Collisions, LSW
*/
#define XAE_TXLTCU_OFFSET 0x0000032C /**< Frames transmitted with late
* Collisions, MSW
*/
#define XAE_TXAECL_OFFSET 0x00000330 /**< Frames aborted with excessive
* Collisions, LSW
*/
#define XAE_TXAECU_OFFSET 0x00000334 /**< Frames aborted with excessive
* Collisions, MSW
*/
#define XAE_TXEDEFL_OFFSET 0x00000338 /**< Transmit Frames with excessive
* Defferal, LSW
*/
#define XAE_TXEDEFU_OFFSET 0x0000033C /**< Transmit Frames with excessive
* Defferal, MSW
*/
#define XAE_RXAERL_OFFSET 0x00000340 /**< Frames received with alignment
* errors, LSW
*/
#define XAE_RXAERU_OFFSET 0x0000034C /**< Frames received with alignment
* errors, MSW
*/
/* End of Statistics Counter Registers Offset definitions */
#define XAE_RCW0_OFFSET 0x00000400 /**< Rx Configuration Word 0 */
#define XAE_RCW1_OFFSET 0x00000404 /**< Rx Configuration Word 1 */
#define XAE_TC_OFFSET 0x00000408 /**< Tx Configuration */
#define XAE_FCC_OFFSET 0x0000040C /**< Flow Control Configuration */
#define XAE_EMMC_OFFSET 0x00000410 /**< EMAC mode configuration */
#define XAE_RXFC_OFFSET 0x00000414 /**< Rx Max Frm Config Register */
#define XAE_TXFC_OFFSET 0x00000418 /**< Tx Max Frm Config Register */
#define XAE_TX_TIMESTAMP_ADJ_OFFSET 0x0000041C /**< Transmitter time stamp
* adjust control Register
*/
#define XAE_PHYC_OFFSET 0x00000420 /**< RGMII/SGMII configuration */
/* 0x00000424 to 0x000004F4 are reserved */
#define XAE_IDREG_OFFSET 0x000004F8 /**< Identification Register */
#define XAE_ARREG_OFFSET 0x000004FC /**< Ability Register */
#define XAE_MDIO_MC_OFFSET 0x00000500 /**< MII Management Config */
#define XAE_MDIO_MCR_OFFSET 0x00000504 /**< MII Management Control */
#define XAE_MDIO_MWD_OFFSET 0x00000508 /**< MII Management Write Data */
#define XAE_MDIO_MRD_OFFSET 0x0000050C /**< MII Management Read Data */
/* 0x00000510 to 0x000005FC are reserved */
#define XAE_MDIO_MIS_OFFSET 0x00000600 /**< MII Management Interrupt
* Status
*/
/* 0x00000604-0x0000061C are reserved */
#define XAE_MDIO_MIP_OFFSET 0x00000620 /**< MII Management Interrupt
* Pending register offse
*/
/* 0x00000624-0x0000063C are reserved */
#define XAE_MDIO_MIE_OFFSET 0x00000640 /**< MII Management Interrupt
* Enable register offset
*/
/* 0x00000644-0x0000065C are reserved */
#define XAE_MDIO_MIC_OFFSET 0x00000660 /**< MII Management Interrupt
* Clear register offset.
*/
/* 0x00000664-0x000006FC are reserved */
#define XAE_UAW0_OFFSET 0x00000700 /**< Unicast address word 0 */
#define XAE_UAW1_OFFSET 0x00000704 /**< Unicast address word 1 */
#define XAE_FMI_OFFSET 0x00000708 /**< Filter Mask Index */
/* 0x0000070C is reserved */
#define XAE_AF0_OFFSET 0x00000710 /**< Address Filter 0 */
#define XAE_AF1_OFFSET 0x00000714 /**< Address Filter 1 */
/* 0x00000718-0x00003FFC are reserved */
/*
* Transmit VLAN Table is from 0x00004000 to 0x00007FFC
* This offset defines an offset to table that has provisioned transmit
* VLAN data. The VLAN table will be used by hardware to provide
* transmit VLAN tagging, stripping, and translation.
*/
#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /**< TX VLAN data table address */
/*
* Receive VLAN Data Table is from 0x00008000 to 0x0000BFFC
* This offset defines an offset to table that has provisioned receive
* VLAN data. The VLAN table will be used by hardware to provide
* receive VLAN tagging, stripping, and translation.
*/
#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /**< RX VLAN data table address */
/* 0x0000C000-0x0000FFFC are reserved */
/* 0x00010000-0x00013FFC are Ethenet AVB address offset */
/* 0x00014000-0x0001FFFC are reserved */
/*
* Extended Multicast Address Table is from 0x0020000 to 0x0003FFFC.
* This offset defines an offset to table that has provisioned multicast
* addresses. It is stored in BRAM and will be used by hardware to provide
* first line of address matching when a multicast frame is reveived. It
* can minimize the use of CPU/software hence minimize performance impact.
*/
#define XAE_MCAST_TABLE_OFFSET 0x00020000 /**< Multicast table address */
/*@}*/
/* Register masks. The following constants define bit locations of various
* bits in the registers. Constants are not defined for those registers
* that have a single bit field representing all 32 bits. For further
* information on the meaning of the various bit masks, refer to the HW spec.
*/
/** @name Reset and Address Filter (RAF) Register bit definitions.
* These bits are associated with the XAE_RAF_OFFSET register.
* @{
*/
#define XAE_RAF_MCSTREJ_MASK 0x00000002 /**< Reject receive
* multicast destination
* address
*/
#define XAE_RAF_BCSTREJ_MASK 0x00000004 /**< Reject receive
* broadcast destination
* address
*/
#define XAE_RAF_TXVTAGMODE_MASK 0x00000018 /**< Tx VLAN TAG mode */
#define XAE_RAF_RXVTAGMODE_MASK 0x00000060 /**< Rx VLAN TAG mode */
#define XAE_RAF_TXVSTRPMODE_MASK 0x00000180 /**< Tx VLAN STRIP mode */
#define XAE_RAF_RXVSTRPMODE_MASK 0x00000600 /**< Rx VLAN STRIP mode */
#define XAE_RAF_NEWFNCENBL_MASK 0x00000800 /**< New function mode */
#define XAE_RAF_EMULTIFLTRENBL_MASK 0x00001000 /**< Exteneded Multicast
* Filtering mode
*/
#define XAE_RAF_STATSRST_MASK 0x00002000 /**< Statistics Counter
* Reset
*/
#define XAE_RAF_RXBADFRMEN_MASK 0x00004000 /**< Receive Bad Frame
* Enable
*/
#define XAE_RAF_TXVTAGMODE_SHIFT 3 /**< Tx Tag mode shift bits */
#define XAE_RAF_RXVTAGMODE_SHIFT 5 /**< Rx Tag mode shift bits */
#define XAE_RAF_TXVSTRPMODE_SHIFT 7 /**< Tx strip mode shift bits*/
#define XAE_RAF_RXVSTRPMODE_SHIFT 9 /**< Rx Strip mode shift bits*/
/*@}*/
/** @name Transmit Pause Frame Register (TPF) bit definitions
* @{
*/
#define XAE_TPF_TPFV_MASK 0x0000FFFF /**< Tx pause frame value */
/*@}*/
/** @name Transmit Inter-Frame Gap Adjustement Register (TFGP) bit definitions
* @{
*/
#define XAE_TFGP_IFGP_MASK 0x0000007F /**< Transmit inter-frame
* gap adjustment value
*/
/*@}*/
/** @name Interrupt Status/Enable/Mask Registers bit definitions
* The bit definition of these three interrupt registers are the same.
* These bits are associated with the XAE_IS_OFFSET, XAE_IP_OFFSET, and
* XAE_IE_OFFSET registers.
* @{
*/
#define XAE_INT_HARDACSCMPLT_MASK 0x00000001 /**< Hard register
* access complete
*/
#define XAE_INT_AUTONEG_MASK 0x00000002 /**< Auto negotiation
* complete
*/
#define XAE_INT_RXCMPIT_MASK 0x00000004 /**< Rx complete */
#define XAE_INT_RXRJECT_MASK 0x00000008 /**< Rx frame rejected */
#define XAE_INT_RXFIFOOVR_MASK 0x00000010 /**< Rx fifo overrun */
#define XAE_INT_TXCMPIT_MASK 0x00000020 /**< Tx complete */
#define XAE_INT_RXDCMLOCK_MASK 0x00000040 /**< Rx Dcm Lock */
#define XAE_INT_MGTRDY_MASK 0x00000080 /**< MGT clock Lock */
#define XAE_INT_PHYRSTCMPLT_MASK 0x00000100 /**< Phy Reset complete */
#define XAE_INT_ALL_MASK 0x0000003F /**< All the ints */
#define XAE_INT_RECV_ERROR_MASK \
(XAE_INT_RXRJECT_MASK | XAE_INT_RXFIFOOVR_MASK) /**< INT bits that
* indicate receive
* errors
*/
/*@}*/
/** @name TPID Register (TPID) bit definitions
* @{
*/
#define XAE_TPID_0_MASK 0x0000FFFF /**< TPID 0 */
#define XAE_TPID_1_MASK 0xFFFF0000 /**< TPID 1 */
/*@}*/
/** @name Receive Configuration Word 1 (RCW1) Register bit definitions
* @{
*/
#define XAE_RCW1_RST_MASK 0x80000000 /**< Reset */
#define XAE_RCW1_JUM_MASK 0x40000000 /**< Jumbo frame enable */
#define XAE_RCW1_FCS_MASK 0x20000000 /**< In-Band FCS enable
* (FCS not stripped) */
#define XAE_RCW1_RX_MASK 0x10000000 /**< Receiver enable */
#define XAE_RCW1_VLAN_MASK 0x08000000 /**< VLAN frame enable */
#define XAE_RCW1_LT_DIS_MASK 0x02000000 /**< Length/type field valid check
* disable
*/
#define XAE_RCW1_CL_DIS_MASK 0x01000000 /**< Control frame Length check
* disable
*/
#define XAE_RCW1_1588_TIMESTAMP_EN_MASK 0x00400000 /**< Inband 1588 time
* stamp enable
*/
#define XAE_RCW1_PAUSEADDR_MASK 0x0000FFFF /**< Pause frame source
* address bits [47:32].Bits
* [31:0] are stored in register
* RCW0
*/
/*@}*/
/** @name Transmitter Configuration (TC) Register bit definitions
* @{
*/
#define XAE_TC_RST_MASK 0x80000000 /**< Reset */
#define XAE_TC_JUM_MASK 0x40000000 /**< Jumbo frame enable */
#define XAE_TC_FCS_MASK 0x20000000 /**< In-Band FCS enable
* (FCS not generated)
*/
#define XAE_TC_TX_MASK 0x10000000 /**< Transmitter enable */
#define XAE_TC_VLAN_MASK 0x08000000 /**< VLAN frame enable */
#define XAE_TC_IFG_MASK 0x02000000 /**< Inter-frame gap adjustment
* enable
*/
#define XAE_TC_1588_CMD_EN_MASK 0x00400000 /**< 1588 Cmd field enable */
/*@}*/
/** @name Flow Control Configuration (FCC) Register Bit definitions
* @{
*/
#define XAE_FCC_FCRX_MASK 0x20000000 /**< Rx flow control enable */
#define XAE_FCC_FCTX_MASK 0x40000000 /**< Tx flow control enable */
/*@}*/
/** @name Ethernet MAC Mode Configuration (EMMC) Register bit definitions
* @{
*/
#define XAE_EMMC_LINKSPEED_MASK 0xC0000000 /**< Link speed */
#define XAE_EMMC_RGMII_MASK 0x20000000 /**< RGMII mode enable */
#define XAE_EMMC_SGMII_MASK 0x10000000 /**< SGMII mode enable */
#define XAE_EMMC_GPCS_MASK 0x08000000 /**< 1000BaseX mode enable*/
#define XAE_EMMC_HOST_MASK 0x04000000 /**< Host interface enable*/
#define XAE_EMMC_TX16BIT 0x02000000 /**< 16 bit Tx client
* enable
*/
#define XAE_EMMC_RX16BIT 0x01000000 /**< 16 bit Rx client
* enable
*/
#define XAE_EMMC_LINKSPD_10 0x00000000 /**< Link Speed mask for
* 10 Mbit
*/
#define XAE_EMMC_LINKSPD_100 0x40000000 /**< Link Speed mask for 100
* Mbit
*/
#define XAE_EMMC_LINKSPD_1000 0x80000000 /**< Link Speed mask for
* 1000 Mbit
*/
/*@}*/
/** @name RGMII/SGMII Configuration (PHYC) Register bit definitions
* @{
*/
#define XAE_PHYC_SGMIILINKSPEED_MASK 0xC0000000 /**< SGMII link speed mask*/
#define XAE_PHYC_RGMIILINKSPEED_MASK 0x0000000C /**< RGMII link speed */
#define XAE_PHYC_RGMIIHD_MASK 0x00000002 /**< RGMII Half-duplex */
#define XAE_PHYC_RGMIILINK_MASK 0x00000001 /**< RGMII link status */
#define XAE_PHYC_RGLINKSPD_10 0x00000000 /**< RGMII link 10 Mbit */
#define XAE_PHYC_RGLINKSPD_100 0x00000004 /**< RGMII link 100 Mbit */
#define XAE_PHYC_RGLINKSPD_1000 0x00000008 /**< RGMII link 1000 Mbit */
#define XAE_PHYC_SGLINKSPD_10 0x00000000 /**< SGMII link 10 Mbit */
#define XAE_PHYC_SGLINKSPD_100 0x40000000 /**< SGMII link 100 Mbit */
#define XAE_PHYC_SGLINKSPD_1000 0x80000000 /**< SGMII link 1000 Mbit */
/*@}*/
/** @name MDIO Management Configuration (MC) Register bit definitions
* @{
*/
#define XAE_MDIO_MC_MDIOEN_MASK 0x00000040 /**< MII management enable*/
#define XAE_MDIO_MC_CLOCK_DIVIDE_MAX 0x3F /**< Maximum MDIO divisor */
/*@}*/
/** @name MDIO Management Control Register (MCR) Register bit definitions
* @{
*/
#define XAE_MDIO_MCR_PHYAD_MASK 0x1F000000 /**< Phy Address Mask */
#define XAE_MDIO_MCR_PHYAD_SHIFT 24 /**< Phy Address Shift */
#define XAE_MDIO_MCR_REGAD_MASK 0x001F0000 /**< Reg Address Mask */
#define XAE_MDIO_MCR_REGAD_SHIFT 16 /**< Reg Address Shift */
#define XAE_MDIO_MCR_OP_MASK 0x0000C000 /**< Operation Code Mask */
#define XAE_MDIO_MCR_OP_SHIFT 13 /**< Operation Code Shift */
#define XAE_MDIO_MCR_OP_READ_MASK 0x00008000 /**< Op Code Read Mask */
#define XAE_MDIO_MCR_OP_WRITE_MASK 0x00004000 /**< Op Code Write Mask */
#define XAE_MDIO_MCR_INITIATE_MASK 0x00000800 /**< Ready Mask */
#define XAE_MDIO_MCR_READY_MASK 0x00000080 /**< Ready Mask */
/*@}*/
/** @name MDIO Interrupt Enable/Mask/Status Registers bit definitions
* The bit definition of these three interrupt registers are the same.
* These bits are associated with the XAE_IS_OFFSET, XAE_IP_OFFSET, and
* XAE_IE_OFFSET registers.
* @{
*/
#define XAE_MDIO_INT_MIIM_RDY_MASK 0x00000001 /**< MIIM Interrupt */
/*@}*/
/** @name Axi Ethernet Unicast Address Register Word 1 (UAW1) Register Bit
* definitions
* @{
*/
#define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF /**< Station address bits
* [47:32]
* Station address bits [31:0]
* are stored in register
* UAW0 */
/*@}*/
/** @name Filter Mask Index (FMI) Register bit definitions
* @{
*/
#define XAE_FMI_PM_MASK 0x80000000 /**< Promiscuous mode
* enable
*/
#define XAE_FMI_IND_MASK 0x00000003 /**< Index Mask */
/*@}*/
/** @name Extended multicast buffer descriptor bit mask
* @{
*/
#define XAE_BD_RX_USR2_BCAST_MASK 0x00000004
#define XAE_BD_RX_USR2_IP_MCAST_MASK 0x00000002
#define XAE_BD_RX_USR2_MCAST_MASK 0x00000001
/*@}*/
/** @name Axi Ethernet Multicast Address Register Word 1 (MAW1)
* @{
*/
#define XAE_MAW1_RNW_MASK 0x00800000 /**< Multicast address
* table register read
* enable
*/
#define XAE_MAW1_ADDR_MASK 0x00030000 /**< Multicast address
* table register address
*/
#define XAE_MAW1_MULTICADDR_MASK 0x0000FFFF /**< Multicast address
* bits [47:32]
* Multicast address
* bits [31:0] are stored
* in register MAW0
*/
#define XAE_MAW1_MATADDR_SHIFT_MASK 16 /**< Number of bits to shift
* right to align with
* XAE_MAW1_CAMADDR_MASK
*/
/*@}*/
/** @name Other Constant definitions used in the driver
* @{
*/
#define XAE_SPEED_10_MBPS 10 /**< Speed of 10 Mbps */
#define XAE_SPEED_100_MBPS 100 /**< Speed of 100 Mbps */
#define XAE_SPEED_1000_MBPS 1000 /**< Speed of 1000 Mbps */
#define XAE_SOFT_TEMAC_LOW_SPEED 0 /**< For soft cores with 10/100
* Mbps speed.
*/
#define XAE_SOFT_TEMAC_HIGH_SPEED 1 /**< For soft cores with
* 10/100/1000 Mbps speed.
*/
#define XAE_HARD_TEMAC_TYPE 2 /**< For hard TEMAC cores used
* virtex-6.
*/
#define XAE_PHY_ADDR_LIMIT 31 /**< Max limit while accessing
* and searching for available
* PHYs.
*/
#define XAE_PHY_REG_NUM_LIMIT 31 /**< Max register limit in PHY
* as mandated by the spec.
*/
#define XAE_LOOPS_TO_COME_OUT_OF_RST 10000 /**< Number of loops in the driver
* API to wait for before
* returning a failure case.
*/
#define XAE_RST_DELAY_LOOPCNT_VAL 200 /**< Timeout in ticks used
* while checking if the core
* had come out of reset. The
* exact tick time is defined
* in each case/loop where it
* will be used
*/
#define XAE_VLAN_TABL_STRP_FLD_LEN 1 /**< Strip field length in vlan
* table used for extended
* vlan features.
*/
#define XAE_VLAN_TABL_TAG_FLD_LEN 1 /**< Tag field length in vlan
* table used for extended
* vlan features.
*/
#define XAE_MAX_VLAN_TABL_ENTRY 0xFFF /**< Max possible number of
* entries in vlan table used
* for extended vlan
* features.
*/
#define XAE_VLAN_TABL_VID_START_OFFSET 2 /**< VID field start offset in
* each entry in the VLAN
* table.
*/
#define XAE_VLAN_TABL_STRP_STRT_OFFSET 1 /**< Strip field start offset
* in each entry in the VLAN
* table.
*/
#define XAE_VLAN_TABL_STRP_ENTRY_MASK 0x01 /**< Mask used to extract the
* the strip field from an
* entry in VLAN table.
*/
#define XAE_VLAN_TABL_TAG_ENTRY_MASK 0x01 /**< Mask used to extract the
* the tag field from an
* entry in VLAN table.
*/
/*@}*/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
xdbg_stmnt(extern int indent_on);
#define XAxiEthernet_indent(RegOffset) \
((indent_on && ((RegOffset) >= XAE_RAF_OFFSET) && ((RegOffset) <= \
XAE_AF1_OFFSET)) ? "\t" : "")
#define XAxiEthernet_reg_name(RegOffset) \
(((RegOffset) == XAE_RAF_OFFSET) ? "XAE_RAF_OFFSET": \
((RegOffset) == XAE_TPF_OFFSET) ? "XAE_TPF_OFFSET": \
((RegOffset) == XAE_IFGP_OFFSET) ? "XAE_IFGP_OFFSET": \
((RegOffset) == XAE_IS_OFFSET) ? "XAE_IS_OFFSET": \
((RegOffset) == XAE_IP_OFFSET) ? "XAE_IP_OFFSET": \
((RegOffset) == XAE_IE_OFFSET) ? "XAE_IE_OFFSET": \
((RegOffset) == XAE_TTAG_OFFSET) ? "XAE_TTAG_OFFSET": \
((RegOffset) == XAE_RTAG_OFFSET) ? "XAE_RTAG_OFFSET": \
((RegOffset) == XAE_UAWL_OFFSET) ? "XAE_UAWL_OFFSET": \
((RegOffset) == XAE_UAWU_OFFSET) ? "XAE_UAWU_OFFSET": \
((RegOffset) == XAE_TPID0_OFFSET) ? "XAE_TPID0_OFFSET": \
((RegOffset) == XAE_TPID1_OFFSET) ? "XAE_TPID1_OFFSET": \
((RegOffset) == XAE_RCW0_OFFSET) ? "XAE_RCW0_OFFSET": \
((RegOffset) == XAE_RCW1_OFFSET) ? "XAE_RCW1_OFFSET": \
((RegOffset) == XAE_TC_OFFSET) ? "XAE_TC_OFFSET": \
((RegOffset) == XAE_FCC_OFFSET) ? "XAE_FCC_OFFSET": \
((RegOffset) == XAE_EMMC_OFFSET) ? "XAE_EMMC_OFFSET": \
((RegOffset) == XAE_PHYC_OFFSET) ? "XAE_PHYC_OFFSET": \
((RegOffset) == XAE_UAW0_OFFSET) ? "XAE_UAW0_OFFSET": \
((RegOffset) == XAE_UAW1_OFFSET) ? "XAE_UAW1_OFFSET": \
((RegOffset) == XAE_FMI_OFFSET) ? "XAE_FMI_OFFSET": \
((RegOffset) == XAE_AF0_OFFSET) ? "XAE_AF0_OFFSET": \
((RegOffset) == XAE_AF1_OFFSET) ? "XAE_AF1_OFFSET": \
((RegOffset) == XAE_TXBL_OFFSET) ? "XAE_TXBL_OFFSET": \
((RegOffset) == XAE_TXBU_OFFSET) ? "XAE_TXBU_OFFSET": \
((RegOffset) == XAE_RXBL_OFFSET) ? "XAE_RXBL_OFFSET": \
((RegOffset) == XAE_RXBU_OFFSET) ? "XAE_RXBU_OFFSET": \
((RegOffset) == XAE_RXUNDRL_OFFSET) ? "XAE_RXUNDRL_OFFSET": \
((RegOffset) == XAE_RXUNDRU_OFFSET) ? "XAE_RXUNDRU_OFFSET": \
((RegOffset) == XAE_RXFRAGL_OFFSET) ? "XAE_RXFRAGL_OFFSET": \
((RegOffset) == XAE_RXFRAGU_OFFSET) ? "XAE_RXFRAGU_OFFSET": \
((RegOffset) == XAE_RX64BL_OFFSET) ? "XAE_RX64BL_OFFSET": \
((RegOffset) == XAE_RX64BU_OFFSET) ? "XAE_RX64BU_OFFSET": \
((RegOffset) == XAE_RX65B127L_OFFSET) ? "XAE_RX65B127L_OFFSET": \
((RegOffset) == XAE_RX65B127U_OFFSET) ? "XAE_RX65B127U_OFFSET": \
((RegOffset) == XAE_RX128B255L_OFFSET) ? "XAE_RX128B255L_OFFSET": \
((RegOffset) == XAE_RX128B255U_OFFSET) ? "XAE_RX128B255U_OFFSET": \
((RegOffset) == XAE_RX256B511L_OFFSET) ? "XAE_RX256B511L_OFFSET": \
((RegOffset) == XAE_RX256B511U_OFFSET) ? "XAE_RX256B511U_OFFSET": \
((RegOffset) == XAE_RX512B1023L_OFFSET) ? "XAE_RX512B1023L_OFFSET": \
((RegOffset) == XAE_RX512B1023U_OFFSET) ? "XAE_RX512B1023U_OFFSET": \
((RegOffset) == XAE_RX1024BL_OFFSET) ? "XAE_RX1024L_OFFSET": \
((RegOffset) == XAE_RX1024BU_OFFSET) ? "XAE_RX1024U_OFFSET": \
((RegOffset) == XAE_RXOVRL_OFFSET) ? "XAE_RXOVRL_OFFSET": \
((RegOffset) == XAE_RXOVRU_OFFSET) ? "XAE_RXOVRU_OFFSET": \
((RegOffset) == XAE_TX64BL_OFFSET) ? "XAE_TX64BL_OFFSET": \
((RegOffset) == XAE_TX64BU_OFFSET) ? "XAE_TX64BU_OFFSET": \
((RegOffset) == XAE_TX65B127L_OFFSET) ? "XAE_TX65B127L_OFFSET": \
((RegOffset) == XAE_TX65B127U_OFFSET) ? "XAE_TX65B127U_OFFSET": \
((RegOffset) == XAE_TX128B255L_OFFSET) ? "XAE_TX128B255L_OFFSET": \
((RegOffset) == XAE_TX128B255U_OFFSET) ? "XAE_TX128B255U_OFFSET": \
((RegOffset) == XAE_TX256B511L_OFFSET) ? "XAE_TX256B511L_OFFSET": \
((RegOffset) == XAE_TX256B511U_OFFSET) ? "XAE_TX256B511U_OFFSET": \
((RegOffset) == XAE_TX512B1023L_OFFSET) ? "XAE_TX512B1023L_OFFSET": \
((RegOffset) == XAE_TX512B1023U_OFFSET) ? "XAE_TX512B1023U_OFFSET": \
((RegOffset) == XAE_TX1024L_OFFSET) ? "XAE_TX1024L_OFFSET": \
((RegOffset) == XAE_TX1024U_OFFSET) ? "XAE_TX1024U_OFFSET": \
((RegOffset) == XAE_TXOVRL_OFFSET) ? "XAE_TXOVRL_OFFSET": \
((RegOffset) == XAE_TXOVRU_OFFSET) ? "XAE_TXOVRU_OFFSET": \
((RegOffset) == XAE_RXFL_OFFSET) ? "XAE_RXFL_OFFSET": \
((RegOffset) == XAE_RXFU_OFFSET) ? "XAE_RXFU_OFFSET": \
((RegOffset) == XAE_RXFCSERL_OFFSET) ? "XAE_RXFCSERL_OFFSET": \
((RegOffset) == XAE_RXFCSERU_OFFSET) ? "XAE_RXFCSERU_OFFSET": \
((RegOffset) == XAE_RXBCSTFL_OFFSET) ? "XAE_RXBCSTFL_OFFSET": \
((RegOffset) == XAE_RXBCSTFU_OFFSET) ? "XAE_RXBCSTFU_OFFSET": \
((RegOffset) == XAE_RXMCSTFL_OFFSET) ? "XAE_RXMCSTFL_OFFSET": \
((RegOffset) == XAE_RXMCSTFU_OFFSET) ? "XAE_RXMCSTFU_OFFSET": \
((RegOffset) == XAE_RXCTRFL_OFFSET) ? "XAE_RXCTRFL_OFFSET": \
((RegOffset) == XAE_RXCTRFU_OFFSET) ? "XAE_RXCTRFU_OFFSET": \
((RegOffset) == XAE_RXLTERL_OFFSET) ? "XAE_RXLTERL_OFFSET": \
((RegOffset) == XAE_RXLTERU_OFFSET) ? "XAE_RXLTERU_OFFSET": \
((RegOffset) == XAE_RXVLANFL_OFFSET) ? "XAE_RXVLANFL_OFFSET": \
((RegOffset) == XAE_RXVLANFU_OFFSET) ? "XAE_RXVLANFU_OFFSET": \
((RegOffset) == XAE_RXPFL_OFFSET) ? "XAE_RXFL_OFFSET": \
((RegOffset) == XAE_RXPFU_OFFSET) ? "XAE_RXFU_OFFSET": \
((RegOffset) == XAE_RXUOPFL_OFFSET) ? "XAE_RXUOPFL_OFFSET": \
((RegOffset) == XAE_RXUOPFU_OFFSET) ? "XAE_RXUOPFU_OFFSET": \
((RegOffset) == XAE_TXFL_OFFSET) ? "XAE_TXFL_OFFSET": \
((RegOffset) == XAE_TXFU_OFFSET) ? "XAE_TXFU_OFFSET": \
((RegOffset) == XAE_TXBCSTFL_OFFSET) ? "XAE_TXBCSTFL_OFFSET": \
((RegOffset) == XAE_TXBCSTFU_OFFSET) ? "XAE_TXBCSTFU_OFFSET": \
((RegOffset) == XAE_TXMCSTFL_OFFSET) ? "XAE_TXMCSTFL_OFFSET": \
((RegOffset) == XAE_TXMCSTFU_OFFSET) ? "XAE_TXMCSTFU_OFFSET": \
((RegOffset) == XAE_TXUNDRERL_OFFSET) ? "XAE_TXUNDRERL_OFFSET": \
((RegOffset) == XAE_TXUNDRERU_OFFSET) ? "XAE_TXUNDRERU_OFFSET": \
((RegOffset) == XAE_TXCTRFL_OFFSET) ? "XAE_TXCTRFL_OFFSET": \
((RegOffset) == XAE_TXCTRFU_OFFSET) ? "XAE_TXCTRFU_OFFSET": \
((RegOffset) == XAE_TXVLANFL_OFFSET) ? "XAE_TXVLANFL_OFFSET": \
((RegOffset) == XAE_TXVLANFU_OFFSET) ? "XAE_TXVLANFU_OFFSET": \
((RegOffset) == XAE_TXPFL_OFFSET) ? "XAE_TXPFL_OFFSET": \
((RegOffset) == XAE_TXPFU_OFFSET) ? "XAE_TXPFU_OFFSET": \
((RegOffset) == XAE_TXSCL_OFFSET) ? "XAE_TXSCL_OFFSET": \
((RegOffset) == XAE_TXSCU_OFFSET) ? "XAE_TXSCU_OFFSET": \
((RegOffset) == XAE_TXMCL_OFFSET) ? "XAE_TXMCL_OFFSET": \
((RegOffset) == XAE_TXMCU_OFFSET) ? "XAE_TXMCU_OFFSET": \
((RegOffset) == XAE_TXDEFL_OFFSET) ? "XAE_TXDEFL_OFFSET": \
((RegOffset) == XAE_TXDEFU_OFFSET) ? "XAE_TXDEFU_OFFSET": \
((RegOffset) == XAE_TXLTCL_OFFSET) ? "XAE_TXLTCL_OFFSET": \
((RegOffset) == XAE_TXLTCU_OFFSET) ? "XAE_TXLTCU_OFFSET": \
((RegOffset) == XAE_TXAECL_OFFSET) ? "XAE_TXAECL_OFFSET": \
((RegOffset) == XAE_TXAECU_OFFSET) ? "XAE_TXAECU_OFFSET": \
((RegOffset) == XAE_TXEDEFL_OFFSET) ? "XAE_TXEDEFL_OFFSET": \
((RegOffset) == XAE_TXEDEFU_OFFSET) ? "XAE_TXEDEFU_OFFSET": \
((RegOffset) == XAE_RXAERL_OFFSET) ? "XAE_RXAERL_OFFSET": \
((RegOffset) == XAE_RXAERU_OFFSET) ? "XAE_RXAERU_OFFSET": \
"unknown")
#define XAxiEthernet_print_reg_o(BaseAddress, RegOffset, Value) \
xdbg_printf(XDBG_DEBUG_TEMAC_REG, "%s0x%0x -> %s(0x%0x)\n", \
XAxiEthernet_indent(RegOffset), (Value), \
XAxiEthernet_reg_name(RegOffset), (RegOffset)) \
#define XAxiEthernet_print_reg_i(BaseAddress, RegOffset, Value) \
xdbg_printf(XDBG_DEBUG_TEMAC_REG, "%s%s(0x%0x) -> 0x%0x\n", \
XAxiEthernet_indent(RegOffset), \
XAxiEthernet_reg_name(RegOffset),(RegOffset), (Value)) \
/****************************************************************************/
/**
*
* XAxiEthernet_ReadReg returns the value read from the register specified by
* <i>RegOffset</i>.
*
* @param BaseAddress is the base address of the Axi Ethernet device.
* @param RegOffset is the offset of the register to be read.
*
* @return Returns the 32-bit value of the register.
*
* @note C-style signature:
* u32 XAxiEthernet_ReadReg(u32 BaseAddress, u32 RegOffset)
*
*****************************************************************************/
#ifdef DEBUG
#define XAxiEthernet_ReadReg(BaseAddress, RegOffset) \
({ \
u32 value; \
value = Xil_In32(((BaseAddress) + (RegOffset))); \
XAxiEthernet_print_reg_i((BaseAddress), (RegOffset), value); \
})
#else
#define XAxiEthernet_ReadReg(BaseAddress, RegOffset) \
(Xil_In32(((BaseAddress) + (RegOffset))))
#endif
/****************************************************************************/
/**
*
* XAxiEthernet_WriteReg, writes <i>Data</i> to the register specified by
* <i>RegOffset</i>.
*
* @param BaseAddress is the base address of the Axi Ethernet device.
* @param RegOffset is the offset of the register to be written.
* @param Data is the 32-bit value to write to the register.
*
* @return None.
*
* @note
* C-style signature:
* void XAxiEthernet_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data)
*
*****************************************************************************/
#ifdef DEBUG
#define XAxiEthernet_WriteReg(BaseAddress, RegOffset, Data) \
({ \
XAxiEthernet_print_reg_o((BaseAddress), (RegOffset), (Data)); \
Xil_Out32(((BaseAddress) + (RegOffset)), (Data)); \
})
#else
#define XAxiEthernet_WriteReg(BaseAddress, RegOffset, Data) \
Xil_Out32(((BaseAddress) + (RegOffset)), (Data))
#endif
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,180 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xaxiethernet_porting_guide.h
*
* This is a guide on how to move from using the ll temac driver to use the
* xaxiethernet driver.
*
* The AXI Ethernet IP is based on the XPS_LL TEMAC IP.
* There are few changes in the IP and some of them are listed below
* - The Interface to access the IP is now AXI instead of the PLBV46
* - AXI4 streaming interfaces is used instead of LL (Local Link)
* - All indirect accesses to Ethernet core registers have been removed.
* - The AxiEthernet reset line is connected to the reset line of the
* device connected to the AXI4-Stream interface. Hence any reset
* of the connected device would reset AxiEthernet.
*
* Please read the HW Device specification of the AXI Ethernet IP for further
* information.
*
*
* The AXI Ethernet can be used in a DMA mode using the AXI DMA or
* used in a FIFO mode using the AXI Streaming FIFO.
*
* There is a new driver for AXI DMA which is used by the AXi Ethernet. Please
* refer the xaxidma_porting_guide.h provided as a part of the AXI DMA driver to
* see the differences from the LL DMA driver.
*
* The LL FIFO driver is a common driver for the LL FIFO and the
* AXI Streaming FIFO.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a ASA 07/18/10 First release
*
* </pre>
*
* <b>Overview</b>
*
* The API for xaxiethernet driver are similar to xlltemac driver. The prefix for the
* API functions and structures is XAxiEthernet_ for the xaxiethernet driver.
*
* The prefix for all hash-defines (option masks or generic hash-defined constants)
* start with XAE_.
*
* The Axi Ethernet API "XAxiEthernet_Reset" is different from the corresponding
* LLTEMAC API "XLlTemac_Reset". The AxiEthernet version does not do a soft
* reset of the AxiEthernet hardware. Since AxiEthernet hardware could only be
* reset through the device connected to the AxiEthernet AXI4-Stream interface,
* the user must ensure that AxiEthernet hardware initialization happens after
* the initialization of the other device.
*
* These are the classification of the APIs
* - APIs that only have prefix changes
* - APIs that have been renamed
* - APIs that are new
*
* Note that data structures have different prefix of XAxiEthernet_. Those API
* functions, that have data structures with prefix change, are considered as
* prefix change.
*
* <b>API Functions That Only Have Prefix Changes</b>
*
* Most of the functions have the prefix change and are given below
* <pre>
* xlltemac driver | xaxiethernet driver
* ---------------------------------------------------------------------------------
* XLlTemac_IsStarted(...) | XAxiEthernet_IsStarted(...)
* XLlTemac_IsDma(...) | XAxiEthernet_IsDma(...)
* XLlTemac_IsFifo(...) | XAxiEthernet_IsFifo(...)
* XLlTemac_LlDevBaseAddress(...) | XAxiEthernet_AxiDevBaseAddress(...)
* XLlTemac_IsRecvFrameDropped(...) | XAxiEthernet_IsRecvFrameDropped(...)
* XLlTemac_GetPhysicalInterface(...) | XAxiEthernet_GetPhysicalInterface(...)
* XLlTemac_IntEnable(...) | XAxiEthernet_IntEnable(...)
* XLlTemac_IntDisable(...) | XAxiEthernet_IntDisable(...)
* XLlTemac_IntPending(...) | XAxiEthernet_IntPending(...)
* XLlTemac_IntClear(...) | XAxiEthernet_IntClear(...)
* XLlTemac_IsExtFuncCap(...) | XAxiEthernet_IsExtFuncCap(...)
* XLlTemac_IsExtMcastEnable(...) | XAxiEthernet_IsExtMcastEnable(...)
* XLlTemac_IsExtMcast(...) | XAxiEthernet_IsExtMcast(...)
* XLlTemac_IsTxVlanStrp(...) | XAxiEthernet_IsTxVlanStrp(...)
* XLlTemac_IsRxVlanStrp(...) | XAxiEthernet_IsRxVlanStrp(...)
* XLlTemac_IsTxVlanTran(...) | XAxiEthernet_IsTxVlanTran(...)
* XLlTemac_IsRxVlanTran(...) | XAxiEthernet_IsRxVlanTran(...)
* XLlTemac_IsTxVlanTag(...) | XAxiEthernet_IsTxVlanTag(...)
* XLlTemac_IsRxVlanTag(...) | XAxiEthernet_IsRxVlanTag(...)
* XLlTemac_SetOptions (...) | XAxiEthernet_SetOptions(...)
* XLlTemac_ClearOptions(...) | XAxiEthernet_ClearOptions(...)
* XLlTemac_GetOptions(...) | XAxiEthernet_GetOptions(...)
* XLlTemac_SetMacAddress(...) | XAxiEthernet_SetMacAddress(...)
* XLlTemac_GetMacAddress(...) | XAxiEthernet_GetMacAddress(...)
* XLlTemac_SetMacPauseAddress(...) | XAxiEthernet_SetMacPauseAddress(...)
* XLlTemac_GetMacPauseAddress(...) | XAxiEthernet_GetMacPauseAddress(...)
* XLlTemac_SendPausePacket(...) | XAxiEthernet_SendPausePacket(...)
* XLlTemac_GetSgmiiStatus(...) | XAxiEthernet_GetSgmiiStatus(...)
* XLlTemac_GetRgmiiStatus(...) | XAxiEthernet_GetRgmiiStatus(...)
*... XLlTemac_GetOperatingSpeed(...) | XAxiEthernet_GetOperatingSpeed(...)
* XLlTemac_SetOperatingSpeed(...) | XAxiEthernet_SetOperatingSpeed(...)
* XLlTemac_PhySetMdioDivisor(...) | XAxiEthernet_PhySetMdioDivisor(...)
* XLlTemac_PhyRead(...) | XAxiEthernet_PhyRead(...)
* XLlTemac_PhyWrite(...) | XAxiEthernet_PhyWrite(...)
* XLlTemac_MulticastAdd(...) | XAxiEthernet_MulticastAdd(...)
* XLlTemac_MulticastGet(...) | XAxiEthernet_MulticastGet(...)
* XLlTemac_MulticastClear(...) | XAxiEthernet_MulticastClear(...)
* XLlTemac_SetTpid(...) | XAxiEthernet_SetTpid(...)
* XLlTemac_ClearTpid(...) | XAxiEthernet_ClearTpid(...)
* XLlTemac_GetTpid(...) | XAxiEthernet_GetTpid(...)
* XLlTemac_SetVTagMode(...) | XAxiEthernet_SetVTagMode(...)
* XLlTemac_GetVTagMode(...) | XAxiEthernet_GetVTagMode(...)
* XLlTemac_SetVStripMode(...) | XAxiEthernet_SetVStripMode(...)
* XLlTemac_GetVStripMode(...) | XAxiEthernet_GetVStripMode(...)
* XLlTemac_SetVTagValue(...) | XAxiEthernet_SetVTagValue(...)
* XLlTemac_GetVTagValue(...) | XAxiEthernet_GetVTagValue(...)
* XLlTemac_SetVidTable(...) | XAxiEthernet_SetVidTable(...)
* XLlTemac_GetVidTable(...) | XAxiEthernet_GetVidTable(...)
* XLlTemac_AddExtMulticastGroup(...) | XAxiEthernet_AddExtMulticastGroup(...)
* XLlTemac_ClearExtMulticastGroup(..)| XAxiEthernet_ClearExtMulticastGroup(...)
* XLlTemac_GetExtMulticastGroup(...) | XAxiEthernet_GetExtMulticastGroup(...)
* XLlTemac_DumpExtMulticastGroup(..) | XAxiEthernet_DumpExtMulticastGroup(...)
*</pre>
*
* <b>API Function names that have changed </b>
*
* <pre>
* xlltemac driver | xaaxiethernet driver
* -----------------------------------------------------------------------
* XLlTemac_IsRxCsum(...) | XAxiEthernet_IsRxPartialCsum(...)
* XLlTemac_IsTxCsum(...) | XAxiEthernet_IsTxPartialCsum(...)
* XLlTemac_Status(...) | XAxiEthernet_GetIntStatus
* </pre>
*
*
* <b>API Functions That Are New API Functions</b>
*
* - XAxiEthernet_GetTemacType(...)
* - XAxiEthernet_IsAvbConfigured(...)
* - XAxiEthernet_IsStatsConfigured(...)
* - XAxiEthernet_SetBadFrmRcvOption((...);
* - XAxiEthernet_ClearBadFrmRcvOption(...);
* - XAxiEthernet_DisableControlFrameLenCheck(...)
* - XAxiEthernet_EnableControlFrameLenCheck(...)
*
*
******************************************************************************/

View file

@ -0,0 +1,95 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/**
*
* @file xaxiethernet_sinit.c
*
* This file contains static initialzation functionality for Axi Ethernet driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa 6/30/10 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xaxiethernet.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/**
* XAxiEthernet_LookupConfig returns a reference to an XAxiEthernet_Config
* structure based on an unique device id, <i>DeviceId</i>. The return value
* will refer to an entry in the device configuration table defined in the
* xaxiethernet_g.c file.
*
* @param DeviceId is the unique device ID of the device for the lookup
* operation.
*
* @return
* - Returns a reference to a config record in the
* configuration table (in xaxiethernet_g.c) corresponding to
* <i>DeviceId</i>, or NULL
* - NULL if no match is found.
*
******************************************************************************/
XAxiEthernet_Config *XAxiEthernet_LookupConfig(u16 DeviceId)
{
extern XAxiEthernet_Config XAxiEthernet_ConfigTable[];
XAxiEthernet_Config *CfgPtr = NULL;
int Index;
for (Index = 0; Index < XPAR_XAXIETHERNET_NUM_INSTANCES; Index++) {
if (XAxiEthernet_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XAxiEthernet_ConfigTable[Index];
break;
}
}
return (CfgPtr);
}

View file

@ -0,0 +1,84 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef XDEBUG
#define XDEBUG
#undef DEBUG
#if defined(DEBUG) && !defined(NDEBUG)
#ifndef XDEBUG_WARNING
#define XDEBUG_WARNING
#warning DEBUG is enabled
#endif
int printf(const char *format, ...);
#define XDBG_DEBUG_ERROR 0x00000001 /* error condition messages */
#define XDBG_DEBUG_GENERAL 0x00000002 /* general debug messages */
#define XDBG_DEBUG_ALL 0xFFFFFFFF /* all debugging data */
#define XDBG_DEBUG_FIFO_REG 0x00000100 /* display register reads/writes */
#define XDBG_DEBUG_FIFO_RX 0x00000101 /* receive debug messages */
#define XDBG_DEBUG_FIFO_TX 0x00000102 /* transmit debug messages */
#define XDBG_DEBUG_FIFO_ALL 0x0000010F /* all fifo debug messages */
#define XDBG_DEBUG_TEMAC_REG 0x00000400 /* display register reads/writes */
#define XDBG_DEBUG_TEMAC_RX 0x00000401 /* receive debug messages */
#define XDBG_DEBUG_TEMAC_TX 0x00000402 /* transmit debug messages */
#define XDBG_DEBUG_TEMAC_ALL 0x0000040F /* all temac debug messages */
#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800 /* receive debug messages */
#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801 /* transmit debug messages */
#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802 /* ioctl debug messages */
#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803 /* debug msg for other routines */
#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080F /* all temac adapter debug messages */
#define xdbg_current_types (XDBG_DEBUG_ERROR | XDBG_DEBUG_GENERAL | XDBG_DEBUG_FIFO_REG | XDBG_DEBUG_TEMAC_REG)
#define xdbg_stmnt(x) x
/* ANSI Syntax */
#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0)
#else /* defined(DEBUG) && !defined(NDEBUG) */
#define xdbg_stmnt(x)
/* ANSI Syntax */
#define xdbg_printf(...)
#endif /* defined(DEBUG) && !defined(NDEBUG) */
#endif /* XDEBUG */