
Upgrade and make misra c compliant Signed-off-by: Punnaiah Choudary Kalluri <punnaia@xilinx.com>
1111 lines
38 KiB
C
Executable file
1111 lines
38 KiB
C
Executable file
/* $Id: xemacps_control.c,v 1.1.2.1 2011/01/20 03:39:02 sadanan Exp $ */
|
|
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2009 - 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 xemacps_control.c
|
|
*
|
|
* Functions in this file implement general purpose command and control related
|
|
* functionality. See xemacps.h for a detailed description of the driver.
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -------- -------------------------------------------------------
|
|
* 1.00a wsy 01/10/10 First release
|
|
* 1.02a asa 11/05/12 Added a new API for deleting an entry from the HASH
|
|
* register. Added a new API for setting the BURST length
|
|
* in DMACR register.
|
|
* 2.1 srt 07/15/14 Add support for Zynq Ultrascale Mp architecture.
|
|
* </pre>
|
|
*****************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "xemacps.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set the MAC address for this driver/device. The address is a 48-bit value.
|
|
* The device must be stopped before calling this function.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param AddressPtr is a pointer to a 6-byte MAC address.
|
|
* @param Index is a index to which MAC (1-4) address.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the MAC address was set successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
*
|
|
*****************************************************************************/
|
|
LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
|
|
{
|
|
u32 MacAddr;
|
|
u8 *Aptr = (u8 *)(void *)AddressPtr;
|
|
u8 IndexLoc = Index;
|
|
LONG Status;
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(Aptr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
}
|
|
else{
|
|
/* Index ranges 1 to 4, for offset calculation is 0 to 3. */
|
|
IndexLoc--;
|
|
|
|
/* Set the MAC bits [31:0] in BOT */
|
|
MacAddr = *(Aptr);
|
|
MacAddr |= ((u32)(*(Aptr+1)) << 8U);
|
|
MacAddr |= ((u32)(*(Aptr+2)) << 16U);
|
|
MacAddr |= ((u32)(*(Aptr+3)) << 24U);
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
|
|
|
|
/* There are reserved bits in TOP so don't affect them */
|
|
MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
|
|
|
|
MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK);
|
|
|
|
/* Set MAC bits [47:32] in TOP */
|
|
MacAddr |= (u32)(*(Aptr+4));
|
|
MacAddr |= (u32)(*(Aptr+5)) << 8U;
|
|
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
|
|
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the MAC address for this driver/device.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param AddressPtr is an output parameter, and is a pointer to a buffer into
|
|
* which the current MAC address will be copied.
|
|
* @param Index is a index to which MAC (1-4) address.
|
|
*
|
|
*****************************************************************************/
|
|
void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
|
|
{
|
|
u32 MacAddr;
|
|
u8 *Aptr = (u8 *)(void *)AddressPtr;
|
|
u8 IndexLoc = Index;
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(Aptr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
|
|
|
|
/* Index ranges 1 to 4, for offset calculation is 0 to 3. */
|
|
IndexLoc--;
|
|
|
|
MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)));
|
|
*Aptr = (u8) MacAddr;
|
|
*(Aptr+1) = (u8) (MacAddr >> 8U);
|
|
*(Aptr+2) = (u8) (MacAddr >> 16U);
|
|
*(Aptr+3) = (u8) (MacAddr >> 24U);
|
|
|
|
/* Read MAC bits [47:32] in TOP */
|
|
MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
|
|
*(Aptr+4) = (u8) MacAddr;
|
|
*(Aptr+5) = (u8) (MacAddr >> 8U);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set 48-bit MAC addresses in hash table.
|
|
* The device must be stopped before calling this function.
|
|
*
|
|
* The hash address register is 64 bits long and takes up two locations in
|
|
* the memory map. The least significant bits are stored in hash register
|
|
* bottom and the most significant bits in hash register top.
|
|
*
|
|
* The unicast hash enable and the multicast hash enable bits in the network
|
|
* configuration register enable the reception of hash matched frames. The
|
|
* destination address is reduced to a 6 bit index into the 64 bit hash
|
|
* register using the following hash function. The hash function is an XOR
|
|
* of every sixth bit of the destination address.
|
|
*
|
|
* <pre>
|
|
* hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
|
|
* hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
|
|
* hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
|
|
* hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
|
|
* hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
|
|
* hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
|
|
* </pre>
|
|
*
|
|
* da[0] represents the least significant bit of the first byte received,
|
|
* that is, the multicast/unicast indicator, and da[47] represents the most
|
|
* significant bit of the last byte received.
|
|
*
|
|
* If the hash index points to a bit that is set in the hash register then
|
|
* the frame will be matched according to whether the frame is multicast
|
|
* or unicast.
|
|
*
|
|
* A multicast match will be signaled if the multicast hash enable bit is
|
|
* set, da[0] is logic 1 and the hash index points to a bit set in the hash
|
|
* register.
|
|
*
|
|
* A unicast match will be signaled if the unicast hash enable bit is set,
|
|
* da[0] is logic 0 and the hash index points to a bit set in the hash
|
|
* register.
|
|
*
|
|
* To receive all multicast frames, the hash register should be set with
|
|
* all ones and the multicast hash enable bit should be set in the network
|
|
* configuration register.
|
|
*
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param AddressPtr is a pointer to a 6-byte MAC address.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the HASH MAC address was set successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
* - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
|
|
* requirement after calculation
|
|
*
|
|
* @note
|
|
* Having Aptr be unsigned type prevents the following operations from sign
|
|
* extending.
|
|
*****************************************************************************/
|
|
LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
|
|
{
|
|
u32 HashAddr;
|
|
u8 *Aptr = (u8 *)(void *)AddressPtr;
|
|
u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
|
|
u32 Result;
|
|
LONG Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(AddressPtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
} else {
|
|
Temp1 = (*(Aptr+0)) & 0x3FU;
|
|
Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
|
|
|
|
Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U);
|
|
Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
|
|
Temp5 = (*(Aptr+3)) & 0x3FU;
|
|
Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
|
|
Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
|
|
Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
|
|
|
|
Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
|
|
(u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
|
|
|
|
if (Result >= (u32)XEMACPS_MAX_HASH_BITS) {
|
|
Status = (LONG)(XST_INVALID_PARAM);
|
|
} else {
|
|
|
|
if (Result < (u32)32) {
|
|
HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET);
|
|
HashAddr |= (u32)(0x00000001U << Result);
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET, HashAddr);
|
|
} else {
|
|
HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET);
|
|
HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32));
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET, HashAddr);
|
|
}
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Delete 48-bit MAC addresses in hash table.
|
|
* The device must be stopped before calling this function.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param AddressPtr is a pointer to a 6-byte MAC address.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the HASH MAC address was deleted successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
* - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
|
|
* requirement after calculation
|
|
*
|
|
* @note
|
|
* Having Aptr be unsigned type prevents the following operations from sign
|
|
* extending.
|
|
*****************************************************************************/
|
|
LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
|
|
{
|
|
u32 HashAddr;
|
|
u8 *Aptr = (u8 *)(void *)AddressPtr;
|
|
u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
|
|
u32 Result;
|
|
LONG Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(Aptr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
} else {
|
|
Temp1 = (*(Aptr+0)) & 0x3FU;
|
|
Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
|
|
Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U);
|
|
Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
|
|
Temp5 = (*(Aptr+3)) & 0x3FU;
|
|
Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
|
|
Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
|
|
Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
|
|
|
|
Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
|
|
(u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
|
|
|
|
if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) {
|
|
Status = (LONG)(XST_INVALID_PARAM);
|
|
} else {
|
|
if (Result < (u32)32) {
|
|
HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET);
|
|
HashAddr &= (u32)(~(0x00000001U << Result));
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET, HashAddr);
|
|
} else {
|
|
HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET);
|
|
HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32)));
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET, HashAddr);
|
|
}
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
/*****************************************************************************/
|
|
/**
|
|
* Clear the Hash registers for the mac address pointed by AddressPtr.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
*
|
|
*****************************************************************************/
|
|
void XEmacPs_ClearHash(XEmacPs *InstancePtr)
|
|
{
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET, 0x0U);
|
|
|
|
/* write bits [63:32] in TOP */
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET, 0x0U);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get the Hash address for this driver/device.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param AddressPtr is an output parameter, and is a pointer to a buffer into
|
|
* which the current HASH MAC address will be copied.
|
|
*
|
|
*****************************************************************************/
|
|
void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
|
|
{
|
|
u32 *Aptr = (u32 *)(void *)AddressPtr;
|
|
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(AddressPtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
*(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHL_OFFSET);
|
|
|
|
/* Read Hash bits [63:32] in TOP */
|
|
*(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_HASHH_OFFSET);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set the Type ID match for this driver/device. The register is a 32-bit
|
|
* value. The device must be stopped before calling this function.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param Id_Check is type ID to be configured.
|
|
* @param Index is a index to which Type ID (1-4).
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the MAC address was set successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
*
|
|
*****************************************************************************/
|
|
LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
|
|
{
|
|
u8 IndexLoc = Index;
|
|
LONG Status;
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U));
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
} else {
|
|
|
|
/* Index ranges 1 to 4, for offset calculation is 0 to 3. */
|
|
IndexLoc--;
|
|
|
|
/* Set the ID bits in MATCHx register */
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check);
|
|
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set options for the driver/device. The driver should be stopped with
|
|
* XEmacPs_Stop() before changing options.
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param Options are the options to set. Multiple options can be set by OR'ing
|
|
* XTE_*_OPTIONS constants together. Options not specified are not
|
|
* affected.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the options were set successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
*
|
|
* @note
|
|
* See xemacps.h for a description of the available options.
|
|
*
|
|
*****************************************************************************/
|
|
LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
|
|
{
|
|
u32 Reg; /* Generic register contents */
|
|
u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
|
|
u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
|
|
LONG Status;
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
} else {
|
|
|
|
/* Many of these options will change the NET_CONFIG registers.
|
|
* To reduce the amount of IO to the device, group these options here
|
|
* and change them all at once.
|
|
*/
|
|
|
|
/* Grab current register contents */
|
|
RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET);
|
|
RegNewNetCfg = RegNetCfg;
|
|
|
|
/*
|
|
* It is configured to max 1536.
|
|
*/
|
|
if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
|
|
}
|
|
|
|
/* Turn on VLAN packet only, only VLAN tagged will be accepted */
|
|
if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
|
|
}
|
|
|
|
/* Turn on FCS stripping on receive packets */
|
|
if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
|
|
}
|
|
|
|
/* Turn on length/type field checking on receive packets */
|
|
if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK;
|
|
}
|
|
|
|
/* Turn on flow control */
|
|
if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
|
|
}
|
|
|
|
/* Turn on promiscuous frame filtering (all frames are received) */
|
|
if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
|
|
}
|
|
|
|
/* Allow broadcast address reception */
|
|
if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK);
|
|
}
|
|
|
|
/* Allow multicast address filtering */
|
|
if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
|
|
}
|
|
|
|
/* enable RX checksum offload */
|
|
if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
|
|
}
|
|
|
|
/* Officially change the NET_CONFIG registers if it needs to be
|
|
* modified.
|
|
*/
|
|
if (RegNetCfg != RegNewNetCfg) {
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
|
|
}
|
|
|
|
/* Enable TX checksum offload */
|
|
if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_DMACR_OFFSET);
|
|
Reg |= XEMACPS_DMACR_TCPCKSUM_MASK;
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_DMACR_OFFSET, Reg);
|
|
}
|
|
|
|
/* Enable transmitter */
|
|
if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET);
|
|
Reg |= XEMACPS_NWCTRL_TXEN_MASK;
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET, Reg);
|
|
}
|
|
|
|
/* Enable receiver */
|
|
if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET);
|
|
Reg |= XEMACPS_NWCTRL_RXEN_MASK;
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_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.
|
|
*/
|
|
|
|
/* Set options word to its new value */
|
|
InstancePtr->Options |= Options;
|
|
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Clear options for the driver/device
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param Options are the options to clear. Multiple options can be cleared by
|
|
* OR'ing XEMACPS_*_OPTIONS constants together. Options not specified
|
|
* are not affected.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the options were set successfully
|
|
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
|
|
*
|
|
* @note
|
|
* See xemacps.h for a description of the available options.
|
|
*
|
|
*****************************************************************************/
|
|
LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
|
|
{
|
|
u32 Reg; /* Generic */
|
|
u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */
|
|
u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */
|
|
LONG Status;
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
/* Be sure device has been stopped */
|
|
if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STARTED);
|
|
} else {
|
|
|
|
/* Many of these options will change the NET_CONFIG registers.
|
|
* To reduce the amount of IO to the device, group these options here
|
|
* and change them all at once.
|
|
*/
|
|
|
|
/* Grab current register contents */
|
|
RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET);
|
|
RegNewNetCfg = RegNetCfg;
|
|
|
|
/* There is only RX configuration!?
|
|
* It is configured in two different length, upto 1536 and 10240 bytes
|
|
*/
|
|
if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK);
|
|
}
|
|
|
|
/* Turn off VLAN packet only */
|
|
if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK);
|
|
}
|
|
|
|
/* Turn off FCS stripping on receive packets */
|
|
if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK);
|
|
}
|
|
|
|
/* Turn off length/type field checking on receive packets */
|
|
if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK);
|
|
}
|
|
|
|
/* Turn off flow control */
|
|
if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK);
|
|
}
|
|
|
|
/* Turn off promiscuous frame filtering (all frames are received) */
|
|
if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK);
|
|
}
|
|
|
|
/* Disallow broadcast address filtering => broadcast reception */
|
|
if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
|
|
}
|
|
|
|
/* Disallow multicast address filtering */
|
|
if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK);
|
|
}
|
|
|
|
/* Disable RX checksum offload */
|
|
if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
|
|
RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK);
|
|
}
|
|
|
|
/* Officially change the NET_CONFIG registers if it needs to be
|
|
* modified.
|
|
*/
|
|
if (RegNetCfg != RegNewNetCfg) {
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
|
|
}
|
|
|
|
/* Disable TX checksum offload */
|
|
if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_DMACR_OFFSET);
|
|
Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK);
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_DMACR_OFFSET, Reg);
|
|
}
|
|
|
|
/* Disable transmitter */
|
|
if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET);
|
|
Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET, Reg);
|
|
}
|
|
|
|
/* Disable receiver */
|
|
if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET);
|
|
Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET, Reg);
|
|
}
|
|
|
|
/* The remaining options not handled here are managed elsewhere in the
|
|
* driver. No register modifications are needed at this time. Reflecting
|
|
* option in InstancePtr->Options is good enough for now.
|
|
*/
|
|
|
|
/* Set options word to its new value */
|
|
InstancePtr->Options &= ~Options;
|
|
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Get current option settings
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
*
|
|
* @return
|
|
* A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
|
|
* as a set opion.
|
|
*
|
|
* @note
|
|
* See xemacps.h for a description of the available options.
|
|
*
|
|
*****************************************************************************/
|
|
u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
return (InstancePtr->Options);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Send a pause packet
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if pause frame transmission was initiated
|
|
* - XST_DEVICE_IS_STOPPED if the device has not been started.
|
|
*
|
|
*****************************************************************************/
|
|
LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
LONG Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
/* Make sure device is ready for this operation */
|
|
if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
|
|
Status = (LONG)(XST_DEVICE_IS_STOPPED);
|
|
} else {
|
|
/* Send flow control frame */
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET);
|
|
Reg |= XEMACPS_NWCTRL_PAUSETX_MASK;
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCTRL_OFFSET, Reg);
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
|
|
* be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
|
|
*
|
|
* @param InstancePtr references the TEMAC channel on which to operate.
|
|
*
|
|
* @return XEmacPs_GetOperatingSpeed returns the link speed in units of
|
|
* megabits per second.
|
|
*
|
|
* @note
|
|
*
|
|
*****************************************************************************/
|
|
u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
|
|
{
|
|
u32 Reg;
|
|
u16 Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET);
|
|
|
|
if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) {
|
|
Status = (u16)(1000);
|
|
} else {
|
|
if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) {
|
|
Status = (u16)(100);
|
|
} else {
|
|
Status = (u16)(10);
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* XEmacPs_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 TEMAC channel on which to operate.
|
|
* @param Speed is the speed to set in units of Mbps. Valid values are 10, 100,
|
|
* or 1000. XEmacPs_SetOperatingSpeed ignores invalid values.
|
|
*
|
|
* @note
|
|
*
|
|
*****************************************************************************/
|
|
void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
|
|
{
|
|
u32 Reg;
|
|
u16 Status;
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000));
|
|
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET);
|
|
Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK));
|
|
|
|
switch (Speed) {
|
|
case (u16)10:
|
|
Status = 0U;
|
|
break;
|
|
|
|
case (u16)100:
|
|
Status = 0U;
|
|
Reg |= XEMACPS_NWCFG_100_MASK;
|
|
break;
|
|
|
|
case (u16)1000:
|
|
Status = 0U;
|
|
Reg |= XEMACPS_NWCFG_1000_MASK;
|
|
break;
|
|
|
|
default:
|
|
Status = 1U;
|
|
break;
|
|
}
|
|
if(Status == (u16)1){
|
|
return;
|
|
}
|
|
|
|
/* Set register and return */
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET, Reg);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Set the MDIO clock divisor.
|
|
*
|
|
* Calculating the divisor:
|
|
*
|
|
* <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. Here is the table to show values to generate MDC,
|
|
*
|
|
* <pre>
|
|
* 000 : divide pclk by 8 (pclk up to 20 MHz)
|
|
* 001 : divide pclk by 16 (pclk up to 40 MHz)
|
|
* 010 : divide pclk by 32 (pclk up to 80 MHz)
|
|
* 011 : divide pclk by 48 (pclk up to 120 MHz)
|
|
* 100 : divide pclk by 64 (pclk up to 160 MHz)
|
|
* 101 : divide pclk by 96 (pclk up to 240 MHz)
|
|
* 110 : divide pclk by 128 (pclk up to 320 MHz)
|
|
* 111 : divide pclk by 224 (pclk up to 540 MHz)
|
|
* </pre>
|
|
*
|
|
* @param InstancePtr is a pointer to the instance to be worked on.
|
|
* @param Divisor is the divisor to set. Range is 0b000 to 0b111.
|
|
*
|
|
*****************************************************************************/
|
|
void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
|
|
{
|
|
u32 Reg;
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
|
|
Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */
|
|
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET);
|
|
/* clear these three bits, could be done with mask */
|
|
Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK);
|
|
|
|
Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
|
|
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWCFG_OFFSET, Reg);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Read the current value of the PHY register indicated by the PhyAddress and
|
|
* the RegisterNum parameters. The MAC provides the driver with the ability to
|
|
* talk to a PHY that adheres to the Media Independent Interface (MII) as
|
|
* defined in the IEEE 802.3 standard.
|
|
*
|
|
* Prior to PHY access with this function, the user should have setup the MDIO
|
|
* clock with XEmacPs_SetMdioDivisor().
|
|
*
|
|
* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
|
|
* @param PhyAddress is the address of the PHY to be read (supports multiple
|
|
* PHYs)
|
|
* @param RegisterNum is the register number, 0-31, of the specific PHY register
|
|
* to read
|
|
* @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into
|
|
* which the current value of the register will be copied.
|
|
*
|
|
* @return
|
|
*
|
|
* - XST_SUCCESS if the PHY was read from successfully
|
|
* - XST_EMAC_MII_BUSY if there is another PHY operation in progress
|
|
*
|
|
* @note
|
|
*
|
|
* This function is not thread-safe. The user must provide mutually exclusive
|
|
* access to this function if there are to be multiple threads that can call it.
|
|
*
|
|
* 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 read is
|
|
* done). If this is of concern to the user, the user should provide a mechanism
|
|
* suitable to their needs for recovery.
|
|
*
|
|
* For the duration of this function, all host interface reads and writes are
|
|
* blocked to the current XEmacPs instance.
|
|
*
|
|
******************************************************************************/
|
|
LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
|
|
u32 RegisterNum, u16 *PhyDataPtr)
|
|
{
|
|
u32 Mgtcr;
|
|
volatile u32 Ipisr;
|
|
u32 IpReadTemp;
|
|
LONG Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
|
|
/* Make sure no other PHY operation is currently in progress */
|
|
if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWSR_OFFSET) &
|
|
XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
|
|
Status = (LONG)(XST_EMAC_MII_BUSY);
|
|
} else {
|
|
|
|
/* Construct Mgtcr mask for the operation */
|
|
Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK |
|
|
(PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
|
|
(RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK);
|
|
|
|
/* Write Mgtcr and wait for completion */
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
|
|
|
|
do {
|
|
Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWSR_OFFSET);
|
|
IpReadTemp = Ipisr;
|
|
} while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
|
|
|
|
/* Read data */
|
|
*PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_PHYMNTNC_OFFSET);
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Write data to the specified PHY register. The Ethernet driver does not
|
|
* require the device to be stopped before writing to the PHY. Although it is
|
|
* probably a good idea to stop the device, it is the responsibility of the
|
|
* application to deem this necessary. The MAC provides the driver with the
|
|
* ability to talk to a PHY that adheres to the Media Independent Interface
|
|
* (MII) as defined in the IEEE 802.3 standard.
|
|
*
|
|
* Prior to PHY access with this function, the user should have setup the MDIO
|
|
* clock with XEmacPs_SetMdioDivisor().
|
|
*
|
|
* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
|
|
* @param PhyAddress is the address of the PHY to be written (supports multiple
|
|
* PHYs)
|
|
* @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
|
|
*
|
|
* - XST_SUCCESS if the PHY was written to successfully. Since there is no error
|
|
* status from the MAC on a write, the user should read the PHY to verify the
|
|
* write was successful.
|
|
* - XST_EMAC_MII_BUSY if there is another PHY operation in progress
|
|
*
|
|
* @note
|
|
*
|
|
* This function is not thread-safe. The user must provide mutually exclusive
|
|
* access to this function if there are to be multiple threads that can call it.
|
|
*
|
|
* 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 to the user, the user should provide a mechanism
|
|
* suitable to their needs for recovery.
|
|
*
|
|
* For the duration of this function, all host interface reads and writes are
|
|
* blocked to the current XEmacPs instance.
|
|
*
|
|
******************************************************************************/
|
|
LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
|
|
u32 RegisterNum, u16 PhyData)
|
|
{
|
|
u32 Mgtcr;
|
|
volatile u32 Ipisr;
|
|
u32 IpWriteTemp;
|
|
LONG Status;
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
|
|
/* Make sure no other PHY operation is currently in progress */
|
|
if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWSR_OFFSET) &
|
|
XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
|
|
Status = (LONG)(XST_EMAC_MII_BUSY);
|
|
} else {
|
|
/* Construct Mgtcr mask for the operation */
|
|
Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK |
|
|
(PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
|
|
(RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData;
|
|
|
|
/* Write Mgtcr and wait for completion */
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
|
|
|
|
do {
|
|
Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_NWSR_OFFSET);
|
|
IpWriteTemp = Ipisr;
|
|
} while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
|
|
|
|
Status = (LONG)(XST_SUCCESS);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* API to update the Burst length in the DMACR register.
|
|
*
|
|
* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
|
|
* @param BLength is the length in bytes for the dma burst.
|
|
*
|
|
* @return None
|
|
*
|
|
******************************************************************************/
|
|
void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength)
|
|
{
|
|
u32 Reg;
|
|
u32 RegUpdateVal;
|
|
|
|
Xil_AssertVoid(InstancePtr != NULL);
|
|
Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) ||
|
|
(BLength == XEMACPS_4BYTE_BURST) ||
|
|
(BLength == XEMACPS_8BYTE_BURST) ||
|
|
(BLength == XEMACPS_16BYTE_BURST));
|
|
|
|
switch (BLength) {
|
|
case XEMACPS_SINGLE_BURST:
|
|
RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
|
|
break;
|
|
|
|
case XEMACPS_4BYTE_BURST:
|
|
RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
|
|
break;
|
|
|
|
case XEMACPS_8BYTE_BURST:
|
|
RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
|
|
break;
|
|
|
|
case XEMACPS_16BYTE_BURST:
|
|
RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
|
|
break;
|
|
|
|
default:
|
|
RegUpdateVal = 0x00000000U;
|
|
break;
|
|
}
|
|
Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XEMACPS_DMACR_OFFSET);
|
|
|
|
Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK);
|
|
Reg |= RegUpdateVal;
|
|
XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
|
|
Reg);
|
|
}
|