
Added initial support Xilinx Embedded Software. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
1772 lines
57 KiB
C
Executable file
1772 lines
57 KiB
C
Executable file
/******************************************************************************
|
|
*
|
|
* 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 THE
|
|
* XILINX CONSORTIUM 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.c
|
|
*
|
|
* The APIs in this file takes care of the primary functionalities of the driver.
|
|
* The APIs in this driver take care of the following:
|
|
* - Starting or stopping the Axi Ethernet device
|
|
* - Initializing and resetting the Axi Ethernet device
|
|
* - Setting MAC address and speed/duplex of the device
|
|
* - Provide means for controlling the PHY and communicating with it.
|
|
* - Turn on/off various features/options provided by the Axi Ethernet
|
|
* device.
|
|
* See xaxiethernet.h for a detailed description of the driver.
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -------- -------------------------------------------------------
|
|
* 1.00a asa 6/30/10 First release based on the ll temac driver
|
|
* 1.02a asa 2/16/11 Made changes in XAxiEthernet_Reset to insert delays.
|
|
* 3.02a srt 4/13/13 Removed Warnings (CR 704998).
|
|
*
|
|
* </pre>
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
#include "xaxiethernet.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
static void InitHw(XAxiEthernet *InstancePtr); /* HW reset */
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
xdbg_stmnt(int indent_on = 0;)
|
|
xdbg_stmnt(u32 _xaxiethernet_rir_value;)
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* XAxiEthernet_CfgInitialize initializes an AXI Ethernet device along with the
|
|
* <i>InstancePtr</i> that references it.
|
|
*
|
|
* The PHY is setup independently from the Ethernet core. Use the MII or
|
|
* whatever other interface may be present for setup.
|
|
*
|
|
* @param InstancePtr references the memory instance to be associated
|
|
* with the AXI Ethernet core instance upon initialization.
|
|
* @param CfgPtr references the structure holding the hardware
|
|
* configuration for the Axi Ethernet core to initialize.
|
|
* @param EffectiveAddress is the processor address used to access the
|
|
* base address of the AXI Ethernet instance. In systems with an
|
|
* MMU and virtual memory, <i>EffectiveAddress</i> is the
|
|
* virtual address mapped to the physical in
|
|
* <code>ConfigPtr->Config.BaseAddress</code>. In systems without
|
|
* an active MMU, <i>EffectiveAddress</i> should be set to the
|
|
* same value as <code>ConfigPtr->Config.BaseAddress</code>.
|
|
*
|
|
* @return XST_SUCCESS.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
int XAxiEthernet_CfgInitialize(XAxiEthernet *InstancePtr,
|
|
XAxiEthernet_Config *CfgPtr,
|
|
u32 EffectiveAddress)
|
|
{
|
|
/* Verify arguments */
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
|
|
/* Clear instance memory and make copy of configuration */
|
|
memset(InstancePtr, 0, sizeof(XAxiEthernet));
|
|
memcpy(&InstancePtr->Config, CfgPtr, sizeof(XAxiEthernet_Config));
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_CfgInitialize\n");
|
|
|
|
/* Set device base address */
|
|
InstancePtr->Config.BaseAddress = EffectiveAddress;
|
|
|
|
/* Reset the hardware and set default options */
|
|
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
|
|
|
|
XAxiEthernet_Reset(InstancePtr);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"AxiTEthernet_CfgInitialize: returning SUCCESS\n");
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_Start starts the Axi Ethernet device as follows:
|
|
* - Enable transmitter if XAE_TRANSMIT_ENABLE_OPTION is set
|
|
* - Enable receiver if XAE_RECEIVER_ENABLE_OPTION is set
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_Start(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
|
|
/* Assert bad arguments and conditions */
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
|
|
/* If already started, then there is nothing to do */
|
|
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
|
return;
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_Start\n");
|
|
|
|
/* Enable transmitter if not already enabled */
|
|
if (InstancePtr->Options & XAE_TRANSMITTER_ENABLE_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "enabling transmitter\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET);
|
|
if (!(Reg & XAE_TC_TX_MASK)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"transmitter not enabled, enabling now\n");
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET,
|
|
Reg | XAE_TC_TX_MASK);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "transmitter enabled\n");
|
|
}
|
|
|
|
/* Enable receiver */
|
|
if (InstancePtr->Options & XAE_RECEIVER_ENABLE_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "enabling receiver\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
if (!(Reg & XAE_RCW1_RX_MASK)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"receiver not enabled, enabling now\n");
|
|
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET,
|
|
Reg | XAE_RCW1_RX_MASK);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "receiver enabled\n");
|
|
}
|
|
|
|
/* Mark as started */
|
|
InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_Start: done\n");
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_Stop gracefully stops the Axi Ethernet device as follows:
|
|
* - Disable all interrupts from this device
|
|
* - Disable the receiver
|
|
*
|
|
* XAxiEthernet_Stop does not modify any of the current device options.
|
|
*
|
|
* Since the transmitter is not disabled, frames currently in internal buffers
|
|
* or in process by a DMA engine are allowed to be transmitted.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @return None
|
|
*
|
|
* @note None.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_Stop(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
|
|
/* If already stopped, then there is nothing to do */
|
|
if (InstancePtr->IsStarted == 0) {
|
|
return;
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_Stop\n");
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_Stop: disabling interrupts\n");
|
|
|
|
/* Disable interrupts */
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IE_OFFSET, 0);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_Stop: disabling receiver\n");
|
|
|
|
/* Disable the receiver */
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
Reg &= ~XAE_RCW1_RX_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, Reg);
|
|
|
|
/*
|
|
* Stopping the receiver in mid-packet causes a dropped packet
|
|
* indication from HW. Clear it.
|
|
*/
|
|
/* get the interrupt pending register */
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IP_OFFSET);
|
|
if (Reg & XAE_INT_RXRJECT_MASK) {
|
|
/* set the interrupt status register to clear the interrupt */
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
|
|
}
|
|
|
|
/* Mark as stopped */
|
|
InstancePtr->IsStarted = 0;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_Stop: done\n");
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_Reset does not perform a soft reset of the AxiEthernet core.
|
|
* AxiEthernet hardware is reset by the device connected to the AXI4-Stream
|
|
* interface.
|
|
* This function inserts some delay before proceeding to check for MgtRdy bit.
|
|
* The delay is necessary to be at a safe side. It takes a while for the reset
|
|
* process to complete and for any of the AxiEthernet registers to be accessed.
|
|
* It then checks for MgtRdy bit in IS register to know if AxiEthernet reset
|
|
* is completed or not. Subsequently it calls one more driver function to
|
|
* complete the AxiEthernet hardware initialization.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @note It is the responsibility of the user to reset the AxiEthernet
|
|
* hardware before using it. AxiEthernet hardware should be reset
|
|
* through the device connected to the AXI4-Stream interface of
|
|
* AxiEthernet.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_Reset(XAxiEthernet *InstancePtr)
|
|
{
|
|
volatile u32 TimeoutLoops;
|
|
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
/*
|
|
* Add delay of 10000 loops to give enough time to the core to come
|
|
* out of reset. Till the time core comes out of reset none of the
|
|
* AxiEthernet registers are accessible including the IS register.
|
|
*/
|
|
TimeoutLoops = XAE_LOOPS_TO_COME_OUT_OF_RST;
|
|
while (TimeoutLoops > 0) {
|
|
TimeoutLoops--;
|
|
}
|
|
|
|
/*
|
|
* Check the status of the MgtRdy bit in the interrupt status
|
|
* registers. This must be done to allow the MGT clock to become stable
|
|
* for the Sgmii and 1000BaseX PHY interfaces. No other register reads
|
|
* will be valid until this bit is valid.
|
|
* The bit is always a 1 for all other PHY interfaces.
|
|
*/
|
|
TimeoutLoops = XAE_RST_DELAY_LOOPCNT_VAL;
|
|
while (TimeoutLoops &&
|
|
(! (XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IS_OFFSET) & XAE_INT_MGTRDY_MASK))) {
|
|
TimeoutLoops--;
|
|
}
|
|
|
|
if(0 == TimeoutLoops) {
|
|
Xil_AssertVoidAlways();
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_Reset\n");
|
|
|
|
/* Stop the device and reset HW */
|
|
XAxiEthernet_Stop(InstancePtr);
|
|
InstancePtr->Options = XAE_DEFAULT_OPTIONS;
|
|
|
|
/* Setup HW */
|
|
InitHw(InstancePtr);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* InitHw (internal use only) performs a one-time setup of a Axi Ethernet device.
|
|
* The setup performed here only need to occur once after any reset.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @note None.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
static void InitHw(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet InitHw\n");
|
|
|
|
|
|
/* Disable the receiver */
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
Reg &= ~XAE_RCW1_RX_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, Reg);
|
|
|
|
/*
|
|
* Stopping the receiver in mid-packet causes a dropped packet
|
|
* indication from HW. Clear it.
|
|
*/
|
|
/* Get the interrupt pending register */
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IP_OFFSET);
|
|
if (Reg & XAE_INT_RXRJECT_MASK) {
|
|
/*
|
|
* Set the interrupt status register to clear the pending
|
|
* interrupt
|
|
*/
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
|
|
}
|
|
|
|
/*
|
|
* Sync default options with HW but leave receiver and transmitter
|
|
* disabled. They get enabled with XAxiEthernet_Start() if
|
|
* XAE_TRANSMITTER_ENABLE_OPTION and XAE_RECEIVER_ENABLE_OPTION
|
|
* are set
|
|
*/
|
|
XAxiEthernet_SetOptions(InstancePtr, InstancePtr->Options &
|
|
~(XAE_TRANSMITTER_ENABLE_OPTION |
|
|
XAE_RECEIVER_ENABLE_OPTION));
|
|
|
|
XAxiEthernet_ClearOptions(InstancePtr, ~InstancePtr->Options);
|
|
|
|
/* Set default MDIO divisor */
|
|
XAxiEthernet_PhySetMdioDivisor(InstancePtr, XAE_MDIO_DIV_DFT);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet InitHw: done\n");
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_SetMacAddress sets the MAC address for the Axi Ethernet device,
|
|
* specified by <i>InstancePtr</i> to the MAC address specified by
|
|
* <i>AddressPtr</i>.
|
|
* The Axi Ethernet device must be stopped before calling this function.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param AddressPtr is a reference to the 6-byte MAC address to set.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS on successful completion.
|
|
* - XST_DEVICE_IS_STARTED if the Axi Ethernet device has not
|
|
* stopped,
|
|
*
|
|
* @note
|
|
* This routine also supports the extended/new VLAN and multicast mode. The
|
|
* XAE_RAF_NEWFNCENBL_MASK bit dictates which offset will be configured.
|
|
*
|
|
******************************************************************************/
|
|
int XAxiEthernet_SetMacAddress(XAxiEthernet *InstancePtr, void *AddressPtr)
|
|
{
|
|
u32 MacAddr;
|
|
u8 *Aptr = (u8 *) AddressPtr;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
Xil_AssertNonvoid(AddressPtr != NULL);
|
|
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
|
return (XST_DEVICE_IS_STARTED);
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_SetMacAddress: setting mac address to:0x%08x%8x%8x%8x%8x%8x\n",
|
|
Aptr[0], Aptr[1], Aptr[2], Aptr[3], Aptr[4], Aptr[5]);
|
|
|
|
/* Prepare MAC bits in either UAW0/UAWL */
|
|
MacAddr = Aptr[0];
|
|
MacAddr |= Aptr[1] << 8;
|
|
MacAddr |= Aptr[2] << 16;
|
|
MacAddr |= Aptr[3] << 24;
|
|
/* Check to see if it is in extended/new mode. */
|
|
if (!(XAxiEthernet_IsExtFuncCap(InstancePtr))) {
|
|
/*
|
|
* Set the MAC bits [31:0] in UAW0.
|
|
* Having Aptr be unsigned type prevents the following
|
|
* operations from sign extending.
|
|
*/
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAW0_OFFSET, MacAddr);
|
|
|
|
/* There are reserved bits in UAW1 so don't affect them */
|
|
MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAW1_OFFSET);
|
|
MacAddr &= ~XAE_UAW1_UNICASTADDR_MASK;
|
|
|
|
/* Set MAC bits [47:32] in UAW1 */
|
|
MacAddr |= Aptr[4];
|
|
MacAddr |= Aptr[5] << 8;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAW1_OFFSET, MacAddr);
|
|
|
|
return (XST_SUCCESS);
|
|
} else { /* Extended mode */
|
|
/*
|
|
* Set the MAC bits [31:0] in UAWL register.
|
|
* Having Aptr be unsigned type prevents the following
|
|
* operations from sign extending.
|
|
*/
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAWL_OFFSET, MacAddr);
|
|
|
|
/* Set MAC bits [47:32] in UAWU register. */
|
|
MacAddr = 0;
|
|
MacAddr |= Aptr[4];
|
|
MacAddr |= Aptr[5] << 8;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAWU_OFFSET, MacAddr);
|
|
|
|
return (XST_SUCCESS);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_GetMacAddress gets the MAC address for the Axi Ethernet,
|
|
* specified by <i>InstancePtr</i> into the memory buffer specified by
|
|
* <i>AddressPtr</i>.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param AddressPtr references the memory buffer to store the retrieved
|
|
* MAC address. This memory buffer must be at least 6 bytes in
|
|
* length.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note
|
|
*
|
|
* This routine also supports the extended/new VLAN and multicast mode. The
|
|
* XAE_RAF_NEWFNCENBL_MASK bit dictates which offset will be configured.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_GetMacAddress(XAxiEthernet *InstancePtr, void *AddressPtr)
|
|
{
|
|
u32 MacAddr;
|
|
u8 *Aptr = (u8 *) AddressPtr;
|
|
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(AddressPtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
|
|
/* Check to see if it is in extended/new mode. */
|
|
if (!(XAxiEthernet_IsExtFuncCap(InstancePtr))) {
|
|
/* Read MAC bits [31:0] in UAW0 */
|
|
MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAW0_OFFSET);
|
|
Aptr[0] = (u8) MacAddr;
|
|
Aptr[1] = (u8) (MacAddr >> 8);
|
|
Aptr[2] = (u8) (MacAddr >> 16);
|
|
Aptr[3] = (u8) (MacAddr >> 24);
|
|
|
|
/* Read MAC bits [47:32] in UAW1 */
|
|
MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAW1_OFFSET);
|
|
Aptr[4] = (u8) MacAddr;
|
|
Aptr[5] = (u8) (MacAddr >> 8);
|
|
} else { /* Extended/new mode */
|
|
/* Read MAC bits [31:0] in UAWL register */
|
|
MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAWL_OFFSET);
|
|
Aptr[0] = (u8) MacAddr;
|
|
Aptr[1] = (u8) (MacAddr >> 8);
|
|
Aptr[2] = (u8) (MacAddr >> 16);
|
|
Aptr[3] = (u8) (MacAddr >> 24);
|
|
|
|
/* Read MAC bits [47:32] in UAWU register */
|
|
MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_UAWU_OFFSET);
|
|
Aptr[4] = (u8) MacAddr;
|
|
Aptr[5] = (u8) (MacAddr >> 8);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_UpdateDepOption check and update dependent options for
|
|
* new/extended features. This is a helper function that is meant to be called
|
|
* by XAxiEthernet_SetOptions() and XAxiEthernet_ClearOptions().
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return Dependent options that are required to set/clear per
|
|
* hardware requirement.
|
|
*
|
|
* @note
|
|
*
|
|
* This helper function collects the dependent OPTION(s) per hardware design.
|
|
* When conflicts arises, extended features have precedence over legacy ones.
|
|
* Two operations to be considered,
|
|
* 1. Adding extended options. If XATE_VLAN_OPTION is enabled and enable one of
|
|
* extended VLAN options, XATE_VLAN_OPTION should be off and configure to
|
|
* hardware.
|
|
* However, axi-ethernet instance Options variable still holds
|
|
* XATE_VLAN_OPTION so when all of the extended feature are removed,
|
|
* XATE_VLAN_OPTION can be effective and configured to hardware.
|
|
* 2. Removing extended options. Remove extended option can not just remove
|
|
* the selected extended option and dependent options. All extended
|
|
* options need to be verified and remained when one or more extended
|
|
* options are enabled.
|
|
*
|
|
* Dependent options are :
|
|
* - XAE_VLAN_OPTION,
|
|
* - XAE_JUMBO_OPTION
|
|
* - XAE_FCS_INSERT_OPTION,
|
|
* - XAE_FCS_STRIP_OPTION
|
|
* - XAE_PROMISC_OPTION.
|
|
*
|
|
******************************************************************************/
|
|
static u32 XAxiEthernet_UpdateDepOptions(XAxiEthernet *InstancePtr)
|
|
{
|
|
/*
|
|
* This is a helper function for XAxiEthernet_[Set|Clear]Options(),
|
|
* verification has been done before invoke this function.
|
|
*/
|
|
u32 DepOptions = InstancePtr->Options;
|
|
|
|
/*
|
|
* The extended/new features require some OPTIONS to be on/off per
|
|
* hardware design. We determine these extended/new functions here
|
|
* first and also on/off other OPTIONS later. So that dependent
|
|
* OPTIONS are in sync and _[Set|Clear]Options() can be performed
|
|
* seamlessly.
|
|
*/
|
|
|
|
/* Enable extended multicast option */
|
|
if (DepOptions & XAE_EXT_MULTICAST_OPTION) {
|
|
/*
|
|
* When extended multicast module is enabled in HW,
|
|
* XAE_PROMISC_OPTION is required to be enabled.
|
|
*/
|
|
if (XAxiEthernet_IsExtMcast(InstancePtr)) {
|
|
DepOptions |= XAE_PROMISC_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext multicast\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"EXT MULTICAST is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended transmit VLAN translation option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_TRAN_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend TX VLAN translation.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsTxVlanTran(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_INSERT_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Tx VLAN trans\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"TX VLAN TRANSLATION is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended receive VLAN translation option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_TRAN_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend RX VLAN translation.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsRxVlanTran(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_STRIP_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Rx VLAN trans\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"RX VLAN TRANSLATION is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended transmit VLAN tag option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_TAG_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend TX VLAN tagging.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsTxVlanTag(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_INSERT_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
DepOptions |= XAE_JUMBO_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Tx VLAN tag\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"TX VLAN TAG is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended receive VLAN tag option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_TAG_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend RX VLAN tagging.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsRxVlanTag(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_STRIP_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
DepOptions |= XAE_JUMBO_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Rx VLAN tag\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"RX VLAN TAG is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended transmit VLAN strip option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_STRP_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend TX VLAN stripping.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsTxVlanStrp(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_INSERT_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
DepOptions |= XAE_JUMBO_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Tx VLAN strip\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"TX VLAN STRIP is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/* Enable extended receive VLAN strip option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_STRP_OPTION) {
|
|
/*
|
|
* Check if hardware is built with extend RX VLAN stripping.
|
|
* if not, output an information message.
|
|
*/
|
|
if (XAxiEthernet_IsRxVlanStrp(InstancePtr)) {
|
|
DepOptions |= XAE_FCS_STRIP_OPTION;
|
|
DepOptions &= ~XAE_VLAN_OPTION;
|
|
DepOptions |= XAE_JUMBO_OPTION;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"CheckDepOptions: enabling ext Rx VLAN strip\n");
|
|
} else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"RX VLAN STRIP is not built in hardware\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Options and dependent Options together is what hardware and user
|
|
* are happy with. But we still need to keep original options
|
|
* in case option(s) are set/cleared, overall options can be managed.
|
|
* Return DepOptions to XAxiEthernet_[Set|Clear]Options for final
|
|
* configuration.
|
|
*/
|
|
return(DepOptions);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_SetOptions enables the options, <i>Options</i> for the
|
|
* Axi Ethernet, specified by <i>InstancePtr</i>. Axi Ethernet should be
|
|
* stopped with XAxiEthernet_Stop() before changing options.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param Options is a bitmask of OR'd XAE_*_OPTION values for options to
|
|
* set. Options not specified are not affected.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS on successful completion.
|
|
* - XST_DEVICE_IS_STARTED if the device has not been stopped.
|
|
*
|
|
*
|
|
* @note
|
|
* See xaxiethernet.h for a description of the available options.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
int XAxiEthernet_SetOptions(XAxiEthernet *InstancePtr, u32 Options)
|
|
{
|
|
u32 Reg; /* Generic register contents */
|
|
u32 RegRcw1; /* Reflects original contents of RCW1 */
|
|
u32 RegTc; /* Reflects original contents of TC */
|
|
u32 RegNewRcw1; /* Reflects new contents of RCW1 */
|
|
u32 RegNewTc; /* Reflects new contents of TC */
|
|
u32 DepOptions; /* Required dependent options for new features */
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
|
return (XST_DEVICE_IS_STARTED);
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetOptions\n");
|
|
|
|
/*
|
|
* Set options word to its new value.
|
|
* The step is required before calling _UpdateDepOptions() since
|
|
* we are operating on updated options.
|
|
*/
|
|
InstancePtr->Options |= Options;
|
|
|
|
/*
|
|
* There are options required to be on/off per hardware requirement.
|
|
* Invoke _UpdateDepOptions to check hardware availability and update
|
|
* options accordingly.
|
|
*/
|
|
DepOptions = XAxiEthernet_UpdateDepOptions(InstancePtr);
|
|
|
|
/*
|
|
* New/extended function bit should be on if any new/extended features
|
|
* are on and hardware is built with them.
|
|
*/
|
|
if (DepOptions & (XAE_EXT_MULTICAST_OPTION |
|
|
XAE_EXT_TXVLAN_TRAN_OPTION |
|
|
XAE_EXT_RXVLAN_TRAN_OPTION |
|
|
XAE_EXT_TXVLAN_TAG_OPTION |
|
|
XAE_EXT_RXVLAN_TAG_OPTION |
|
|
XAE_EXT_TXVLAN_STRP_OPTION |
|
|
XAE_EXT_RXVLAN_STRP_OPTION)) {
|
|
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) | XAE_RAF_NEWFNCENBL_MASK);
|
|
}
|
|
|
|
/*
|
|
* Many of these options will change the RCW1 or TC registers.
|
|
* To reduce the amount of IO to the device, group these options here
|
|
* and change them all at once.
|
|
*/
|
|
/* Get current register contents */
|
|
RegRcw1 = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
RegTc = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET);
|
|
RegNewRcw1 = RegRcw1;
|
|
RegNewTc = RegTc;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"current control regs: RCW1: 0x%0x; TC: 0x%0x\n",
|
|
RegRcw1, RegTc);
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"Options: 0x%0x; default options: 0x%0x\n",Options,
|
|
XAE_DEFAULT_OPTIONS);
|
|
|
|
/* Turn on jumbo packet support for both Rx and Tx */
|
|
if (DepOptions & XAE_JUMBO_OPTION) {
|
|
RegNewTc |= XAE_TC_JUM_MASK;
|
|
RegNewRcw1 |= XAE_RCW1_JUM_MASK;
|
|
}
|
|
|
|
/* Turn on VLAN packet support for both Rx and Tx */
|
|
if (DepOptions & XAE_VLAN_OPTION) {
|
|
RegNewTc |= XAE_TC_VLAN_MASK;
|
|
RegNewRcw1 |= XAE_RCW1_VLAN_MASK;
|
|
}
|
|
|
|
/* Turn on FCS stripping on receive packets */
|
|
if (DepOptions & XAE_FCS_STRIP_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: enabling fcs stripping\n");
|
|
RegNewRcw1 &= ~XAE_RCW1_FCS_MASK;
|
|
}
|
|
|
|
/* Turn on FCS insertion on transmit packets */
|
|
if (DepOptions & XAE_FCS_INSERT_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: enabling fcs insertion\n");
|
|
RegNewTc &= ~XAE_TC_FCS_MASK;
|
|
}
|
|
|
|
/* Turn on length/type field checking on receive packets */
|
|
if (DepOptions & XAE_LENTYPE_ERR_OPTION) {
|
|
RegNewRcw1 &= ~XAE_RCW1_LT_DIS_MASK;
|
|
}
|
|
|
|
/* Enable transmitter */
|
|
if (DepOptions & XAE_TRANSMITTER_ENABLE_OPTION) {
|
|
RegNewTc |= XAE_TC_TX_MASK;
|
|
}
|
|
|
|
/* Enable receiver */
|
|
if (DepOptions & XAE_RECEIVER_ENABLE_OPTION) {
|
|
RegNewRcw1 |= XAE_RCW1_RX_MASK;
|
|
}
|
|
|
|
/* Change the TC or RCW1 registers if they need to be modified */
|
|
if (RegTc != RegNewTc) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: writing tc: 0x%0x\n", RegNewTc);
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET, RegNewTc);
|
|
}
|
|
|
|
if (RegRcw1 != RegNewRcw1) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: writing rcw1: 0x%0x\n", RegNewRcw1);
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, RegNewRcw1);
|
|
}
|
|
|
|
/*
|
|
* Rest of options twiddle bits of other registers. Handle them one at
|
|
* a time
|
|
*/
|
|
|
|
/* Turn on flow control */
|
|
if (DepOptions & XAE_FLOW_CONTROL_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: enabling flow control\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FCC_OFFSET);
|
|
Reg |= XAE_FCC_FCRX_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FCC_OFFSET, Reg);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: rcw1 is now (fcc):0x%0x\n",
|
|
XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET));
|
|
|
|
/* Turn on promiscuous frame filtering (all frames are received ) */
|
|
if (DepOptions & XAE_PROMISC_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: enabling promiscuous mode\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FMI_OFFSET);
|
|
Reg |= XAE_FMI_PM_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FMI_OFFSET, Reg);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: rcw1 is now (afm):0x%0x\n",
|
|
XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET));
|
|
|
|
/* Allow broadcast address filtering */
|
|
if (DepOptions & XAE_BROADCAST_OPTION) {
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg &= ~XAE_RAF_BCSTREJ_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: rcw1 is now (raf):0x%0x\n",
|
|
XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET));
|
|
|
|
/* Allow multicast address filtering */
|
|
if (DepOptions & (XAE_MULTICAST_OPTION | XAE_EXT_MULTICAST_OPTION)) {
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg &= ~XAE_RAF_MCSTREJ_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: rcw1 is now (raf2): 0x%0x\n",
|
|
XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET));
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"setOptions: rcw1 is now (raf2):0x%0x\n",
|
|
XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET));
|
|
|
|
/*
|
|
* The remaining options not handled here are managed elsewhere in the
|
|
* driver. No register modifications are needed at this time.
|
|
* Reflecting the option in InstancePtr->Options is good enough for
|
|
* now.
|
|
*/
|
|
/* Enable extended multicast option */
|
|
if (DepOptions & XAE_EXT_MULTICAST_OPTION) {
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) | XAE_RAF_EMULTIFLTRENBL_MASK);
|
|
}
|
|
|
|
/*
|
|
* New/extended [TX|RX] VLAN translation option does not have specific
|
|
* bits to on/off.
|
|
*/
|
|
|
|
/* Enable extended transmit VLAN tag option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_TAG_OPTION) {
|
|
Reg = XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg = (Reg & ~XAE_RAF_TXVTAGMODE_MASK) |
|
|
(XAE_DEFAULT_TXVTAG_MODE <<
|
|
XAE_RAF_TXVTAGMODE_SHIFT);
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/* Enable extended receive VLAN tag option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_TAG_OPTION) {
|
|
Reg = XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg = (Reg & ~XAE_RAF_RXVTAGMODE_MASK) |
|
|
(XAE_DEFAULT_RXVTAG_MODE <<
|
|
XAE_RAF_RXVTAGMODE_SHIFT);
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/* Enable extended transmit VLAN strip option */
|
|
if (Options & XAE_EXT_TXVLAN_STRP_OPTION) {
|
|
Reg = XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg = (Reg & ~XAE_RAF_TXVSTRPMODE_MASK) |
|
|
(XAE_DEFAULT_TXVSTRP_MODE <<
|
|
XAE_RAF_TXVSTRPMODE_SHIFT);
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/* Enable extended receive VLAN strip option */
|
|
if (Options & XAE_EXT_RXVLAN_STRP_OPTION) {
|
|
Reg = XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg = (Reg & ~XAE_RAF_RXVSTRPMODE_MASK) |
|
|
(XAE_DEFAULT_RXVSTRP_MODE <<
|
|
XAE_RAF_RXVSTRPMODE_SHIFT);
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* The remaining options not handled here are managed elsewhere in the
|
|
* driver. No register modifications are needed at this time.
|
|
* Reflecting the option in InstancePtr->Options is good enough for
|
|
* now.
|
|
*/
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "setOptions: returning SUCCESS\n");
|
|
return (XST_SUCCESS);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_ClearOptions clears the options, <i>Options</i> for the
|
|
* Axi Ethernet, specified by <i>InstancePtr</i>. Axi Ethernet should be stopped
|
|
* with XAxiEthernet_Stop() before changing options.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param Options is a bitmask of OR'd XAE_*_OPTION values for options to
|
|
* clear. Options not specified are not affected.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS on successful completion.
|
|
* - XST_DEVICE_IS_STARTED if the device has not been stopped.
|
|
*
|
|
* @note
|
|
* See xaxiethernet.h for a description of the available options.
|
|
*
|
|
******************************************************************************/
|
|
int XAxiEthernet_ClearOptions(XAxiEthernet *InstancePtr, u32 Options)
|
|
{
|
|
u32 Reg; /* Generic */
|
|
u32 RegRcw1; /* Reflects original contents of RCW1 */
|
|
u32 RegTc; /* Reflects original contents of TC */
|
|
u32 RegNewRcw1; /* Reflects new contents of RCW1 */
|
|
u32 RegNewTc; /* Reflects new contents of TC */
|
|
u32 DepOptions; /* Required dependent options for new features */
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearOptions: 0x%08x\n",
|
|
Options);
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
|
return (XST_DEVICE_IS_STARTED);
|
|
}
|
|
|
|
/*
|
|
* Set options word to its new value.
|
|
* The step is required before calling _UpdateDepOptions() since
|
|
* we are operating on updated options.
|
|
*/
|
|
InstancePtr->Options &= ~Options;
|
|
|
|
/*
|
|
* There are options required to be on/off per hardware requirement.
|
|
* Invoke _UpdateDepOptions to check hardware availability and update
|
|
* options accordingly.
|
|
*/
|
|
DepOptions = ~(XAxiEthernet_UpdateDepOptions(InstancePtr));
|
|
|
|
/*
|
|
* New/extended function bit should be off if none of new/extended
|
|
* features is on after hardware is validated and gone through
|
|
* _UpdateDepOptions().
|
|
*/
|
|
if (!(~(DepOptions) & (XAE_EXT_MULTICAST_OPTION |
|
|
XAE_EXT_TXVLAN_TRAN_OPTION |
|
|
XAE_EXT_RXVLAN_TRAN_OPTION |
|
|
XAE_EXT_TXVLAN_TAG_OPTION |
|
|
XAE_EXT_RXVLAN_TAG_OPTION |
|
|
XAE_EXT_TXVLAN_STRP_OPTION |
|
|
XAE_EXT_RXVLAN_STRP_OPTION))) {
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_NEWFNCENBL_MASK);
|
|
}
|
|
|
|
/*
|
|
* Many of these options will change the RCW1 or TC registers.
|
|
* Group these options here and change them all at once. What we are
|
|
* trying to accomplish is to reduce the amount of IO to the device
|
|
*/
|
|
|
|
/* Get the current register contents */
|
|
RegRcw1 = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
RegTc = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET);
|
|
RegNewRcw1 = RegRcw1;
|
|
RegNewTc = RegTc;
|
|
|
|
/* Turn off jumbo packet support for both Rx and Tx */
|
|
if (DepOptions & XAE_JUMBO_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling jumbo\n");
|
|
RegNewTc &= ~XAE_TC_JUM_MASK;
|
|
RegNewRcw1 &= ~XAE_RCW1_JUM_MASK;
|
|
}
|
|
|
|
/* Turn off VLAN packet support for both Rx and Tx */
|
|
if (DepOptions & XAE_VLAN_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling vlan\n");
|
|
RegNewTc &= ~XAE_TC_VLAN_MASK;
|
|
RegNewRcw1 &= ~XAE_RCW1_VLAN_MASK;
|
|
}
|
|
|
|
/* Turn off FCS stripping on receive packets */
|
|
if (DepOptions & XAE_FCS_STRIP_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling fcs strip\n");
|
|
RegNewRcw1 |= XAE_RCW1_FCS_MASK;
|
|
}
|
|
|
|
/* Turn off FCS insertion on transmit packets */
|
|
if (DepOptions & XAE_FCS_INSERT_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling fcs insert\n");
|
|
RegNewTc |= XAE_TC_FCS_MASK;
|
|
}
|
|
|
|
/* Turn off length/type field checking on receive packets */
|
|
if (DepOptions & XAE_LENTYPE_ERR_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling lentype err\n");
|
|
RegNewRcw1 |= XAE_RCW1_LT_DIS_MASK;
|
|
}
|
|
|
|
/* Disable transmitter */
|
|
if (DepOptions & XAE_TRANSMITTER_ENABLE_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling transmitter\n");
|
|
RegNewTc &= ~XAE_TC_TX_MASK;
|
|
}
|
|
|
|
/* Disable receiver */
|
|
if (DepOptions & XAE_RECEIVER_ENABLE_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling receiver\n");
|
|
RegNewRcw1 &= ~XAE_RCW1_RX_MASK;
|
|
}
|
|
|
|
/* Change the TC and RCW1 registers if they need to be
|
|
* modified
|
|
*/
|
|
if (RegTc != RegNewTc) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: setting TC: 0x%0x\n", RegNewTc);
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_TC_OFFSET, RegNewTc);
|
|
}
|
|
|
|
if (RegRcw1 != RegNewRcw1) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: setting RCW1: 0x%0x\n",RegNewRcw1);
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, RegNewRcw1);
|
|
}
|
|
|
|
/*
|
|
* Rest of options twiddle bits of other registers. Handle them one at
|
|
* a time
|
|
*/
|
|
|
|
/* Turn off flow control */
|
|
if (DepOptions & XAE_FLOW_CONTROL_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling flow control\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FCC_OFFSET);
|
|
Reg &= ~XAE_FCC_FCRX_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FCC_OFFSET, Reg);
|
|
}
|
|
|
|
/* Turn off promiscuous frame filtering */
|
|
if (DepOptions & XAE_PROMISC_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling promiscuous mode\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FMI_OFFSET);
|
|
Reg &= ~XAE_FMI_PM_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_FMI_OFFSET, Reg);
|
|
}
|
|
|
|
/* Disable broadcast address filtering */
|
|
if (DepOptions & XAE_BROADCAST_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions: disabling broadcast mode\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg |= XAE_RAF_BCSTREJ_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/* Disable multicast address filtering */
|
|
if ((DepOptions & XAE_MULTICAST_OPTION) &&
|
|
(DepOptions & XAE_EXT_MULTICAST_OPTION)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling multicast mode\n");
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg |= XAE_RAF_MCSTREJ_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/* Disable extended multicast option */
|
|
if (DepOptions & XAE_EXT_MULTICAST_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling extended multicast mode\n");
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_EMULTIFLTRENBL_MASK);
|
|
}
|
|
|
|
/* Disable extended transmit VLAN tag option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_TAG_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling extended TX VLAN tag mode\n");
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_TXVTAGMODE_MASK);
|
|
}
|
|
|
|
/* Disable extended receive VLAN tag option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_TAG_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling extended RX VLAN tag mode\n");
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_RXVTAGMODE_MASK);
|
|
}
|
|
|
|
/* Disable extended transmit VLAN strip option */
|
|
if (DepOptions & XAE_EXT_TXVLAN_STRP_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling extended TX VLAN strip mode\n");
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_TXVSTRPMODE_MASK);
|
|
}
|
|
|
|
/* Disable extended receive VLAN strip option */
|
|
if (DepOptions & XAE_EXT_RXVLAN_STRP_OPTION) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_ClearOptions:disabling extended RX VLAN strip mode\n");
|
|
XAxiEthernet_WriteReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET,
|
|
XAxiEthernet_ReadReg((InstancePtr)->Config.BaseAddress,
|
|
XAE_RAF_OFFSET) & ~XAE_RAF_RXVSTRPMODE_MASK);
|
|
}
|
|
|
|
/*
|
|
* The remaining options not handled here are managed elsewhere in the
|
|
* driver. No register modifications are needed at this time.
|
|
* Reflecting the option in InstancePtr->Options is good enough for
|
|
* now.
|
|
*/
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "ClearOptions: returning SUCCESS\n");
|
|
return (XST_SUCCESS);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_GetOptions returns the current option settings.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return Returns a bitmask of XAE_*_OPTION constants,
|
|
* each bit specifying an option that is currently active.
|
|
*
|
|
* @note
|
|
* See xaxiethernet.h for a description of the available options.
|
|
*
|
|
******************************************************************************/
|
|
u32 XAxiEthernet_GetOptions(XAxiEthernet *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
return (InstancePtr->Options);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_GetOperatingSpeed gets the current operating link speed. This
|
|
* may be the value set by XAxiEthernet_SetOperatingSpeed() or a hardware
|
|
* default.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return Returns the link speed in units of megabits per second (10 /
|
|
* 100 / 1000).
|
|
* Can return a value of 0, in case it does not get a valid
|
|
* speed from EMMC.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
u16 XAxiEthernet_GetOperatingSpeed(XAxiEthernet *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetOperatingSpeed\n");
|
|
switch (XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_EMMC_OFFSET) & XAE_EMMC_LINKSPEED_MASK) {
|
|
|
|
case XAE_EMMC_LINKSPD_1000:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_GetOperatingSpeed: returning 1000\n");
|
|
return XAE_SPEED_1000_MBPS;
|
|
|
|
case XAE_EMMC_LINKSPD_100:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_GetOperatingSpeed: returning 100\n");
|
|
return XAE_SPEED_100_MBPS;
|
|
|
|
case XAE_EMMC_LINKSPD_10:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_GetOperatingSpeed: returning 10\n");
|
|
return (XAE_SPEED_10_MBPS);
|
|
|
|
default:
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_SetOperatingSpeed sets the current operating link speed. For
|
|
* any traffic to be passed, this speed must match the current
|
|
* MII/GMII/SGMII/RGMII link speed.
|
|
*
|
|
* @param InstancePtr references the Axi Ethernet on which to
|
|
* operate.
|
|
* @param Speed is the speed to set in units of Mbps.
|
|
* Valid values are 10, 100, or 1000.
|
|
*
|
|
* @return - XST_SUCCESS on successful setting of speed.
|
|
* - XST_FAILURE, if the speed cannot be set for the present
|
|
* harwdare configuration.
|
|
*
|
|
* @note None.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
int XAxiEthernet_SetOperatingSpeed(XAxiEthernet *InstancePtr, u16 Speed)
|
|
{
|
|
u32 EmmcReg;
|
|
u8 TemacType;
|
|
u8 PhyType;
|
|
u8 SetSpeed = TRUE;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
|
Xil_AssertNonvoid((Speed == XAE_SPEED_10_MBPS) ||
|
|
(Speed == XAE_SPEED_100_MBPS) ||
|
|
(Speed == XAE_SPEED_1000_MBPS));
|
|
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetOperatingSpeed\n");
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_SetOperatingSpeed: setting speed to:%d (0x%0x)\n",
|
|
Speed, Speed);
|
|
|
|
TemacType = XAxiEthernet_GetTemacType(InstancePtr);
|
|
PhyType = XAxiEthernet_GetPhysicalInterface(InstancePtr);
|
|
(void) (TemacType);
|
|
|
|
/*
|
|
* The following code checks for all allowable speed conditions before
|
|
* writing to the register. Please refer to the hardware specs for
|
|
* more information on it.
|
|
* For PHY type 1000Base-x, 10 and 100 Mbps are not supported.
|
|
* For soft/hard Axi Ethernet core, 1000 Mbps is supported in all PHY
|
|
* types except MII.
|
|
*/
|
|
if((Speed == XAE_SPEED_10_MBPS) || (Speed == XAE_SPEED_100_MBPS)) {
|
|
if(PhyType == XAE_PHY_TYPE_1000BASE_X) {
|
|
SetSpeed = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
if((Speed == XAE_SPEED_1000_MBPS) &&
|
|
(PhyType == XAE_PHY_TYPE_MII)) {
|
|
SetSpeed = FALSE;
|
|
}
|
|
}
|
|
|
|
if(SetSpeed == TRUE) {
|
|
/*
|
|
* Get the current contents of the EMAC config register and
|
|
* zero out speed bits
|
|
*/
|
|
EmmcReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_EMMC_OFFSET) & ~XAE_EMMC_LINKSPEED_MASK;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_SetOperatingSpeed: current speed: 0x%0x\n",
|
|
EmmcReg);
|
|
switch (Speed) {
|
|
case XAE_SPEED_10_MBPS:
|
|
break;
|
|
|
|
case XAE_SPEED_100_MBPS:
|
|
EmmcReg |= XAE_EMMC_LINKSPD_100;
|
|
break;
|
|
|
|
case XAE_SPEED_1000_MBPS:
|
|
EmmcReg |= XAE_EMMC_LINKSPD_1000;
|
|
break;
|
|
|
|
default:
|
|
return (XST_FAILURE);
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_SetOperatingSpeed: new speed: 0x%0x\n",
|
|
EmmcReg);
|
|
/* Set register and return */
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_EMMC_OFFSET, EmmcReg);
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_SetOperatingSpeed: done\n");
|
|
return (XST_SUCCESS);
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_ERROR,
|
|
"Speed not compatible with the Axi Ethernet Phy type\n");
|
|
return (XST_FAILURE);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_SetBadFrmRcvOption is used to enable the bad frame receive
|
|
* option. If enabled, this option ensures that bad receive frames are allowed
|
|
* and passed to the AXI4-Stream interface as if they are good frames.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_SetBadFrmRcvOption(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg |= XAE_RAF_RXBADFRMEN_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_ClearBadFrmRcvOption is used to disable the bad frame receive
|
|
* option.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_ClearBadFrmRcvOption(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
|
|
Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET);
|
|
Reg &= ~XAE_RAF_RXBADFRMEN_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RAF_OFFSET, Reg);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_DisableControlFrameLenCheck is used to disable the length check
|
|
* for control frames (pause frames). This means once the API is called, control
|
|
* frames larger than the minimum frame length are accepted.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_DisableControlFrameLenCheck(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 RegRcw1;
|
|
|
|
/* Get the current register contents */
|
|
RegRcw1 = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
RegRcw1 |= XAE_RCW1_CL_DIS_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, RegRcw1);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_EnableControlFrameLenCheck is used to enable the length check
|
|
* for control frames (pause frames). After calling the API, all control frames
|
|
* received will be checked for proper length (less than minimum frame length).
|
|
* By default, upon normal start up, control frame length check is enabled.
|
|
* Hence this API needs to be called only if previously the control frame length
|
|
* check has been disabled by calling the API
|
|
* XAxiEthernet_DisableControlFrameLenCheck.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_EnableControlFrameLenCheck(XAxiEthernet *InstancePtr)
|
|
{
|
|
u32 RegRcw1;
|
|
|
|
/* Get the current register contents */
|
|
RegRcw1 = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET);
|
|
RegRcw1 &= ~XAE_RCW1_CL_DIS_MASK;
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_RCW1_OFFSET, RegRcw1);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XAxiEthernet_PhySetMdioDivisor sets the MDIO clock divisor in the
|
|
* Axi Ethernet,specified by <i>InstancePtr</i> to the value, <i>Divisor</i>.
|
|
* This function must be called once after each reset prior to accessing
|
|
* MII PHY registers.
|
|
*
|
|
* From the Virtex-6(TM) and Spartan-6 (TM) Embedded Tri-Mode Ethernet
|
|
* MAC User's Guide, the following equation governs the MDIO clock to the PHY:
|
|
*
|
|
* <pre>
|
|
* f[HOSTCLK]
|
|
* f[MDC] = -----------------------
|
|
* (1 + Divisor) * 2
|
|
* </pre>
|
|
*
|
|
* where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the
|
|
* MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not
|
|
* exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster
|
|
* access.
|
|
*
|
|
* @param InstancePtr references the Axi Ethernet instance on which to
|
|
* operate.
|
|
* @param Divisor is the divisor value to set within the range of 0 to
|
|
* XAE_MDIO_MC_CLK_DVD_MAX.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_PhySetMdioDivisor(XAxiEthernet *InstancePtr, u8 Divisor)
|
|
{
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
|
|
Xil_AssertVoid(Divisor <= XAE_MDIO_MC_CLOCK_DIVIDE_MAX);
|
|
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_PhySetMdioDivisor\n");
|
|
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MC_OFFSET,
|
|
(u32) Divisor | XAE_MDIO_MC_MDIOEN_MASK);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
* XAxiEthernet_PhyRead reads the specified PHY register, <i>RegiseterNum</i>
|
|
* on the PHY specified by <i>PhyAddress</i> into <i>PhyDataPtr</i>.
|
|
* This Ethernet driver does not require the device to be stopped before reading
|
|
* from the PHY. It is the responsibility of the calling code to stop the
|
|
* device if it is deemed necessary.
|
|
*
|
|
* Note that the Axi Ethernet hardware provides the ability to talk to a PHY
|
|
* that adheres to the Media Independent Interface (MII) as defined in the
|
|
* IEEE 802.3 standard.
|
|
*
|
|
* <b>It is important that calling code set up the MDIO clock with
|
|
* XAxiEthernet_PhySetMdioDivisor() prior to accessing the PHY with this
|
|
* function.
|
|
* </b>
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param PhyAddress is the address of the PHY to be written (multiple
|
|
* PHYs supported).
|
|
* @param RegisterNum is the register number, 0-31, of the specific PHY
|
|
* register to write.
|
|
* @param PhyDataPtr is a reference to the location where the 16-bit
|
|
* result value is stored.
|
|
*
|
|
* @return None.
|
|
*
|
|
*
|
|
* @note
|
|
*
|
|
* There is the possibility that this function will not return if the hardware
|
|
* is broken (i.e., it never sets the status bit indicating that the write is
|
|
* done). If this is of concern, the calling code should provide a mechanism
|
|
* suitable for recovery.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_PhyRead(XAxiEthernet *InstancePtr, u32 PhyAddress,
|
|
u32 RegisterNum, u16 *PhyDataPtr)
|
|
{
|
|
u32 MdioCtrlReg = 0;
|
|
|
|
/*
|
|
* Verify that each of the inputs are valid.
|
|
*/
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(PhyAddress <= XAE_PHY_ADDR_LIMIT);
|
|
Xil_AssertVoid(RegisterNum <= XAE_PHY_REG_NUM_LIMIT);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_PhyRead: BaseAddress: 0x%08x\n",
|
|
InstancePtr->Config.BaseAddress);
|
|
|
|
/*
|
|
* Wait till MDIO interface is ready to accept a new transaction.
|
|
*/
|
|
while (!(XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET) & XAE_MDIO_MCR_READY_MASK)) {
|
|
;
|
|
}
|
|
|
|
MdioCtrlReg = ((PhyAddress << XAE_MDIO_MCR_PHYAD_SHIFT) &
|
|
XAE_MDIO_MCR_PHYAD_MASK) |
|
|
((RegisterNum << XAE_MDIO_MCR_REGAD_SHIFT)
|
|
& XAE_MDIO_MCR_REGAD_MASK) |
|
|
XAE_MDIO_MCR_INITIATE_MASK |
|
|
XAE_MDIO_MCR_OP_READ_MASK;
|
|
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET, MdioCtrlReg);
|
|
|
|
|
|
/*
|
|
* Wait till MDIO transaction is completed.
|
|
*/
|
|
while (!(XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET) & XAE_MDIO_MCR_READY_MASK)) {
|
|
;
|
|
}
|
|
|
|
/* Read data */
|
|
*PhyDataPtr = (u16) XAxiEthernet_ReadReg
|
|
(InstancePtr->Config.BaseAddress,XAE_MDIO_MRD_OFFSET);
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,
|
|
"XAxiEthernet_PhyRead: Value retrieved: 0x%0x\n", *PhyDataPtr);
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
* XAxiEthernet_PhyWrite writes <i>PhyData</i> to the specified PHY register,
|
|
* <i>RegiseterNum</i> on the PHY specified by <i>PhyAddress</i>. This Ethernet
|
|
* driver does not require the device to be stopped before writing to the PHY.
|
|
* It is the responsibility of the calling code to stop the device if it is
|
|
* deemed necessary.
|
|
*
|
|
* Note that the Axi Ethernet hardware provides the ability to talk to a PHY
|
|
* that adheres to the Media Independent Interface (MII) as defined in the
|
|
* IEEE 802.3 standard.
|
|
*
|
|
* <b>It is important that calling code set up the MDIO clock with
|
|
* XAxiEthernet_PhySetMdioDivisor() prior to accessing the PHY with this
|
|
* function.</b>
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Ethernet instance to be
|
|
* worked on.
|
|
* @param PhyAddress is the address of the PHY to be written (multiple
|
|
* PHYs supported).
|
|
* @param RegisterNum is the register number, 0-31, of the specific PHY
|
|
* register to write.
|
|
* @param PhyData is the 16-bit value that will be written to the
|
|
* register.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note
|
|
*
|
|
* There is the possibility that this function will not return if the hardware
|
|
* is broken (i.e., it never sets the status bit indicating that the write is
|
|
* done). If this is of concern, the calling code should provide a mechanism
|
|
* suitable for recovery.
|
|
*
|
|
******************************************************************************/
|
|
void XAxiEthernet_PhyWrite(XAxiEthernet *InstancePtr, u32 PhyAddress,
|
|
u32 RegisterNum, u16 PhyData)
|
|
{
|
|
u32 MdioCtrlReg = 0;
|
|
|
|
/*
|
|
* Verify that each of the inputs are valid.
|
|
*/
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(PhyAddress <= XAE_PHY_ADDR_LIMIT);
|
|
Xil_AssertVoid(RegisterNum <= XAE_PHY_REG_NUM_LIMIT);
|
|
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_PhyWrite\n");
|
|
|
|
/*
|
|
* Wait till the MDIO interface is ready to accept a new transaction.
|
|
*/
|
|
while (!(XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET) & XAE_MDIO_MCR_READY_MASK)) {
|
|
;
|
|
}
|
|
|
|
MdioCtrlReg = ((PhyAddress << XAE_MDIO_MCR_PHYAD_SHIFT) &
|
|
XAE_MDIO_MCR_PHYAD_MASK) |
|
|
((RegisterNum << XAE_MDIO_MCR_REGAD_SHIFT) &
|
|
XAE_MDIO_MCR_REGAD_MASK) |
|
|
XAE_MDIO_MCR_INITIATE_MASK |
|
|
XAE_MDIO_MCR_OP_WRITE_MASK;
|
|
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MWD_OFFSET, PhyData);
|
|
|
|
XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET, MdioCtrlReg);
|
|
|
|
/*
|
|
* Wait till the MDIO interface is ready to accept a new transaction.
|
|
*/
|
|
while (!(XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XAE_MDIO_MCR_OFFSET) & XAE_MDIO_MCR_READY_MASK)) {
|
|
;
|
|
}
|
|
|
|
}
|
|
|