/****************************************************************************** * * 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_control.c * * This file has driver APIs related to the controlling of the extended * features of the AXI Ethernet device. Please note that APIs for turning on/off * any of the driver features are present in axiethernet.c. This file takes care * of controlling these features. * - Normal/extended multicast filtering * - Normal/extended VLAN features * - RGMII/SGMII features * * See xaxiethernet.h for a detailed description of the driver. * *
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa  6/30/10 First release based on the ll temac driver
* 
*****************************************************************************/ /***************************** Include Files *********************************/ #include "xaxiethernet.h" /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Function Prototypes ******************************/ /************************** Variable Definitions *****************************/ /*****************************************************************************/ /** * XAxiEthernet_MulticastAdd adds the Ethernet address, AddressPtr to the * Axi Ethernet device's multicast filter list, at list index Entry. The * address referenced by AddressPtr may be of any unicast, multicast, or * broadcast address form. The hardware for the Axi Ethernet device can hold up * to XAE_MULTI_MAT_ENTRIES addresses in this filter list.

* * The device must be stopped to use this function.

* * Once an Ethernet address is programmed, the Axi Ethernet device will begin * receiving data sent from that address. The Axi Ethernet hardware does not * have a control bit to disable multicast filtering. The only way to prevent * the Axi Ethernet device from receiving messages from an Ethernet address in * the Multicast Address Table (MAT) is to clear it with * XAxiEthernet_MulticastClear(). * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr is a pointer to the 6-byte Ethernet address to set. * The previous address at the location Entry (if any) is * overwritten with the value at AddressPtr. * @param Entry is the hardware storage location to program this address * and must be between 0 to (XAE_MULTI_MAT_ENTRIES - 1). * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED.if the Axi Ethernet device is not * stopped. * * @note * * This routine works only with normal multicast filtering feature. A maximum * of 4 multicast addresses can be stored in the HW provided multicast table. * * To use the extended multicast feature, extended multicast filtering must * be enabled by using driver API XAxiEthernet_SetOptions with proper option * fields set. Once extended multicast filtering is enabled, the APIs * XAxiEthernet_[Add|Clear|Get]ExtMulticastGroup() must be used to manage * multicast address groups. * ******************************************************************************/ int XAxiEthernet_MulticastAdd(XAxiEthernet *InstancePtr, void *AddressPtr, int Entry) { u32 Af0Reg; u32 Af1Reg; u32 FmiReg; u8 *Aptr = (u8 *) AddressPtr; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(AddressPtr != NULL); Xil_AssertNonvoid(Entry < XAE_MULTI_MAT_ENTRIES); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastAdd\n"); /* The device must be stopped before clearing the multicast hash * table. */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastAdd: returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Set MAC bits [31:0] */ Af0Reg = Aptr[0]; Af0Reg |= Aptr[1] << 8; Af0Reg |= Aptr[2] << 16; Af0Reg |= Aptr[3] << 24; /* Set MAC bits [47:32] */ Af1Reg = Aptr[4]; Af1Reg |= Aptr[5] << 8; FmiReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET); FmiReg &= 0xFFFFFF00; FmiReg |= (Entry); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET, FmiReg); /* Add in MAT address */ xdbg_printf(XDBG_DEBUG_GENERAL, "Setting MAT entry: %d\n", Entry); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_AF0_OFFSET, Af0Reg); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_AF1_OFFSET, Af1Reg); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_MulticastGet gets the Ethernet address stored at * index Entry in the Axi Ethernet device's multicast filter list.

* * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr references the memory buffer to store the retrieved * Ethernet address. This memory buffer must be at least 6 bytes * in length. * @param Entry is the hardware storage location from which to retrieve * the address and must be between 0 to (XAE_MULTI_MAT_ENTRIES - 1) * * @return None. * * @note * * This routine works only with normal multicast filtering feature. A maximum * of 4 multicast addresses can be stored in the HW provided multicast table. * * To use the extended multicast feature, extended multicast filtering must * be enabled by using driver API XAxiEthernet_SetOptions with proper option * fields set. Once extended multicast filtering is enabled, the APIs * XAxiEthernet_[Add|Clear|Get]ExtMulticastGroup() must be used to manage * multicast address groups. * ******************************************************************************/ void XAxiEthernet_MulticastGet(XAxiEthernet *InstancePtr, void *AddressPtr, int Entry) { u32 Af0Reg; u32 Af1Reg; u32 FmiReg; u8 *Aptr = (u8 *) AddressPtr; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(AddressPtr != NULL); Xil_AssertVoid(Entry < XAE_MULTI_MAT_ENTRIES); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastGet\n"); FmiReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET); FmiReg &= 0xFFFFFF00; FmiReg |= (Entry); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET, FmiReg); Af0Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_AF0_OFFSET); Af1Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_AF1_OFFSET); /* Copy the address to the user buffer */ Aptr[0] = (u8) Af0Reg; Aptr[1] = (u8) (Af0Reg >> 8); Aptr[2] = (u8) (Af0Reg >> 16); Aptr[3] = (u8) (Af0Reg >> 24); Aptr[4] = (u8) Af1Reg; Aptr[5] = (u8) (Af1Reg >> 8); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastGet: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_MulticastClear clears the Ethernet address stored at index * Entry in the Axi Ethernet device's multicast filter list.

* * The device must be stopped to use this function.

* * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Entry is the HW storage location used when this address was * added. It must be between 0 to (XAE_MULTI_MAT_ENTRIES - 1). * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED.if the Axi Ethernet device is not * stopped. * * @note * * This routine works only with normal multicast filtering feature. A maximum * of 4 multicast addresses can be stored in the HW provided multicast table. * * To use the extended multicast feature, extended multicast filtering must * be enabled by using driver API XAxiEthernet_SetOptions with proper option * fields set. Once extended multicast filtering is enabled, the APIs * XAxiEthernet_[Add|Clear|Get]ExtMulticastGroup() must be used to manage * multicast address groups. * ******************************************************************************/ int XAxiEthernet_MulticastClear(XAxiEthernet *InstancePtr, int Entry) { u32 FmiReg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Entry < XAE_MULTI_MAT_ENTRIES); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastClear\n"); /* * The device must be stopped before clearing the multicast hash * table. */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastClear:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } FmiReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET); FmiReg &= 0xFFFFFF00; FmiReg |= (Entry); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_FMI_OFFSET, FmiReg); /* Clear the entry by writing 0:0:0:0:0:0 to it */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_AF0_OFFSET, 0); XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_AF1_OFFSET, 0); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_MulticastClear: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_SetMacPauseAddress sets the MAC address used for pause frames * to AddressPtr. AddressPtr will be the address the Axi Ethernet * device will recognize as being for pause frames. Pause frames transmitted * with XAxiEthernet_SendPausePacket() will also use this address. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr is a pointer to the 6-byte Ethernet address to set. * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * * @note None. * ******************************************************************************/ int XAxiEthernet_SetMacPauseAddress(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); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress\n"); /* Be sure device has been stopped */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Set the MAC bits [31:0] in RCW0 register */ MacAddr = Aptr[0]; MacAddr |= Aptr[1] << 8; MacAddr |= Aptr[2] << 16; MacAddr |= Aptr[3] << 24; XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RCW0_OFFSET, MacAddr); /* RCW1 contains other info that must be preserved */ MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RCW1_OFFSET); MacAddr &= ~XAE_RCW1_PAUSEADDR_MASK; /* Set MAC bits [47:32] */ MacAddr |= Aptr[4]; MacAddr |= Aptr[5] << 8; XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RCW1_OFFSET, MacAddr); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetMacPauseAddress gets the MAC address used for pause frames * for the Axi Ethernet device specified by InstancePtr. * * @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 None. * ******************************************************************************/ void XAxiEthernet_GetMacPauseAddress(XAxiEthernet *InstancePtr, void *AddressPtr) { u32 MacAddr; u8 *Aptr = (u8 *) AddressPtr; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(AddressPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress\n"); /* Read MAC bits [31:0] in ERXC0 */ MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RCW0_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 RCW1 */ MacAddr = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RCW1_OFFSET); Aptr[4] = (u8) MacAddr; Aptr[5] = (u8) (MacAddr >> 8); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_SendPausePacket sends a pause packet with the value of * PauseValue. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param PauseValue is the pause value in units of 512 bit times. * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * * @note None. * ******************************************************************************/ int XAxiEthernet_SendPausePacket(XAxiEthernet *InstancePtr, u16 PauseValue) { Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetMacPauseAddress\n"); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SendPausePacket:returning DEVICE_IS_STOPPED\n"); return (XST_DEVICE_IS_STOPPED); } /* Send flow control frame */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_TPF_OFFSET, (u32) PauseValue & XAE_TPF_TPFV_MASK); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SendPausePacket: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetSgmiiStatus get the state of the link when using the SGMII * media interface. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param SpeedPtr references the location to store the result, which is * the auto negotiated link speed in units of Mbits/sec, either 0, * 10, 100, or 1000. * * @return * - XST_SUCCESS on successful completion. * - XST_NO_FEATURE if the Axi Ethernet device is not using an * SGMII interface, * * @note Currently SGMII PHY does not support half duplex mode. * ******************************************************************************/ int XAxiEthernet_GetSgmiiStatus(XAxiEthernet *InstancePtr, u16 *SpeedPtr) { int PhyType; u32 EgmicReg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(SpeedPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetSgmiiStatus\n"); /* Make sure PHY is SGMII */ PhyType = XAxiEthernet_GetPhysicalInterface(InstancePtr); if (PhyType != XAE_PHY_TYPE_SGMII) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetSgmiiStatus: returning NO_FEATURE\n"); return (XST_NO_FEATURE); } /* Get the current contents of RGMII/SGMII config register */ EgmicReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_PHYC_OFFSET); /* Extract speed */ switch (EgmicReg & XAE_PHYC_SGMIILINKSPEED_MASK) { case XAE_PHYC_SGLINKSPD_10: *SpeedPtr = XAE_SPEED_10_MBPS; break; case XAE_PHYC_SGLINKSPD_100: *SpeedPtr = XAE_SPEED_100_MBPS; break; case XAE_PHYC_SGLINKSPD_1000: *SpeedPtr = XAE_SPEED_1000_MBPS; break; default: *SpeedPtr = 0; } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetSgmiiStatus: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetRgmiiStatus get the state of the link when using the RGMII * media interface. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param SpeedPtr references the location to store the result, which is * the auto negotiated link speed in units of Mbits/sec, * either 0, 10, 100, or 1000. * @param IsFullDuplexPtr references the value that is set by this * function to indicate full duplex operation. * IsFullDuplexPtr is set to TRUE when the RGMII link is * operating in full duplex mode, otherwise it is set to FALSE. * @param IsLinkUpPtr references the value that is set by this function * to indicate the link status.IsLinkUpPtr is set to TRUE * when the RGMII link up, otherwise it is set to FALSE. * * @return * - XST_SUCCESS on successful completion. * - XST_NO_FEATURE if the Axi Ethernet device is not using an * RGMII interface, * * @note None. * ******************************************************************************/ int XAxiEthernet_GetRgmiiStatus(XAxiEthernet *InstancePtr, u16 *SpeedPtr, int *IsFullDuplexPtr, int *IsLinkUpPtr) { int PhyType; u32 EgmicReg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(SpeedPtr != NULL); Xil_AssertNonvoid(IsFullDuplexPtr != NULL); Xil_AssertNonvoid(IsLinkUpPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetRgmiiStatus\n"); /* Make sure PHY is RGMII */ PhyType = XAxiEthernet_GetPhysicalInterface(InstancePtr); if ((PhyType != XAE_PHY_TYPE_RGMII_1_3) && (PhyType != XAE_PHY_TYPE_RGMII_2_0)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetRgmiiStatus: returning NO_FEATURE\n"); return (XST_NO_FEATURE); } /* Get the current contents of RGMII/SGMII config register */ EgmicReg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_PHYC_OFFSET); /* Extract speed */ switch (EgmicReg & XAE_PHYC_RGMIILINKSPEED_MASK) { case XAE_PHYC_RGLINKSPD_10: *SpeedPtr = XAE_SPEED_10_MBPS; break; case XAE_PHYC_RGLINKSPD_100: *SpeedPtr = XAE_SPEED_100_MBPS; break; case XAE_PHYC_RGLINKSPD_1000: *SpeedPtr = XAE_SPEED_1000_MBPS; break; default: *SpeedPtr = 0; } /* Extract duplex and link status */ if (EgmicReg & XAE_PHYC_RGMIIHD_MASK) { *IsFullDuplexPtr = FALSE; } else { *IsFullDuplexPtr = TRUE; } if (EgmicReg & XAE_PHYC_RGMIILINK_MASK) { *IsLinkUpPtr = TRUE; } else { *IsLinkUpPtr = FALSE; } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetRgmiiStatus: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_SetTpid sets the VLAN Tag Protocol Identifier(TPID). * * Four values can be configured - 0x8100, 0x9100, 0x9200, 0x88A8. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Tpid is a hex value to be added to the TPID table. The four * values that can be added are 0x8100, 0x9100, 0x9200, 0x88A8. * @param Entry is the hardware storage location to program this address * and must be between 0..XAE_TPID_MAX_ENTRIES. * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED, if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable or have * the VLAN tag capability. * - XST_INVALID_PARAM if Tpid is not one of supported values. * * @note The device must be stopped to use this function. * *****************************************************************************/ int XAxiEthernet_SetTpid(XAxiEthernet *InstancePtr, u16 Tpid, u8 Entry) { u32 RegTpid; u32 RegTpidOffset; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Entry < XAE_TPID_MAX_ENTRIES); /* The device must be stopped before modify VLAN TPID */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetTpid: returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check hw capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetTpid: returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetTpid\n"); /* Verify TPID */ switch (Tpid) { case 0x8100: case 0x88a8: case 0x9100: case 0x9200: break; default: return (XST_INVALID_PARAM); } /* Determine which register to operate on */ if (Entry < 2) { RegTpidOffset = XAE_TPID0_OFFSET; } else { RegTpidOffset = XAE_TPID1_OFFSET; } RegTpid = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, RegTpidOffset); /* Determine upper/lower 16 bits to operate on */ if (Entry % 2) { /* Program HW */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, RegTpidOffset, (RegTpid & XAE_TPID_0_MASK) | (Tpid << 16)); } else { /* Program HW */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, RegTpidOffset, (RegTpid & XAE_TPID_1_MASK) | Tpid); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetTpid: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_ClearTpid clears the VLAN Tag Protocol Identifier(TPID). * * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Entry is the hardware storage location to program this address * and must be between 0..XAE_TPID_MAX_ENTRIES. * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable or have * the VLAN tag capability. * * @note The device must be stopped to use this function. * *****************************************************************************/ int XAxiEthernet_ClearTpid(XAxiEthernet *InstancePtr, u8 Entry) { u32 RegTpid; u32 RegTpidOffset; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Entry < XAE_TPID_MAX_ENTRIES); /* The device must be stopped before modify VLAN TPID */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearTpid: returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check hw capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearTpid: returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearExtTpid\n"); /* Determine which register to operate on */ if (Entry < 2) { RegTpidOffset = XAE_TPID0_OFFSET; } else { RegTpidOffset = XAE_TPID1_OFFSET; } RegTpid = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, RegTpidOffset); /* Determine upper/lower 16 bits to operate on */ if (Entry % 2) { /* Program HW */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, RegTpidOffset, (RegTpid & XAE_TPID_1_MASK)); } else { /* Program HW */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, RegTpidOffset, (RegTpid & XAE_TPID_0_MASK)); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearTpid: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetTpid gets the VLAN Tag Protocol Identifier value (TPID). * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param TpidPtr references the location to store the result. * @param Entry is the hardware storage location to program this address * and must be between 0..XAE_TPID_MAX_ENTRIES. * * @return None. * * @note None. * *****************************************************************************/ void XAxiEthernet_GetTpid(XAxiEthernet *InstancePtr, u16 *TpidPtr, u8 Entry) { u32 RegTpid; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(TpidPtr != NULL); Xil_AssertVoid(Entry < XAE_TPID_MAX_ENTRIES); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetTpid\n"); if (Entry < 2) { RegTpid = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_TPID0_OFFSET); } else { RegTpid = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_TPID1_OFFSET); } if (Entry % 2) { *TpidPtr = (RegTpid >> 16); } else { *TpidPtr = (RegTpid & XAE_TPID_0_MASK); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetTpid: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_SetVTagMode configures the VLAN tagging mode. * * Four modes can be configured, * - XAE_VTAG_NONE for no tagging. * - XAE_VTAG_ALL to tag all frames. * - XAE_VTAG_EXISTED to tag already tagged frames. * - XAE_VTAG_SELECT to tag selected already tagged frames based on VID * value. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Mode is the VLAN tag mode. Value must be between b'00-b'11. * @param Dir must be either XAE_TX or XAE_RX. * * @return * - XST_SUCCESS. on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable or have * the TX VLAN tag capability. * - XST_INVALID_PARAM if Mode is not one of supported modes. * * @note * * The device must be stopped to use this function.

* * The fourth mode (specified by XAE_VTAG_SELECT) requires a method for * specifying which tagged frames should receive an additional VLAN tag. * The VLAN translation table 'tag enabled' is referenced. That configuration * is handled in XAxiEthernet_SetVidTable(). * * Mode value shifting is handled in this function. No shifting is required to * call this function. * *****************************************************************************/ int XAxiEthernet_SetVTagMode(XAxiEthernet *InstancePtr, u32 Mode, int Dir) { u32 RegRaf; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid((Dir == XAE_TX) || (Dir == XAE_RX)); /* The device must be stopped before modify TX VLAN Tag mode */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagMode:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check hw capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagMode: returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } /* Mode has to be one of the supported values */ switch (Mode) { case XAE_VTAG_NONE: case XAE_VTAG_ALL: case XAE_VTAG_EXISTED: case XAE_VTAG_SELECT: break; default: return (XST_INVALID_PARAM); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagMode\n"); /* Program HW */ RegRaf = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET); /* Transmit direction */ if (XAE_TX == Dir) { XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET, ((RegRaf & ~XAE_RAF_TXVTAGMODE_MASK) | (Mode << XAE_RAF_TXVTAGMODE_SHIFT))); } else { /* Receive direction */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET, ((RegRaf & ~XAE_RAF_RXVTAGMODE_MASK) | (Mode << XAE_RAF_RXVTAGMODE_SHIFT))); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagMode: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetVTagMode gets VLAN tagging mode. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be worked on. * @param ModePtr references the location to store the VLAN tag mode. * Value is between b'00-b'11. * @param Dir must be either XAE_TX or XAE_RX. * * @return None. * * @note * * The device must be stopped to use this function.

* Mode value shifting is handled in this function. No shifting is required to * call this function. * *****************************************************************************/ void XAxiEthernet_GetVTagMode(XAxiEthernet *InstancePtr, u8 *ModePtr, int Dir) { u32 RegRaf; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(ModePtr != NULL); Xil_AssertVoid((Dir == XAE_TX) || (Dir == XAE_RX)); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVTagMode\n"); /* Access HW configuration */ RegRaf = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET); /* Transmit direction */ if (XAE_TX == Dir) { *ModePtr = (RegRaf & XAE_RAF_TXVTAGMODE_MASK) >> XAE_RAF_TXVTAGMODE_SHIFT; } else { /* Receive direction */ *ModePtr = (RegRaf & XAE_RAF_RXVTAGMODE_MASK) >> XAE_RAF_RXVTAGMODE_SHIFT; } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVTagMode: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_SetVStripMode configures the VLAN strip mode. * * Three modes can be configured : * - XAE_VSTRP_NONE for no stripping. * - XAE_VSTRP_ALL to strip one tag from all frames. * - XAE_VSTRP_SELECT to strip one tag from already selected tagged frames * based on VID value. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Mode is the VLAN strip mode. Value must be b'00, b'01, or b'11. * @param Dir must be either XAE_TX or XAE_RX. * * @return * - XST_SUCCESS on successful completion., returns XST_SUCCESS. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable or have * the TX VLAN strip capability. * - XST_INVALID_PARAM if Mode is not one of supported modes. * * @note * * The device must be stopped to use this function.

* The third mode (specified by XAE_VSTRP_SELECT) requires a method for * specifying which tagged frames should be stripped. The VLAN translation * table 'stripped enabled' is referenced. That configuration is handled in * XAxiEthernet_SetVidTable(). * * Mode value shifting is handled in this function. No shifting is required to * call this function. * *****************************************************************************/ int XAxiEthernet_SetVStripMode(XAxiEthernet *InstancePtr, u32 Mode, int Dir) { u32 RegRaf; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid((Dir == XAE_TX) || (Dir == XAE_RX)); /* The device must be stopped before modify TX VLAN Tag mode */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVStripMode: returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check HW capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVStripMode:returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } /* Mode has to be one of the supported values */ switch (Mode) { case XAE_VSTRP_NONE: case XAE_VSTRP_ALL: case XAE_VSTRP_SELECT: break; default: return (XST_INVALID_PARAM); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetStripMode\n"); /* Program HW */ RegRaf = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET); /* Transmit direction */ if (XAE_TX == Dir) { XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET, ((RegRaf & ~XAE_RAF_TXVSTRPMODE_MASK) | (Mode << XAE_RAF_TXVSTRPMODE_SHIFT))); } else { /* Receive direction */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET, ((RegRaf & ~XAE_RAF_RXVSTRPMODE_MASK) | (Mode << XAE_RAF_RXVSTRPMODE_SHIFT))); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVStripMode:returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetVStripMode gets the VLAN stripping mode. * * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param ModePtr references the location to store the VLAN strip mode * returned by this function. Value is b'00, b'01 or b'11. * Refer XAE_VTSRAP_* in xaxiethernet.h file for the details. * @param Dir must be either XAE_TX or XAE_RX. * * @return None. * * @note * * Mode value shifting is handled in this function. No shifting is required to * call this function. * *****************************************************************************/ void XAxiEthernet_GetVStripMode(XAxiEthernet *InstancePtr, u8 *ModePtr, int Dir) { u32 RegRaf; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(ModePtr != NULL); Xil_AssertVoid((Dir == XAE_TX) || (Dir == XAE_RX)); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVStripMode\n"); /* Access HW configuration */ RegRaf = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RAF_OFFSET); /* Transmit direction */ if (XAE_TX == Dir) { *ModePtr = (RegRaf & XAE_RAF_TXVSTRPMODE_MASK) >> XAE_RAF_TXVSTRPMODE_SHIFT; } else { /* Receive direction */ *ModePtr = (RegRaf & XAE_RAF_RXVSTRPMODE_MASK) >> XAE_RAF_RXVSTRPMODE_SHIFT; } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVStripMode: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_SetVTagValue configures the VLAN tagging value. * * The device must be stopped to use this function.

* * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param VTagValue is the VLAN tag value to be configured. A 32bit * value. * TPID, one of the following 16 bit values, * 0x8100, 0x88a8, 0x9100, 0x9200. * Priority, 3 bits * CFI, 1 bit * VID, 12 bits * @param Dir must be either XAE_TX or XAE_RX. * * @return * - XST_SUCCESS on successful completion, returns . * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable/have * TX VLAN tag capability. * - XST_INVALID_PARAM, if the TPID is not one the four supported * values. * * @note * * The four supported TPID values are 0x8100, 0x88a8, 0x9100, 0x9200. * XAxiEthernet_SetVTagValue performs verification on TPID only. * * Ethernet VLAN frames' VLAN type/length(2B) and tag control information(2B). * Bit layout : bbbb bbbb bbbb bbbb bbb b bbbb bbbb bbbb * \ / | | \ VID (12b) / * \ / | CFI bit (1b) * TPID (16b) priority bit (3b) * *****************************************************************************/ int XAxiEthernet_SetVTagValue(XAxiEthernet *InstancePtr, u32 VTagValue, int Dir) { Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid((Dir == XAE_TX) || (Dir == XAE_RX)); /* The device must be stopped before modifying TX VLAN Tag value */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagValue:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check HW capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagValue:returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } /* Verify TPID */ switch (VTagValue >> 16) { case 0x8100: case 0x88a8: case 0x9100: case 0x9200: break; default: return (XST_INVALID_PARAM); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagValue\n"); /* Program HW */ /* Transmit direction */ if (XAE_TX == Dir) { XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_TTAG_OFFSET, VTagValue); } else { /* Receive direction */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RTAG_OFFSET, VTagValue); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVTagValue:returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetVTagValue gets the configured VLAN tagging value. * * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param VTagValuePtr references the location to store the result. * Format is TPID, one of the following 16 bit values, * 0x8100, 0x88a8, 0x9100, 0x9200. * Priority, 3 bits * CFI, 1 bit * VID, 12 bits * @param Dir must be either XAE_TX or XAE_RX. * * @return None. * * @note * * Ethernet VLAN frames' VLAN type/length(2B) and tag control information(2B). * Bit layout : bbbb bbbb bbbb bbbb bbb b bbbb bbbb bbbb * \ / | | \ VID (12b) / * \ / | CFI bit (1b) * TPID (16b) priority bit (3b) * *****************************************************************************/ void XAxiEthernet_GetVTagValue(XAxiEthernet *InstancePtr, u32 *VTagValuePtr, int Dir) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(VTagValuePtr != NULL); Xil_AssertVoid((Dir == XAE_TX) || (Dir == XAE_RX)); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVTagValue\n"); /* Transmit direction */ if (XAE_TX == Dir) { *VTagValuePtr = XAxiEthernet_ReadReg (InstancePtr->Config.BaseAddress, XAE_TTAG_OFFSET); } else { /* Receive direction */ *VTagValuePtr = XAxiEthernet_ReadReg( InstancePtr->Config.BaseAddress, XAE_RTAG_OFFSET); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVTagValue: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_SetVidTable sets VID table includes new VLAN ID, strip * and tag enable bits. * * The device must be stopped to use this function.

* * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Entry is the hardware storage location/index to program updated * VID value, strip, or tag value. * The value must be between 0..0xFFF. * @param Vid is updated/translated Vid value to be programmed. * @param Strip is strip enable indication for Vid. * @param Tag is tag enable indication for Vid. * @param Dir must be either XAE_TX or XAE_RX. * * @return * - XST_SUCCESS on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_NO_FEATURE if the Axi Ethernet does not enable/have * extended functionalities. * * @note * * The hardware requires the table to be 'indexed' with Entry and must be * 0x000..0xFFF. * * Bits layout is bbbb bbbb bbbb b b * VLAN ID (12b), | | * | VLAN double tag enable bit * VLAN strip enable bit * * To disable translation indexed by Entry, Set Vid = Entry. * *****************************************************************************/ int XAxiEthernet_SetVidTable(XAxiEthernet *InstancePtr, u32 Entry, u32 Vid, u8 Strip, u8 Tag, int Dir) { u32 Reg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Entry <= XAE_MAX_VLAN_TABL_ENTRY); Xil_AssertNonvoid((Dir == XAE_TX) || (Dir == XAE_RX)); Xil_AssertNonvoid(Vid <= XAE_MAX_VLAN_TABL_ENTRY); Xil_AssertNonvoid(Strip <= XAE_VLAN_TABL_STRP_FLD_LEN); Xil_AssertNonvoid(Tag <= XAE_VLAN_TABL_TAG_FLD_LEN); /* The device must be stopped before modify TX VLAN Tag value */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVidTable:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check HW capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVidTable:returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVidTable\n"); /* Program HW */ Reg = (Vid << XAE_VLAN_TABL_VID_START_OFFSET) | (Strip << XAE_VLAN_TABL_STRP_STRT_OFFSET) | Tag; /* Transmit direction */ if (XAE_TX == Dir) { XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_TX_VLAN_DATA_OFFSET + (Entry << XAE_VLAN_TABL_VID_START_OFFSET), Reg); } else { /* Receive direction */ XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_RX_VLAN_DATA_OFFSET + (Entry << XAE_VLAN_TABL_VID_START_OFFSET), Reg); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_SetVidTable: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetVidTable gets VID table content includes new VLAN ID, strip * and tag enable bits. * * The device must be stopped to use this function.

* * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param Entry is the hardware storage location/index to program * updated VID value, strip, or tag value. The value must be * between 0..0xFFF. * @param VidPtr references the location to store the result. * This function stores the Vid value indexed by Entry into * this location. * @param StripPtr references the location to store the result. * This function stores the strip enable bit value indexed * by Entry into this location. * @param TagPtr references the location to store the result. This * function stores the tag enable bit value indexed by Entry * into this location. * @param Dir must be either XAE_TX or XAE_RX. * * @return None. * * @note * * The hardware requires the table to be 'indexed' with Entry and * must be 0x000..0xFFF. * * Bits layout is bbbb bbbb bbbb b b * VLAN ID (12b), | | * | VLAN double tag enable bit * VLAN strip enable bit * *****************************************************************************/ void XAxiEthernet_GetVidTable(XAxiEthernet *InstancePtr, u32 Entry, u32 *VidPtr, u8 *StripPtr, u8 *TagPtr, int Dir) { u32 Reg; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Entry <= XAE_MAX_VLAN_TABL_ENTRY); Xil_AssertVoid(VidPtr != NULL); Xil_AssertVoid(StripPtr != NULL); Xil_AssertVoid(TagPtr != NULL); Xil_AssertVoid((Dir == XAE_TX) || (Dir == XAE_RX)); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVidTable\n"); /* Transmit direction */ if (XAE_TX == Dir) { Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_TX_VLAN_DATA_OFFSET + (Entry << XAE_VLAN_TABL_VID_START_OFFSET)); } else { /* Receive direction */ Reg = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_RX_VLAN_DATA_OFFSET + (Entry << XAE_VLAN_TABL_VID_START_OFFSET)); } *VidPtr = (Reg >> XAE_VLAN_TABL_VID_START_OFFSET); *StripPtr = (Reg >> XAE_VLAN_TABL_STRP_STRT_OFFSET) & XAE_VLAN_TABL_STRP_ENTRY_MASK; *TagPtr = Reg & XAE_VLAN_TABL_TAG_ENTRY_MASK; xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetVidTable: done\n"); } /*****************************************************************************/ /** * XAxiEthernet_AddExtMulticastGroup adds an entry to the multicast Ethernet * address table. The new entry, represents a group of MAC addresses * based on the contents of AddressPtr. AddressPtr is one member of the MAC * address set in the newly added entry. * * The device must be stopped to use this function.

* * Once an Ethernet address is programmed, the Axi Ethernet device will begin * receiving data sent from that address. The Axi Ethernet hardware does not * have a control bit to disable multicast filtering. The only way to prevent * the Axi Ethernet device from receiving messages from an Ethernet address in * the multicast table is to clear it with * XAxiEthernet_ClearExtMulticastGroup(). * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr is a pointer to the 6-byte Ethernet address to add. * * @return * - XST_SUCCESS.on successful completion. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped. * - XST_INVALID_PARAM if the input MAC address is not between * 01:00:5E:00:00:00 and 01:00:5E:7F:FF:FF per RFC1112. * * @note * * This routine consider all 2**23 possible multicast Ethernet addresses to be * 8Mx1 bit or 1M bytes memory area. All defined multicast addresses are from * 01.00.5E.00.00.00 to 01.00.5E.7F.FF.FF * The most significant 25 bit out of 48 bit are static, so they will not be * part of calculation. * * The hardware requires to 'index' with bit 22-8, 15 bits in * total. The least significant byte/8 bits are considered a group. * * This API operates at a group (256 MAC addresses) for hardware to do the * first layer address filtering. It is user's responsibility to provision * this table appropriately. * *****************************************************************************/ int XAxiEthernet_AddExtMulticastGroup(XAxiEthernet *InstancePtr, void *AddressPtr) { u8 *Aptr = (u8 *) AddressPtr; u32 Loc; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(AddressPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_AddExtMulticastGroup\n"); /* * The device must be stopped before setting the multicast table. */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_AddExtMulticastGroup:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check HW capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr) || !XAxiEthernet_IsExtMcastEnable(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_AddExtMulticastGroup:returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } /* * Verify if address is a good/valid multicast address, between * 01:00:5E:00:00:00 to 01:00:5E:7F:FF:FF per RFC1112. * This address is referenced to be index to the table. */ if ((0x01 != Aptr[0]) || (0x00 != Aptr[1]) || (0x5e != Aptr[2]) || (0x0 != (Aptr[3] & 0x80))) return (XST_INVALID_PARAM); /* * Program hardware table, index : bit 22-8. Bit 23 is 0, * when passed the if statement above. * note: if the index/bits changed, need to revisit calculation. */ Loc = Aptr[3]; Loc = Loc << 8; Loc |= Aptr[4]; /* Word aligned address access */ Loc = Loc << 2; XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_MCAST_TABLE_OFFSET + Loc, 0x01); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_AddExtMulticastGroup: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_ClearExtMulticastGroup clears input multicast Ethernet address * group from table. * * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr is a pointer to the 6-byte Ethernet address to clear. * * @return * - XST_SUCCESS on successful completion, returns XST_SUCCESS. * - XST_DEVICE_IS_STARTED if the Axi Ethernet device is not * stopped * - XST_INVALID_PARAM if input MAC address is not between * 01:00:5E:00:00:00 and 01:00:5E:7F:FF:FF per RFC1112. * * @note * * Please reference XAxiEthernet_AddExtMulticastGroup for multicast address * index and bit value calculation. * * In table, hardware requires to 'index' with bit 22-8, 15 bits in * total. The least significant byte/8 bits are considered a group. * * There is a scenario that might introduce issues: * When multicast tables are programmed initially to accept * 01:00:5E:12:34:56 and 01:00:5E:12:34:78 but later decided to clear * 01:00:5E:12:34:78. Without validating all possible combinations at the * indexed entry, multicast table might be misconfigured and drop * frames. * * When clearing a multicast address table entry, note that a whole group of * mac addresses will no longer be accepted - this because an entry in the * table represents multiple(256) mac addresses. * * The device must be stopped to use this function.

* This API operates at a group (256 MAC addresses) level for hardware to * perform the first layer address filtering. It is user's responsibility to * provision this table appropriately. * *****************************************************************************/ int XAxiEthernet_ClearExtMulticastGroup(XAxiEthernet *InstancePtr, void *AddressPtr) { u8 *Aptr = (u8 *) AddressPtr; u32 Loc; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(AddressPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearExtMulticastGroup\n"); /* * The device must be stopped before clearing the multicast table. */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearExtMulticastGroup:returning DEVICE_IS_STARTED\n"); return (XST_DEVICE_IS_STARTED); } /* Check HW capability */ if (!XAxiEthernet_IsExtFuncCap(InstancePtr) || !XAxiEthernet_IsExtMcastEnable(InstancePtr)) { xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearExtMulticastGroup:returning DEVICE_NO_FEATURE\n"); return (XST_NO_FEATURE); } /* * Verify if address is a good/valid multicast address, between * 01:00:5E:00:00:00 to 01:00:5E:7F:FF:FF per RFC1112. * This address is referenced to be index to the table. */ if ((0x01 != Aptr[0]) || (0x00 != Aptr[1]) || (0x5e != Aptr[2]) || (0x0 != (Aptr[3] & 0x80))) return (XST_INVALID_PARAM); Loc = Aptr[3]; Loc = Loc << 8; Loc |= Aptr[4]; /* Word aligned address access */ Loc = Loc << 2; XAxiEthernet_WriteReg(InstancePtr->Config.BaseAddress, XAE_MCAST_TABLE_OFFSET + Loc, 0x00); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_ClearExtMulticastGroup: returning SUCCESS\n"); return (XST_SUCCESS); } /*****************************************************************************/ /** * XAxiEthernet_GetExtMulticastGroup returns whether the given Ethernet address * group is stored in the table. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * @param AddressPtr is a pointer to the 6-byte Ethernet address. * * @return * - TRUE if it is an acceptable multicast MAC address * and the group is present in the table. * - FALSE if it is not a valid multicast MAC address * or the group was not found in the table. * * @note * * In the table, hardware requires to 'index' with bit 22-8, 15 bits in * total. The least significant byte/8 bits are considered a group. * This API operates at a group (256 MAC addresses) level. * *****************************************************************************/ int XAxiEthernet_GetExtMulticastGroup(XAxiEthernet *InstancePtr, void *AddressPtr) { u8 *Aptr = (u8 *) AddressPtr; u32 Loc; u8 Bit; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(AddressPtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetExtMulticastGroup\n"); /* * Verify if address is a good/valid multicast address, between * 01:00:5E:00:00:00 to 01:00:5E:7F:FF:FF per RFC1112. * This address is referenced to be index to the table. */ if ((0x01 != Aptr[0]) || (0x00 != Aptr[1]) || (0x5e != Aptr[2]) || (0x0 != (Aptr[3] & 0x80))) return (FALSE); Loc = Aptr[3]; Loc = Loc << 8; Loc |= Aptr[4]; /* * Word aligned address access */ Loc = Loc << 2; Bit = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_MCAST_TABLE_OFFSET + Loc); if (Bit) { return (TRUE); } else { return (FALSE); } xdbg_printf(XDBG_DEBUG_GENERAL, "XAxiEthernet_GetExtMulticastGroup:done\n"); } /*****************************************************************************/ /** * XAxiEthernet_DumpExtMulticastGroup dumps ALL provisioned acceptable multicast * MAC in the Axi Ethernet device's multicast table. * * @param InstancePtr is a pointer to the Axi Ethernet instance to be * worked on. * * @return None. * * @note * * Hardware requires to 'index' with bit 22-8, 15 bits in * total. The least significant byte/8 bits are considered a set. * * This API operates at a set (256 MAC addresses) level. * *****************************************************************************/ void XAxiEthernet_DumpExtMulticastGroup(XAxiEthernet *InstancePtr) { u32 Loc; u32 Index; u8 Bit; char MacAddr[6]; Xil_AssertVoid(InstancePtr != NULL); /* * Pre-populated these bytes, we know and guarantee these if * provisioned through the XAxiEthernet_AddExtMulticastGroup(). */ MacAddr[0] = 0x01; MacAddr[1] = 0x00; MacAddr[2] = 0x5E; for (Index = 0; Index < (1 << 15); Index++) { MacAddr[3] = Index << 16; MacAddr[4] = Index << 8; MacAddr[5] = 0; Loc = MacAddr[3]; Loc |= MacAddr[4] << 8; /* Word aligned address access */ Loc = Loc << 2; Bit = XAxiEthernet_ReadReg(InstancePtr->Config.BaseAddress, XAE_MCAST_TABLE_OFFSET + Loc); if (Bit) { xdbg_printf(XDBG_DEBUG_GENERAL, "%x:%x:%x:%x:%x:%x\n", MacAddr[5], MacAddr[4], MacAddr[3], MacAddr[2], MacAddr[1], MacAddr[0]); } } }