/****************************************************************************** * * Copyright (C) 2004 - 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 xemaclite.c * * Functions in this file are the minimum required functions for the EmacLite * driver. See xemaclite.h for a detailed description of the driver. * *
* MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- -------------------------------------------------------- * 1.01a ecm 01/31/04 First release * 1.11a mta 03/21/07 Updated to new coding style * 1.11a ecm 05/18/07 Updated the TxBufferAvailable routine to look at both * the active and busy bits * 1.13a sv 02/1/08 Updated the TxBufferAvailable routine to return * busy status properly * 2.00a ktn 02/16/09 Added support for MDIO * 2.01a ktn 07/20/09 Modified XEmacLite_Send function to use Ping buffers * Interrupt enable bit since this alone is used to enable * the interrupts for both Ping and Pong Buffers. * 3.00a ktn 10/22/09 Updated driver to use the HAL APIs/macros. * The macros have been renamed to remove _m from the name. * 3.01a ktn 07/08/10 The macro XEmacLite_GetReceiveDataLength is changed to * a static function. * Updated the XEmacLite_GetReceiveDataLength and * XEmacLite_Recv functions to support little endian * MicroBlaze. * 3.02a sdm 07/22/11 Removed redundant code in XEmacLite_Recv functions for * CR617290 * 3.04a srt 04/13/13 Removed warnings (CR 705000). * *******************************************************************************/ /***************************** Include Files *********************************/ #include "xil_io.h" #include "xenv.h" #include "xemaclite.h" #include "xemaclite_i.h" /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Function Prototypes ******************************/ static u16 XEmacLite_GetReceiveDataLength(u32 BaseAddress); /************************** Variable Definitions *****************************/ /*****************************************************************************/ /** * * Initialize a specific XEmacLite instance/driver. The initialization entails: * - Initialize fields of the XEmacLite instance structure. * * The driver defaults to polled mode operation. * * @param InstancePtr is a pointer to the XEmacLite instance. * @param EmacLiteConfigPtr points to the XEmacLite device configuration * structure. * @param EffectiveAddr is the device base address in the virtual memory * address space. If the address translation is not used then the * physical address is passed. * Unexpected errors may occur if the address mapping is changed * after this function is invoked. * * @return * - XST_SUCCESS if initialization was successful. * * @note The initialization of the PHY device is not done in this * function. The user needs to use XEmacLite_PhyRead and * XEmacLite_PhyWrite functions to access the PHY device. * ******************************************************************************/ int XEmacLite_CfgInitialize(XEmacLite *InstancePtr, XEmacLite_Config *EmacLiteConfigPtr, u32 EffectiveAddr) { /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(EmacLiteConfigPtr != NULL); /* * Zero the provided instance memory. */ memset(InstancePtr, 0, sizeof(XEmacLite)); /* * Set some default values for instance data, don't indicate the device * is ready to use until everything has been initialized successfully. */ InstancePtr->EmacLiteConfig.BaseAddress = EffectiveAddr; InstancePtr->EmacLiteConfig.DeviceId = EmacLiteConfigPtr->DeviceId; InstancePtr->EmacLiteConfig.TxPingPong = EmacLiteConfigPtr->TxPingPong; InstancePtr->EmacLiteConfig.RxPingPong = EmacLiteConfigPtr->RxPingPong; InstancePtr->EmacLiteConfig.MdioInclude = EmacLiteConfigPtr->MdioInclude; InstancePtr->EmacLiteConfig.Loopback = EmacLiteConfigPtr->Loopback; InstancePtr->NextTxBufferToUse = 0x0; InstancePtr->NextRxBufferToUse = 0x0; InstancePtr->RecvHandler = (XEmacLite_Handler) StubHandler; InstancePtr->SendHandler = (XEmacLite_Handler) StubHandler; /* * Clear the TX CSR's in case this is a restart. */ XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_TSR_OFFSET, 0); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0); /* * Since there were no failures, indicate the device is ready to use. */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return XST_SUCCESS; } /*****************************************************************************/ /** * * Send an Ethernet frame. The ByteCount is the total frame size, including * header. * * @param InstancePtr is a pointer to the XEmacLite instance. * @param FramePtr is a pointer to frame. For optimal performance, a * 32-bit aligned buffer should be used but it is not required, the * function will align the data if necessary. * @param ByteCount is the size, in bytes, of the frame * * @return * - XST_SUCCESS if data was transmitted. * - XST_FAILURE if buffer(s) was (were) full and no valid data was * transmitted. * * @note * * This function call is not blocking in nature, i.e. it will not wait until the * frame is transmitted. * ******************************************************************************/ int XEmacLite_Send(XEmacLite *InstancePtr, u8 *FramePtr, unsigned ByteCount) { u32 Register; u32 BaseAddress; u32 EmacBaseAddress; u32 IntrEnableStatus; /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); /* * Determine the expected TX buffer address. */ BaseAddress = XEmacLite_NextTransmitAddr(InstancePtr); EmacBaseAddress = InstancePtr->EmacLiteConfig.BaseAddress; /* * Check the Length if it is too large, truncate it. * The maximum Tx packet size is * Ethernet header (14 Bytes) + Maximum MTU (1500 bytes). */ if (ByteCount > XEL_MAX_TX_FRAME_SIZE) { ByteCount = XEL_MAX_TX_FRAME_SIZE; } /* * Determine if the expected buffer address is empty. */ Register = XEmacLite_GetTxStatus(BaseAddress); /* * If the expected buffer is available, fill it with the provided data * Align if necessary. */ if ((Register & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { /* * Switch to next buffer if configured. */ if (InstancePtr->EmacLiteConfig.TxPingPong != 0) { InstancePtr->NextTxBufferToUse ^= XEL_BUFFER_OFFSET; } /* * Write the frame to the buffer. */ XEmacLite_AlignedWrite(FramePtr, (u32 *) BaseAddress, ByteCount); /* * The frame is in the buffer, now send it. */ XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET, (ByteCount & (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); /* * Update the Tx Status Register to indicate that there is a * frame to send. * If the interrupt enable bit of Ping buffer(since this * controls both the buffers) is enabled then set the * XEL_TSR_XMIT_ACTIVE_MASK flag which is used by the interrupt * handler to call the callback function provided by the user * to indicate that the frame has been transmitted. */ Register = XEmacLite_GetTxStatus(BaseAddress); Register |= XEL_TSR_XMIT_BUSY_MASK; IntrEnableStatus = XEmacLite_GetTxStatus(EmacBaseAddress); if ((IntrEnableStatus & XEL_TSR_XMIT_IE_MASK) != 0) { Register |= XEL_TSR_XMIT_ACTIVE_MASK; } XEmacLite_SetTxStatus(BaseAddress, Register); return XST_SUCCESS; } /* * If the expected buffer was full, try the other buffer if configured. */ if (InstancePtr->EmacLiteConfig.TxPingPong != 0) { BaseAddress ^= XEL_BUFFER_OFFSET; /* * Determine if the expected buffer address is empty. */ Register = XEmacLite_GetTxStatus(BaseAddress); /* * If the next buffer is available, fill it with the provided * data. */ if ((Register & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { /* * Write the frame to the buffer. */ XEmacLite_AlignedWrite(FramePtr, (u32 *) BaseAddress, ByteCount); /* * The frame is in the buffer, now send it. */ XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET, (ByteCount & (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO))); /* * Update the Tx Status Register to indicate that there * is a frame to send. * If the interrupt enable bit of Ping buffer(since this * controls both the buffers) is enabled then set the * XEL_TSR_XMIT_ACTIVE_MASK flag which is used by the * interrupt handler to call the callback function * provided by the user to indicate that the frame has * been transmitted. */ Register = XEmacLite_GetTxStatus(BaseAddress); Register |= XEL_TSR_XMIT_BUSY_MASK; IntrEnableStatus = XEmacLite_GetTxStatus(EmacBaseAddress); if ((IntrEnableStatus & XEL_TSR_XMIT_IE_MASK) != 0) { Register |= XEL_TSR_XMIT_ACTIVE_MASK; } XEmacLite_SetTxStatus(BaseAddress, Register); /* * Do not switch to next buffer, there is a sync problem * and the expected buffer should not change. */ return XST_SUCCESS; } } /* * Buffer(s) was(were) full, return failure to allow for polling usage. */ return XST_FAILURE; } /*****************************************************************************/ /** * * Receive a frame. Intended to be called from the interrupt context or * with a wrapper which waits for the receive frame to be available. * * @param InstancePtr is a pointer to the XEmacLite instance. * @param FramePtr is a pointer to a buffer where the frame will * be stored. The buffer must be at least XEL_MAX_FRAME_SIZE bytes. * For optimal performance, a 32-bit aligned buffer should be used * but it is not required, the function will align the data if * necessary. * * @return * * The type/length field of the frame received. When the type/length field * contains the type, XEL_MAX_FRAME_SIZE bytes will be copied out of the * buffer and it is up to the higher layers to sort out the frame. * Function returns 0 if there is no data waiting in the receive buffer or * the pong buffer if configured. * * @note * * This function call is not blocking in nature, i.e. it will not wait until * a frame arrives. * ******************************************************************************/ u16 XEmacLite_Recv(XEmacLite *InstancePtr, u8 *FramePtr) { u16 LengthType; u16 Length; u32 Register; u32 BaseAddress; /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); /* * Determine the expected buffer address. */ BaseAddress = XEmacLite_NextReceiveAddr(InstancePtr); /* * Verify which buffer has valid data. */ Register = XEmacLite_GetRxStatus(BaseAddress); if ((Register & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { /* * The driver is in sync, update the next expected buffer if * configured. */ if (InstancePtr->EmacLiteConfig.RxPingPong != 0) { InstancePtr->NextRxBufferToUse ^= XEL_BUFFER_OFFSET; } } else { /* * The instance is out of sync, try other buffer if other * buffer is configured, return 0 otherwise. If the instance is * out of sync, do not update the 'NextRxBufferToUse' since it * will correct on subsequent calls. */ if (InstancePtr->EmacLiteConfig.RxPingPong != 0) { BaseAddress ^= XEL_BUFFER_OFFSET; } else { return 0; /* No data was available */ } /* * Verify that buffer has valid data. */ Register = XEmacLite_GetRxStatus(BaseAddress); if ((Register & XEL_RSR_RECV_DONE_MASK) != XEL_RSR_RECV_DONE_MASK) { return 0; /* No data was available */ } } /* * Get the length of the frame that arrived. */ LengthType = XEmacLite_GetReceiveDataLength(BaseAddress); /* * Check if length is valid. */ if (LengthType > XEL_MAX_FRAME_SIZE) { if (LengthType == XEL_ETHER_PROTO_TYPE_IP) { /* * The packet is a an IP Packet. */ #ifdef __LITTLE_ENDIAN__ Length = (XEmacLite_ReadReg((BaseAddress), XEL_HEADER_IP_LENGTH_OFFSET + XEL_RXBUFF_OFFSET) & (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO)); Length = (u16) (((Length & 0xFF00) >> 8) | ((Length & 0x00FF) << 8)); #else Length = ((XEmacLite_ReadReg((BaseAddress), XEL_HEADER_IP_LENGTH_OFFSET + XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) & (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO)); #endif Length += XEL_HEADER_SIZE + XEL_FCS_SIZE; } else if (LengthType == XEL_ETHER_PROTO_TYPE_ARP) { /* * The packet is an ARP Packet. */ Length = XEL_ARP_PACKET_SIZE + XEL_HEADER_SIZE + XEL_FCS_SIZE; } else { /* * Field contains type other than IP or ARP, use max * frame size and let user parse it. */ Length = XEL_MAX_FRAME_SIZE; } } else { /* * Use the length in the frame, plus the header and trailer. */ Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE; } /* * Read from the EmacLite. */ XEmacLite_AlignedRead(((u32 *) (BaseAddress + XEL_RXBUFF_OFFSET)), FramePtr, Length); /* * Acknowledge the frame. */ Register = XEmacLite_GetRxStatus(BaseAddress); Register &= ~XEL_RSR_RECV_DONE_MASK; XEmacLite_SetRxStatus(BaseAddress, Register); return Length; } /*****************************************************************************/ /** * * Set the MAC address for this device. The address is a 48-bit value. * * @param InstancePtr is a pointer to the XEmacLite instance. * @param AddressPtr is a pointer to a 6-byte MAC address. * the format of the MAC address is major octet to minor octet * * @return None. * * @note * * - TX must be idle and RX should be idle for deterministic results. * It is recommended that this function should be called after the * initialization and before transmission of any packets from the device. * - Function will not return if hardware is absent or not functioning * properly. * - The MAC address can be programmed using any of the two transmit * buffers (if configured). * ******************************************************************************/ void XEmacLite_SetMacAddress(XEmacLite *InstancePtr, u8 *AddressPtr) { u32 BaseAddress; /* * Verify that each of the inputs are valid. */ Xil_AssertVoid(InstancePtr != NULL); /* * Determine the expected TX buffer address. */ BaseAddress = XEmacLite_NextTransmitAddr(InstancePtr); /* * Copy the MAC address to the Transmit buffer. */ XEmacLite_AlignedWrite(AddressPtr, (u32 *) BaseAddress, XEL_MAC_ADDR_SIZE); /* * Set the length. */ XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET, XEL_MAC_ADDR_SIZE); /* * Update the MAC address in the EmacLite. */ XEmacLite_SetTxStatus(BaseAddress, XEL_TSR_PROG_MAC_ADDR); /* * Wait for EmacLite to finish with the MAC address update. */ while ((XEmacLite_GetTxStatus(BaseAddress) & XEL_TSR_PROG_MAC_ADDR) != 0); } /******************************************************************************/ /** * * This is a stub for the send and receive callbacks. The stub * is here in case the upper layers forget to set the handlers. * * @param CallBackRef is a pointer to the upper layer callback reference. * * @return None. * * @note None. * ******************************************************************************/ void StubHandler(void *CallBackRef) { (void)(CallBackRef); Xil_AssertVoidAlways(); } /****************************************************************************/ /** * * Determine if there is a transmit buffer available. * * @param InstancePtr is the pointer to the instance of the driver to * be worked on. * * @return * - TRUE if there is a TX buffer available for data to be written * - FALSE if Tx Buffer is not available. * * @note None. * *****************************************************************************/ int XEmacLite_TxBufferAvailable(XEmacLite *InstancePtr) { u32 Register; int TxPingBusy; int TxPongBusy; /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); /* * Read the Tx Status and determine if the buffer is available. */ Register = XEmacLite_GetTxStatus(InstancePtr->EmacLiteConfig. BaseAddress); TxPingBusy = (Register & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)); /* * Read the Tx Status of the second buffer register and determine if the * buffer is available. */ if (InstancePtr->EmacLiteConfig.TxPingPong != 0) { Register = XEmacLite_GetTxStatus(InstancePtr->EmacLiteConfig. BaseAddress + XEL_BUFFER_OFFSET); TxPongBusy = (Register & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)); return (!(TxPingBusy && TxPongBusy)); } return (!TxPingBusy); } /****************************************************************************/ /** * * Flush the Receive buffers. All data will be lost. * * @param InstancePtr is the pointer to the instance of the driver to * be worked on. * * @return None. * * @note None. * *****************************************************************************/ void XEmacLite_FlushReceive(XEmacLite *InstancePtr) { u32 Register; /* * Verify that each of the inputs are valid. */ Xil_AssertVoid(InstancePtr != NULL); /* * Read the current buffer register and determine if the buffer is * available. */ Register = XEmacLite_GetRxStatus(InstancePtr->EmacLiteConfig. BaseAddress); /* * Preserve the IE bit. */ Register &= XEL_RSR_RECV_IE_MASK; /* * Write out the value to flush the RX buffer. */ XEmacLite_SetRxStatus(InstancePtr->EmacLiteConfig.BaseAddress, Register); /* * If the pong buffer is available, flush it also. */ if (InstancePtr->EmacLiteConfig.RxPingPong != 0) { /* * Read the current buffer register and determine if the buffer * is available. */ Register = XEmacLite_GetRxStatus(InstancePtr->EmacLiteConfig. BaseAddress + XEL_BUFFER_OFFSET); /* * Preserve the IE bit. */ Register &= XEL_RSR_RECV_IE_MASK; /* * Write out the value to flush the RX buffer. */ XEmacLite_SetRxStatus(InstancePtr->EmacLiteConfig.BaseAddress + XEL_BUFFER_OFFSET, Register); } } /******************************************************************************/ /** * * Read the specified PHY register. * * @param InstancePtr is the pointer to the instance of the driver. * @param PhyAddress is the address of the PHY device. The valid range is * is from 0 to 31. * @param RegNum is the register number in the PHY device which * is to be read. The valid range is is from 0 to 31. * @param PhyDataPtr is a pointer to the data in which the data read * from the PHY device is returned. * * @return * - XST_SUCCESS if the data is read from the PHY. * - XST_DEVICE_BUSY if MDIO is busy. * * @note This function waits for the completion of MDIO data transfer. * *****************************************************************************/ int XEmacLite_PhyRead(XEmacLite *InstancePtr, u32 PhyAddress, u32 RegNum, u16 *PhyDataPtr) { u32 PhyAddrReg; u32 MdioCtrlReg; /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->EmacLiteConfig.MdioInclude == TRUE); Xil_AssertNonvoid(PhyAddress <= 31); Xil_AssertNonvoid(RegNum <= 31); Xil_AssertNonvoid(PhyDataPtr != NULL); /* * Verify MDIO master status. */ if (XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET) & XEL_MDIOCNTR_STATUS_MASK) { return XST_DEVICE_BUSY; } PhyAddrReg = ((((PhyAddress << XEL_MDIO_ADDRESS_SHIFT) & XEL_MDIO_ADDRESS_MASK) | RegNum) | XEL_MDIO_OP_MASK); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOADDR_OFFSET, PhyAddrReg); /* * Enable MDIO and start the transfer. */ MdioCtrlReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET, MdioCtrlReg | XEL_MDIOCNTR_STATUS_MASK | XEL_MDIOCNTR_ENABLE_MASK); /* * Wait till the completion of transfer. */ while ((XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET) & XEL_MDIOCNTR_STATUS_MASK)); /* * Read data from MDIO read data register. */ *PhyDataPtr = (u16)XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIORD_OFFSET); /* * Disable the MDIO. */ MdioCtrlReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET, MdioCtrlReg & ~XEL_MDIOCNTR_ENABLE_MASK); return XST_SUCCESS; } /******************************************************************************/ /** * * Write the given data to the specified register in the PHY device. * * @param InstancePtr is the pointer to the instance of the driver. * @param PhyAddress is the address of the PHY device. The valid range is * is from 0 to 31. * @param RegNum is the register number in the PHY device which * is to be written. The valid range is is from 0 to 31. * @param PhyData is the data to be written to the specified register in * the PHY device. * * @return * - XST_SUCCESS if the data is written to the PHY. * - XST_DEVICE_BUSY if MDIO is busy. * * @note This function waits for the completion of MDIO data transfer. * *******************************************************************************/ int XEmacLite_PhyWrite(XEmacLite *InstancePtr, u32 PhyAddress, u32 RegNum, u16 PhyData) { u32 PhyAddrReg; u32 MdioCtrlReg; /* * Verify that each of the inputs are valid. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->EmacLiteConfig.MdioInclude == TRUE); Xil_AssertNonvoid(PhyAddress <= 31); Xil_AssertNonvoid(RegNum <= 31); /* * Verify MDIO master status. */ if (XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET) & XEL_MDIOCNTR_STATUS_MASK) { return XST_DEVICE_BUSY; } PhyAddrReg = ((((PhyAddress << XEL_MDIO_ADDRESS_SHIFT) & XEL_MDIO_ADDRESS_MASK) | RegNum) & ~XEL_MDIO_OP_MASK); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOADDR_OFFSET, PhyAddrReg); /* * Write data to MDIO write data register. */ XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOWR_OFFSET, (u32)PhyData); /* * Enable MDIO and start the transfer. */ MdioCtrlReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET, MdioCtrlReg | XEL_MDIOCNTR_STATUS_MASK | XEL_MDIOCNTR_ENABLE_MASK); /* * Wait till the completion of transfer. */ while ((XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET) & XEL_MDIOCNTR_STATUS_MASK)); /* * Disable the MDIO. */ MdioCtrlReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_MDIOCNTR_OFFSET, MdioCtrlReg & ~XEL_MDIOCNTR_ENABLE_MASK); return XST_SUCCESS; } /****************************************************************************/ /** * * Enable Internal loop back functionality. * * @param InstancePtr is the pointer to the instance of the driver. * * @return None. * * @note None. * *****************************************************************************/ void XEmacLite_EnableLoopBack(XEmacLite *InstancePtr) { u32 TsrReg; /* * Verify that each of the inputs are valid. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->EmacLiteConfig.Loopback == TRUE); TsrReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_TSR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_TSR_OFFSET, TsrReg | XEL_TSR_LOOPBACK_MASK); } /****************************************************************************/ /** * * Disable Internal loop back functionality. * * @param InstancePtr is the pointer to the instance of the driver. * * @return None. * * @note None. * *****************************************************************************/ void XEmacLite_DisableLoopBack(XEmacLite *InstancePtr) { u32 TsrReg; /* * Verify that each of the inputs are valid. */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->EmacLiteConfig.Loopback == TRUE); TsrReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_TSR_OFFSET); XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress, XEL_TSR_OFFSET, TsrReg & (~XEL_TSR_LOOPBACK_MASK)); } /*****************************************************************************/ /** * * Return the length of the data in the Receive Buffer. * * @param BaseAddress contains the base address of the device. * * @return The type/length field of the frame received. * * @note None. * ******************************************************************************/ static u16 XEmacLite_GetReceiveDataLength(u32 BaseAddress) { u16 Length; #ifdef __LITTLE_ENDIAN__ Length = (XEmacLite_ReadReg((BaseAddress), XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET) & (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO)); Length = (u16) (((Length & 0xFF00) >> 8) | ((Length & 0x00FF) << 8)); #else Length = ((XEmacLite_ReadReg((BaseAddress), XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) & (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO)); #endif return Length; }