mirror of https://github.com/F-Stack/f-stack.git
1269 lines
45 KiB
C
1269 lines
45 KiB
C
/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Freescale Semiconductor nor the
|
|
* names of its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
*
|
|
* ALTERNATIVELY, this software may be distributed under the terms of the
|
|
* GNU General Public License ("GPL") as published by the Free Software
|
|
* Foundation, either version 2 of that License or (at your option) any
|
|
* later version.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/******************************************************************************
|
|
@File tgec.c
|
|
|
|
@Description FM 10G MAC ...
|
|
*//***************************************************************************/
|
|
|
|
#include "std_ext.h"
|
|
#include "string_ext.h"
|
|
#include "error_ext.h"
|
|
#include "xx_ext.h"
|
|
#include "endian_ext.h"
|
|
#include "crc_mac_addr_ext.h"
|
|
#include "debug_ext.h"
|
|
|
|
#include "fm_common.h"
|
|
#include "tgec.h"
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Internal routines */
|
|
/*****************************************************************************/
|
|
|
|
static t_Error CheckInitParameters(t_Tgec *p_Tgec)
|
|
{
|
|
if(ENET_SPEED_FROM_MODE(p_Tgec->enetMode) < e_ENET_SPEED_10000)
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC driver only support 10G speed"));
|
|
#if (FM_MAX_NUM_OF_10G_MACS > 0)
|
|
if(p_Tgec->macId >= FM_MAX_NUM_OF_10G_MACS)
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId of 10G can not be greater than 0"));
|
|
#endif
|
|
if(p_Tgec->addr == 0)
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC Must have a valid MAC Address"));
|
|
if(!p_Tgec->f_Exception)
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Exception"));
|
|
if(!p_Tgec->f_Event)
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Event"));
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static void SetDefaultParam(t_TgecDriverParam *p_TgecDriverParam)
|
|
{
|
|
p_TgecDriverParam->wanModeEnable = DEFAULT_wanModeEnable;
|
|
p_TgecDriverParam->promiscuousModeEnable = DEFAULT_promiscuousModeEnable;
|
|
p_TgecDriverParam->pauseForwardEnable = DEFAULT_pauseForwardEnable;
|
|
p_TgecDriverParam->pauseIgnore = DEFAULT_pauseIgnore;
|
|
p_TgecDriverParam->txAddrInsEnable = DEFAULT_txAddrInsEnable;
|
|
|
|
p_TgecDriverParam->loopbackEnable = DEFAULT_loopbackEnable;
|
|
p_TgecDriverParam->cmdFrameEnable = DEFAULT_cmdFrameEnable;
|
|
p_TgecDriverParam->rxErrorDiscard = DEFAULT_rxErrorDiscard;
|
|
p_TgecDriverParam->phyTxenaOn = DEFAULT_phyTxenaOn;
|
|
p_TgecDriverParam->sendIdleEnable = DEFAULT_sendIdleEnable;
|
|
p_TgecDriverParam->noLengthCheckEnable = DEFAULT_noLengthCheckEnable;
|
|
p_TgecDriverParam->lgthCheckNostdr = DEFAULT_lgthCheckNostdr;
|
|
p_TgecDriverParam->timeStampEnable = DEFAULT_timeStampEnable;
|
|
p_TgecDriverParam->rxSfdAny = DEFAULT_rxSfdAny;
|
|
p_TgecDriverParam->rxPblFwd = DEFAULT_rxPblFwd;
|
|
p_TgecDriverParam->txPblFwd = DEFAULT_txPblFwd;
|
|
|
|
p_TgecDriverParam->txIpgLength = DEFAULT_txIpgLength;
|
|
p_TgecDriverParam->maxFrameLength = DEFAULT_maxFrameLength;
|
|
|
|
p_TgecDriverParam->debugMode = DEFAULT_debugMode;
|
|
|
|
p_TgecDriverParam->pauseTime = DEFAULT_pauseTime;
|
|
|
|
#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
|
|
p_TgecDriverParam->skipFman11Workaround = DEFAULT_skipFman11Workaround;
|
|
#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
|
|
}
|
|
|
|
/* ........................................................................... */
|
|
|
|
static void TgecErrException(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
uint32_t event;
|
|
t_TgecMemMap *p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
event = GET_UINT32(p_TgecMemMap->ievent);
|
|
/* do not handle MDIO events */
|
|
event &= ~(IMASK_MDIO_SCAN_EVENTMDIO | IMASK_MDIO_CMD_CMPL);
|
|
|
|
event &= GET_UINT32(p_TgecMemMap->imask);
|
|
|
|
WRITE_UINT32(p_TgecMemMap->ievent, event);
|
|
|
|
if (event & IMASK_REM_FAULT)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_REM_FAULT);
|
|
if (event & IMASK_LOC_FAULT)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_LOC_FAULT);
|
|
if (event & IMASK_1TX_ECC_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
|
|
if (event & IMASK_TX_FIFO_UNFL)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL);
|
|
if (event & IMASK_TX_FIFO_OVFL)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL);
|
|
if (event & IMASK_TX_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_ER);
|
|
if (event & IMASK_RX_FIFO_OVFL)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL);
|
|
if (event & IMASK_RX_ECC_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
|
|
if (event & IMASK_RX_JAB_FRM)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_JAB_FRM);
|
|
if (event & IMASK_RX_OVRSZ_FRM)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_OVRSZ_FRM);
|
|
if (event & IMASK_RX_RUNT_FRM)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_RUNT_FRM);
|
|
if (event & IMASK_RX_FRAG_FRM)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FRAG_FRM);
|
|
if (event & IMASK_RX_LEN_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_LEN_ER);
|
|
if (event & IMASK_RX_CRC_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_CRC_ER);
|
|
if (event & IMASK_RX_ALIGN_ER)
|
|
p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ALIGN_ER);
|
|
}
|
|
|
|
static void TgecException(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
uint32_t event;
|
|
t_TgecMemMap *p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
event = GET_UINT32(p_TgecMemMap->ievent);
|
|
/* handle only MDIO events */
|
|
event &= (IMASK_MDIO_SCAN_EVENTMDIO | IMASK_MDIO_CMD_CMPL);
|
|
event &= GET_UINT32(p_TgecMemMap->imask);
|
|
|
|
WRITE_UINT32(p_TgecMemMap->ievent, event);
|
|
|
|
if(event & IMASK_MDIO_SCAN_EVENTMDIO)
|
|
p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO);
|
|
if(event & IMASK_MDIO_CMD_CMPL)
|
|
p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_CMD_CMPL);
|
|
}
|
|
|
|
static void FreeInitResources(t_Tgec *p_Tgec)
|
|
{
|
|
if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ))
|
|
{
|
|
XX_DisableIntr(p_Tgec->mdioIrq);
|
|
XX_FreeIntr(p_Tgec->mdioIrq);
|
|
}
|
|
else if (p_Tgec->mdioIrq == 0)
|
|
REPORT_ERROR(MINOR, E_NOT_SUPPORTED, (NO_MSG));
|
|
FmUnregisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Tgec->macId, e_FM_INTR_TYPE_ERR);
|
|
|
|
/* release the driver's group hash table */
|
|
FreeHashTable(p_Tgec->p_MulticastAddrHash);
|
|
p_Tgec->p_MulticastAddrHash = NULL;
|
|
|
|
/* release the driver's individual hash table */
|
|
FreeHashTable(p_Tgec->p_UnicastAddrHash);
|
|
p_Tgec->p_UnicastAddrHash = NULL;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static void HardwareClearAddrInPaddr(t_Tgec *p_Tgec, uint8_t paddrNum)
|
|
{
|
|
if (paddrNum != 0)
|
|
return; /* At this time MAC has only one address */
|
|
|
|
WRITE_UINT32(p_Tgec->p_MemMap->mac_addr_2, 0x0);
|
|
WRITE_UINT32(p_Tgec->p_MemMap->mac_addr_3, 0x0);
|
|
}
|
|
|
|
/* ........................................................................... */
|
|
|
|
static void HardwareAddAddrInPaddr(t_Tgec *p_Tgec, uint64_t *p_Addr, uint8_t paddrNum)
|
|
{
|
|
uint32_t tmpReg32 = 0;
|
|
uint64_t addr = *p_Addr;
|
|
t_TgecMemMap *p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
if (paddrNum != 0)
|
|
return; /* At this time MAC has only one address */
|
|
|
|
tmpReg32 = (uint32_t)(addr>>16);
|
|
SwapUint32P(&tmpReg32);
|
|
WRITE_UINT32(p_TgecMemMap->mac_addr_2, tmpReg32);
|
|
|
|
tmpReg32 = (uint32_t)(addr);
|
|
SwapUint32P(&tmpReg32);
|
|
tmpReg32 >>= 16;
|
|
WRITE_UINT32(p_TgecMemMap->mac_addr_3, tmpReg32);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* 10G MAC API routines */
|
|
/*****************************************************************************/
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecEnable(t_Handle h_Tgec, e_CommMode mode)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_MemMap ;
|
|
uint32_t tmpReg32 = 0;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_HANDLE);
|
|
|
|
p_MemMap= (t_TgecMemMap*)(p_Tgec->p_MemMap);
|
|
|
|
tmpReg32 = GET_UINT32(p_MemMap->cmd_conf_ctrl);
|
|
|
|
switch (mode)
|
|
{
|
|
case e_COMM_MODE_NONE:
|
|
tmpReg32 &= ~(CMD_CFG_TX_EN | CMD_CFG_RX_EN);
|
|
break;
|
|
case e_COMM_MODE_RX :
|
|
tmpReg32 |= CMD_CFG_RX_EN ;
|
|
break;
|
|
case e_COMM_MODE_TX :
|
|
tmpReg32 |= CMD_CFG_TX_EN ;
|
|
break;
|
|
case e_COMM_MODE_RX_AND_TX:
|
|
tmpReg32 |= (CMD_CFG_TX_EN | CMD_CFG_RX_EN);
|
|
break;
|
|
}
|
|
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, tmpReg32);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecDisable (t_Handle h_Tgec, e_CommMode mode)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_MemMap ;
|
|
uint32_t tmpReg32 = 0;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_HANDLE);
|
|
|
|
p_MemMap= (t_TgecMemMap*)(p_Tgec->p_MemMap);
|
|
|
|
tmpReg32 = GET_UINT32(p_MemMap->cmd_conf_ctrl);
|
|
switch (mode)
|
|
{
|
|
case e_COMM_MODE_RX:
|
|
tmpReg32 &= ~CMD_CFG_RX_EN;
|
|
break;
|
|
case e_COMM_MODE_TX:
|
|
tmpReg32 &= ~CMD_CFG_TX_EN;
|
|
break;
|
|
case e_COMM_MODE_RX_AND_TX:
|
|
tmpReg32 &= ~(CMD_CFG_TX_EN | CMD_CFG_RX_EN);
|
|
break;
|
|
default:
|
|
RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
|
|
}
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, tmpReg32);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecSetPromiscuous(t_Handle h_Tgec, bool newVal)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
uint32_t tmpReg32;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
tmpReg32 = GET_UINT32(p_TgecMemMap->cmd_conf_ctrl);
|
|
|
|
if (newVal)
|
|
tmpReg32 |= CMD_CFG_PROMIS_EN;
|
|
else
|
|
tmpReg32 &= ~CMD_CFG_PROMIS_EN;
|
|
|
|
WRITE_UINT32(p_TgecMemMap->cmd_conf_ctrl, tmpReg32);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Tgec Configs modification functions */
|
|
/*****************************************************************************/
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigLoopback(t_Handle h_Tgec, bool newVal)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
#ifdef FM_NO_TGEC_LOOPBACK
|
|
{
|
|
t_FmRevisionInfo revInfo;
|
|
FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &revInfo);
|
|
if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
|
|
RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("no loopback in this chip rev!"));
|
|
}
|
|
#endif /* FM_NO_TGEC_LOOPBACK */
|
|
|
|
p_Tgec->p_TgecDriverParam->loopbackEnable = newVal;
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigWan(t_Handle h_Tgec, bool newVal)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_Tgec->p_TgecDriverParam->wanModeEnable = newVal;
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigMaxFrameLength(t_Handle h_Tgec, uint16_t newVal)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_Tgec->p_TgecDriverParam->maxFrameLength = newVal;
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigLengthCheck(t_Handle h_Tgec, bool newVal)
|
|
{
|
|
#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
|
|
UNUSED(h_Tgec);
|
|
RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
|
|
|
|
#else
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
UNUSED(newVal);
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_Tgec->p_TgecDriverParam->noLengthCheckEnable = !newVal;
|
|
|
|
return E_OK;
|
|
#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigException(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
uint32_t bitMask = 0;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
#ifdef FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001
|
|
{
|
|
t_FmRevisionInfo revInfo;
|
|
FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &revInfo);
|
|
if((revInfo.majorRev <=2) &&
|
|
enable &&
|
|
((exception == e_FM_MAC_EX_10G_LOC_FAULT) || (exception == e_FM_MAC_EX_10G_REM_FAULT)))
|
|
RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_MAC_EX_10G_LOC_FAULT and e_FM_MAC_EX_10G_REM_FAULT !"));
|
|
}
|
|
#endif /* FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001 */
|
|
|
|
GET_EXCEPTION_FLAG(bitMask, exception);
|
|
if(bitMask)
|
|
{
|
|
if (enable)
|
|
p_Tgec->exceptions |= bitMask;
|
|
else
|
|
p_Tgec->exceptions &= ~bitMask;
|
|
}
|
|
else
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecConfigSkipFman11Workaround(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_Tgec->p_TgecDriverParam->skipFman11Workaround = TRUE;
|
|
|
|
return E_OK;
|
|
}
|
|
#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Tgec Run Time API functions */
|
|
/*****************************************************************************/
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecTxMacPause(t_Handle h_Tgec, uint16_t pauseTime)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
uint32_t ptv = 0;
|
|
t_TgecMemMap *p_MemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_STATE);
|
|
|
|
p_MemMap = (t_TgecMemMap*)(p_Tgec->p_MemMap);
|
|
|
|
ptv = (uint32_t)pauseTime;
|
|
|
|
WRITE_UINT32(p_MemMap->pause_quant, ptv);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecRxIgnoreMacPause(t_Handle h_Tgec, bool en)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_MemMap;
|
|
uint32_t tmpReg32;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_STATE);
|
|
|
|
p_MemMap = (t_TgecMemMap*)(p_Tgec->p_MemMap);
|
|
tmpReg32 = GET_UINT32(p_MemMap->cmd_conf_ctrl);
|
|
if (en)
|
|
tmpReg32 |= CMD_CFG_PAUSE_IGNORE;
|
|
else
|
|
tmpReg32 &= ~CMD_CFG_PAUSE_IGNORE;
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, tmpReg32);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* Counters handling */
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecGetStatistics(t_Handle h_Tgec, t_FmMacStatistics *p_Statistics)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
p_Statistics->eStatPkts64 = GET_UINT64(p_TgecMemMap->R64);
|
|
p_Statistics->eStatPkts65to127 = GET_UINT64(p_TgecMemMap->R127);
|
|
p_Statistics->eStatPkts128to255 = GET_UINT64(p_TgecMemMap->R255);
|
|
p_Statistics->eStatPkts256to511 = GET_UINT64(p_TgecMemMap->R511);
|
|
p_Statistics->eStatPkts512to1023 = GET_UINT64(p_TgecMemMap->R1023);
|
|
p_Statistics->eStatPkts1024to1518 = GET_UINT64(p_TgecMemMap->R1518);
|
|
p_Statistics->eStatPkts1519to1522 = GET_UINT64(p_TgecMemMap->R1519X);
|
|
/* */
|
|
p_Statistics->eStatFragments = GET_UINT64(p_TgecMemMap->TRFRG);
|
|
p_Statistics->eStatJabbers = GET_UINT64(p_TgecMemMap->TRJBR);
|
|
|
|
p_Statistics->eStatsDropEvents = GET_UINT64(p_TgecMemMap->RDRP);
|
|
p_Statistics->eStatCRCAlignErrors = GET_UINT64(p_TgecMemMap->RALN);
|
|
|
|
p_Statistics->eStatUndersizePkts = GET_UINT64(p_TgecMemMap->TRUND);
|
|
p_Statistics->eStatOversizePkts = GET_UINT64(p_TgecMemMap->TROVR);
|
|
/* Pause */
|
|
p_Statistics->reStatPause = GET_UINT64(p_TgecMemMap->RXPF);
|
|
p_Statistics->teStatPause = GET_UINT64(p_TgecMemMap->TXPF);
|
|
|
|
|
|
/* MIB II */
|
|
p_Statistics->ifInOctets = GET_UINT64(p_TgecMemMap->ROCT);
|
|
p_Statistics->ifInMcastPkts = GET_UINT64(p_TgecMemMap->RMCA);
|
|
p_Statistics->ifInBcastPkts = GET_UINT64(p_TgecMemMap->RBCA);
|
|
p_Statistics->ifInPkts = GET_UINT64(p_TgecMemMap->RUCA)
|
|
+ p_Statistics->ifInMcastPkts
|
|
+ p_Statistics->ifInBcastPkts;
|
|
p_Statistics->ifInDiscards = 0;
|
|
p_Statistics->ifInErrors = GET_UINT64(p_TgecMemMap->RERR);
|
|
|
|
p_Statistics->ifOutOctets = GET_UINT64(p_TgecMemMap->TOCT);
|
|
p_Statistics->ifOutMcastPkts = GET_UINT64(p_TgecMemMap->TMCA);
|
|
p_Statistics->ifOutBcastPkts = GET_UINT64(p_TgecMemMap->TBCA);
|
|
p_Statistics->ifOutPkts = GET_UINT64(p_TgecMemMap->TUCA);
|
|
p_Statistics->ifOutDiscards = 0;
|
|
p_Statistics->ifOutErrors = GET_UINT64(p_TgecMemMap->TERR);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecEnable1588TimeStamp(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
SANITY_CHECK_RETURN_ERROR(p_TgecMemMap, E_INVALID_HANDLE);
|
|
|
|
WRITE_UINT32(p_TgecMemMap->cmd_conf_ctrl, GET_UINT32(p_TgecMemMap->cmd_conf_ctrl) | CMD_CFG_EN_TIMESTAMP);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecDisable1588TimeStamp(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
SANITY_CHECK_RETURN_ERROR(p_TgecMemMap, E_INVALID_HANDLE);
|
|
|
|
WRITE_UINT32(p_TgecMemMap->cmd_conf_ctrl, GET_UINT32(p_TgecMemMap->cmd_conf_ctrl) & ~CMD_CFG_EN_TIMESTAMP);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecModifyMacAddress (t_Handle h_Tgec, t_EnetAddr *p_EnetAddr)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
uint32_t tmpReg32 = 0;
|
|
uint64_t addr;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
|
|
/* Initialize MAC Station Address registers (1 & 2) */
|
|
/* Station address have to be swapped (big endian to little endian */
|
|
|
|
addr = ((*(uint64_t *)p_EnetAddr) >> 16);
|
|
p_Tgec->addr = addr;
|
|
|
|
tmpReg32 = (uint32_t)(addr>>16);
|
|
SwapUint32P(&tmpReg32);
|
|
WRITE_UINT32(p_TgecMemMap->mac_addr_0, tmpReg32);
|
|
|
|
tmpReg32 = (uint32_t)(addr);
|
|
SwapUint32P(&tmpReg32);
|
|
tmpReg32 >>= 16;
|
|
WRITE_UINT32(p_TgecMemMap->mac_addr_1, tmpReg32);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecResetCounters (t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_MemMap ;
|
|
uint32_t tmpReg32, cmdConfCtrl;
|
|
int i;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_HANDLE);
|
|
|
|
p_MemMap= (t_TgecMemMap*)(p_Tgec->p_MemMap);
|
|
|
|
cmdConfCtrl = GET_UINT32(p_MemMap->cmd_conf_ctrl);
|
|
|
|
cmdConfCtrl |= CMD_CFG_STAT_CLR;
|
|
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, cmdConfCtrl);
|
|
|
|
for (i=0; i<1000; i++)
|
|
{
|
|
tmpReg32 = GET_UINT32(p_MemMap->cmd_conf_ctrl);
|
|
if (!(tmpReg32 & CMD_CFG_STAT_CLR))
|
|
break;
|
|
}
|
|
|
|
cmdConfCtrl &= ~CMD_CFG_STAT_CLR;
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, cmdConfCtrl);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecAddExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *) h_Tgec;
|
|
uint64_t ethAddr;
|
|
uint8_t paddrNum;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
|
|
ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
|
|
|
|
if (ethAddr & GROUP_ADDRESS)
|
|
/* Multicast address has no effect in PADDR */
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
|
|
|
|
/* Make sure no PADDR contains this address */
|
|
for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
|
|
{
|
|
if (p_Tgec->indAddrRegUsed[paddrNum])
|
|
{
|
|
if (p_Tgec->paddr[paddrNum] == ethAddr)
|
|
{
|
|
RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Find first unused PADDR */
|
|
for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
|
|
{
|
|
if (!(p_Tgec->indAddrRegUsed[paddrNum]))
|
|
{
|
|
/* mark this PADDR as used */
|
|
p_Tgec->indAddrRegUsed[paddrNum] = TRUE;
|
|
/* store address */
|
|
p_Tgec->paddr[paddrNum] = ethAddr;
|
|
|
|
/* put in hardware */
|
|
HardwareAddAddrInPaddr(p_Tgec, ðAddr, paddrNum);
|
|
p_Tgec->numOfIndAddrInRegs++;
|
|
|
|
return E_OK;
|
|
}
|
|
}
|
|
|
|
/* No free PADDR */
|
|
RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecDelExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *) h_Tgec;
|
|
uint64_t ethAddr;
|
|
uint8_t paddrNum;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_HANDLE);
|
|
|
|
ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
|
|
|
|
/* Find used PADDR containing this address */
|
|
for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
|
|
{
|
|
if ((p_Tgec->indAddrRegUsed[paddrNum]) &&
|
|
(p_Tgec->paddr[paddrNum] == ethAddr))
|
|
{
|
|
/* mark this PADDR as not used */
|
|
p_Tgec->indAddrRegUsed[paddrNum] = FALSE;
|
|
/* clear in hardware */
|
|
HardwareClearAddrInPaddr(p_Tgec, paddrNum);
|
|
p_Tgec->numOfIndAddrInRegs--;
|
|
|
|
return E_OK;
|
|
}
|
|
}
|
|
|
|
RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecAddHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
t_EthHashEntry *p_HashEntry;
|
|
uint32_t crc;
|
|
uint32_t hash;
|
|
uint64_t ethAddr;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
|
|
|
|
if (!(ethAddr & GROUP_ADDRESS))
|
|
/* Unicast addresses not supported in hash */
|
|
RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
|
|
|
|
/* CRC calculation */
|
|
GET_MAC_ADDR_CRC(ethAddr, crc);
|
|
crc = MIRROR_32(crc);
|
|
|
|
hash = (crc >> HASH_CTRL_MCAST_SHIFT) & HASH_ADDR_MASK; /* Take 9 MSB bits */
|
|
|
|
/* Create element to be added to the driver hash table */
|
|
p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
|
|
p_HashEntry->addr = ethAddr;
|
|
INIT_LIST(&p_HashEntry->node);
|
|
|
|
LIST_AddToTail(&(p_HashEntry->node), &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash]));
|
|
WRITE_UINT32(p_TgecMemMap->hashtable_ctrl, (hash | HASH_CTRL_MCAST_EN));
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecDelHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
t_EthHashEntry *p_HashEntry = NULL;
|
|
t_List *p_Pos;
|
|
uint32_t crc;
|
|
uint32_t hash;
|
|
uint64_t ethAddr;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
|
|
|
|
/* CRC calculation */
|
|
GET_MAC_ADDR_CRC(ethAddr, crc);
|
|
crc = MIRROR_32(crc);
|
|
|
|
hash = (crc >> HASH_CTRL_MCAST_SHIFT) & HASH_ADDR_MASK; /* Take 9 MSB bits */
|
|
|
|
LIST_FOR_EACH(p_Pos, &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash]))
|
|
{
|
|
|
|
p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
|
|
if(p_HashEntry->addr == ethAddr)
|
|
{
|
|
LIST_DelAndInit(&p_HashEntry->node);
|
|
XX_Free(p_HashEntry);
|
|
break;
|
|
}
|
|
}
|
|
if(LIST_IsEmpty(&p_Tgec->p_MulticastAddrHash->p_Lsts[hash]))
|
|
WRITE_UINT32(p_TgecMemMap->hashtable_ctrl, (hash & ~HASH_CTRL_MCAST_EN));
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecGetId(t_Handle h_Tgec, uint32_t *macId)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_NULL_POINTER);
|
|
|
|
UNUSED(p_Tgec);
|
|
UNUSED(macId);
|
|
RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("TgecGetId Not Supported"));
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecGetVersion(t_Handle h_Tgec, uint32_t *macVersion)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
*macVersion = GET_UINT32(p_TgecMemMap->tgec_id);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecSetExcpetion(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
uint32_t bitMask = 0, tmpReg;
|
|
t_TgecMemMap *p_TgecMemMap;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_NULL_POINTER);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_NULL_POINTER);
|
|
|
|
p_TgecMemMap = p_Tgec->p_MemMap;
|
|
#ifdef FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001
|
|
{
|
|
t_FmRevisionInfo revInfo;
|
|
FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &revInfo);
|
|
if((revInfo.majorRev <=2) &&
|
|
enable &&
|
|
((exception == e_FM_MAC_EX_10G_LOC_FAULT) || (exception == e_FM_MAC_EX_10G_REM_FAULT)))
|
|
RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_MAC_EX_10G_LOC_FAULT and e_FM_MAC_EX_10G_REM_FAULT !"));
|
|
}
|
|
#endif /* FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001 */
|
|
|
|
GET_EXCEPTION_FLAG(bitMask, exception);
|
|
if(bitMask)
|
|
{
|
|
if (enable)
|
|
p_Tgec->exceptions |= bitMask;
|
|
else
|
|
p_Tgec->exceptions &= ~bitMask;
|
|
}
|
|
else
|
|
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
|
|
|
|
tmpReg = GET_UINT32(p_TgecMemMap->imask);
|
|
if(enable)
|
|
tmpReg |= bitMask;
|
|
else
|
|
tmpReg &= ~bitMask;
|
|
WRITE_UINT32(p_TgecMemMap->imask, tmpReg);
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static uint16_t TgecGetMaxFrameLength(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_VALUE(p_Tgec, E_INVALID_HANDLE, 0);
|
|
|
|
return (uint16_t)GET_UINT32(p_Tgec->p_MemMap->maxfrm);
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
|
|
static t_Error TgecTxEccWorkaround(t_Tgec *p_Tgec)
|
|
{
|
|
t_Error err;
|
|
|
|
XX_Print("Applying 10G tx-ecc error workaround (10GMAC-A004) ...");
|
|
/* enable and set promiscuous */
|
|
WRITE_UINT32(p_Tgec->p_MemMap->cmd_conf_ctrl, CMD_CFG_PROMIS_EN | CMD_CFG_TX_EN | CMD_CFG_RX_EN);
|
|
err = Fm10GTxEccWorkaround(p_Tgec->fmMacControllerDriver.h_Fm, p_Tgec->macId);
|
|
/* disable */
|
|
WRITE_UINT32(p_Tgec->p_MemMap->cmd_conf_ctrl, 0);
|
|
if (err)
|
|
XX_Print("FAILED!\n");
|
|
else
|
|
XX_Print("done.\n");
|
|
TgecResetCounters (p_Tgec);
|
|
|
|
return err;
|
|
}
|
|
#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
|
|
|
|
/* .............................................................................. */
|
|
|
|
#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
|
|
static t_Error TgecDumpRegs(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
DECLARE_DUMP;
|
|
|
|
if (p_Tgec->p_MemMap)
|
|
{
|
|
DUMP_TITLE(p_Tgec->p_MemMap, ("10G MAC %d: ", p_Tgec->macId));
|
|
DUMP_VAR(p_Tgec->p_MemMap, tgec_id);
|
|
DUMP_VAR(p_Tgec->p_MemMap, scratch);
|
|
DUMP_VAR(p_Tgec->p_MemMap, cmd_conf_ctrl);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mac_addr_0);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mac_addr_1);
|
|
DUMP_VAR(p_Tgec->p_MemMap, maxfrm);
|
|
DUMP_VAR(p_Tgec->p_MemMap, pause_quant);
|
|
DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_sections);
|
|
DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_sections);
|
|
DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_almost_f_e);
|
|
DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_almost_f_e);
|
|
DUMP_VAR(p_Tgec->p_MemMap, hashtable_ctrl);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mdio_cfg_status);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mdio_command);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mdio_data);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mdio_regaddr);
|
|
DUMP_VAR(p_Tgec->p_MemMap, status);
|
|
DUMP_VAR(p_Tgec->p_MemMap, tx_ipg_len);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mac_addr_2);
|
|
DUMP_VAR(p_Tgec->p_MemMap, mac_addr_3);
|
|
DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_rd);
|
|
DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_wr);
|
|
DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_rd);
|
|
DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_wr);
|
|
DUMP_VAR(p_Tgec->p_MemMap, imask);
|
|
DUMP_VAR(p_Tgec->p_MemMap, ievent);
|
|
DUMP_VAR(p_Tgec->p_MemMap, udp_port);
|
|
DUMP_VAR(p_Tgec->p_MemMap, type_1588v2);
|
|
}
|
|
|
|
return E_OK;
|
|
}
|
|
#endif /* (defined(DEBUG_ERRORS) && ... */
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* FM Init & Free API */
|
|
/*****************************************************************************/
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecInit(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
t_TgecDriverParam *p_TgecDriverParam;
|
|
t_TgecMemMap *p_MemMap;
|
|
uint64_t addr;
|
|
uint32_t tmpReg32;
|
|
t_Error err;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MemMap, E_INVALID_HANDLE);
|
|
|
|
#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
|
|
if (!p_Tgec->p_TgecDriverParam->skipFman11Workaround &&
|
|
((err = TgecTxEccWorkaround(p_Tgec)) != E_OK))
|
|
#ifdef NCSW_LINUX
|
|
{
|
|
/* the workaround fails in simics, just report and continue initialization */
|
|
REPORT_ERROR(MAJOR, err, ("TgecTxEccWorkaround FAILED, skipping workaround"));
|
|
}
|
|
#else
|
|
{
|
|
FreeInitResources(p_Tgec);
|
|
RETURN_ERROR(MAJOR, err, ("TgecTxEccWorkaround FAILED"));
|
|
}
|
|
#endif
|
|
#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
|
|
|
|
CHECK_INIT_PARAMETERS(p_Tgec, CheckInitParameters);
|
|
|
|
p_TgecDriverParam = p_Tgec->p_TgecDriverParam;
|
|
p_MemMap = p_Tgec->p_MemMap;
|
|
|
|
/* MAC Address */
|
|
addr = p_Tgec->addr;
|
|
tmpReg32 = (uint32_t)(addr>>16);
|
|
SwapUint32P(&tmpReg32);
|
|
WRITE_UINT32(p_MemMap->mac_addr_0, tmpReg32);
|
|
|
|
tmpReg32 = (uint32_t)(addr);
|
|
SwapUint32P(&tmpReg32);
|
|
tmpReg32 >>= 16;
|
|
WRITE_UINT32(p_MemMap->mac_addr_1, tmpReg32);
|
|
|
|
/* Config */
|
|
tmpReg32 = 0;
|
|
if (p_TgecDriverParam->wanModeEnable)
|
|
tmpReg32 |= CMD_CFG_WAN_MODE;
|
|
if (p_TgecDriverParam->promiscuousModeEnable)
|
|
tmpReg32 |= CMD_CFG_PROMIS_EN;
|
|
if (p_TgecDriverParam->pauseForwardEnable)
|
|
tmpReg32 |= CMD_CFG_PAUSE_FWD;
|
|
if (p_TgecDriverParam->pauseIgnore)
|
|
tmpReg32 |= CMD_CFG_PAUSE_IGNORE;
|
|
if (p_TgecDriverParam->txAddrInsEnable)
|
|
tmpReg32 |= CMD_CFG_TX_ADDR_INS;
|
|
if (p_TgecDriverParam->loopbackEnable)
|
|
tmpReg32 |= CMD_CFG_LOOPBACK_EN;
|
|
if (p_TgecDriverParam->cmdFrameEnable)
|
|
tmpReg32 |= CMD_CFG_CMD_FRM_EN;
|
|
if (p_TgecDriverParam->rxErrorDiscard)
|
|
tmpReg32 |= CMD_CFG_RX_ER_DISC;
|
|
if (p_TgecDriverParam->phyTxenaOn)
|
|
tmpReg32 |= CMD_CFG_PHY_TX_EN;
|
|
if (p_TgecDriverParam->sendIdleEnable)
|
|
tmpReg32 |= CMD_CFG_SEND_IDLE;
|
|
if (p_TgecDriverParam->noLengthCheckEnable)
|
|
tmpReg32 |= CMD_CFG_NO_LEN_CHK;
|
|
if (p_TgecDriverParam->lgthCheckNostdr)
|
|
tmpReg32 |= CMD_CFG_LEN_CHK_NOSTDR;
|
|
if (p_TgecDriverParam->timeStampEnable)
|
|
tmpReg32 |= CMD_CFG_EN_TIMESTAMP;
|
|
if (p_TgecDriverParam->rxSfdAny)
|
|
tmpReg32 |= RX_SFD_ANY;
|
|
if (p_TgecDriverParam->rxPblFwd)
|
|
tmpReg32 |= CMD_CFG_RX_PBL_FWD;
|
|
if (p_TgecDriverParam->txPblFwd)
|
|
tmpReg32 |= CMD_CFG_TX_PBL_FWD;
|
|
tmpReg32 |= 0x40;
|
|
WRITE_UINT32(p_MemMap->cmd_conf_ctrl, tmpReg32);
|
|
|
|
/* Max Frame Length */
|
|
WRITE_UINT32(p_MemMap->maxfrm, (uint32_t)p_TgecDriverParam->maxFrameLength);
|
|
err = FmSetMacMaxFrame(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MAC_10G, p_Tgec->fmMacControllerDriver.macId, p_TgecDriverParam->maxFrameLength);
|
|
if(err)
|
|
{
|
|
FreeInitResources(p_Tgec);
|
|
RETURN_ERROR(MAJOR, err, NO_MSG);
|
|
}
|
|
|
|
/* Pause Time */
|
|
WRITE_UINT32(p_MemMap->pause_quant, p_TgecDriverParam->pauseTime);
|
|
|
|
#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
|
|
WRITE_UINT32(p_Tgec->p_MemMap->tx_ipg_len,
|
|
(GET_UINT32(p_Tgec->p_MemMap->tx_ipg_len) & ~TX_IPG_LENGTH_MASK) | DEFAULT_txIpgLength);
|
|
#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
|
|
|
|
/* Configure MII */
|
|
tmpReg32 = GET_UINT32(p_Tgec->p_MiiMemMap->mdio_cfg_status);
|
|
#ifdef FM_10G_MDIO_HOLD_ERRATA_XAUI3
|
|
{
|
|
t_FmRevisionInfo revInfo;
|
|
FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &revInfo);
|
|
if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
|
|
tmpReg32 |= (MIIMCOM_MDIO_HOLD_4_REG_CLK << 2);
|
|
}
|
|
#endif /* FM_10G_MDIO_HOLD_ERRATA_XAUI3 */
|
|
tmpReg32 &= ~MIIMCOM_DIV_MASK;
|
|
/* (one half of fm clock => 2.5Mhz) */
|
|
tmpReg32 |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT);
|
|
WRITE_UINT32(p_Tgec->p_MiiMemMap->mdio_cfg_status, tmpReg32);
|
|
|
|
p_Tgec->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
|
|
if(!p_Tgec->p_MulticastAddrHash)
|
|
{
|
|
FreeInitResources(p_Tgec);
|
|
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
|
|
}
|
|
|
|
p_Tgec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
|
|
if(!p_Tgec->p_UnicastAddrHash)
|
|
{
|
|
FreeInitResources(p_Tgec);
|
|
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
|
|
}
|
|
|
|
/* interrupts */
|
|
#ifdef FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001
|
|
{
|
|
t_FmRevisionInfo revInfo;
|
|
FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &revInfo);
|
|
if (revInfo.majorRev <=2)
|
|
p_Tgec->exceptions &= ~(IMASK_REM_FAULT | IMASK_LOC_FAULT);
|
|
}
|
|
#endif /* FM_10G_REM_N_LCL_FLT_EX_ERRATA_10GMAC001 */
|
|
WRITE_UINT32(p_MemMap->ievent, EVENTS_MASK);
|
|
WRITE_UINT32(p_MemMap->imask, p_Tgec->exceptions);
|
|
|
|
FmRegisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Tgec->macId, e_FM_INTR_TYPE_ERR, TgecErrException , p_Tgec);
|
|
if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ))
|
|
{
|
|
XX_SetIntr(p_Tgec->mdioIrq, TgecException, p_Tgec);
|
|
XX_EnableIntr(p_Tgec->mdioIrq);
|
|
}
|
|
else if (p_Tgec->mdioIrq == 0)
|
|
REPORT_ERROR(MINOR, E_NOT_SUPPORTED, (NO_MSG));
|
|
|
|
XX_Free(p_TgecDriverParam);
|
|
p_Tgec->p_TgecDriverParam = NULL;
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static t_Error TgecFree(t_Handle h_Tgec)
|
|
{
|
|
t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
|
|
|
|
SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
|
|
|
|
FreeInitResources(p_Tgec);
|
|
|
|
if (p_Tgec->p_TgecDriverParam)
|
|
{
|
|
XX_Free(p_Tgec->p_TgecDriverParam);
|
|
p_Tgec->p_TgecDriverParam = NULL;
|
|
}
|
|
XX_Free (p_Tgec);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/* .............................................................................. */
|
|
|
|
static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
|
|
{
|
|
p_FmMacControllerDriver->f_FM_MAC_Init = TgecInit;
|
|
p_FmMacControllerDriver->f_FM_MAC_Free = TgecFree;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = TgecConfigLoopback;
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = TgecConfigMaxFrameLength;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigWan = TgecConfigWan;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = NULL; /* TGEC always works with pad+crc */
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is not supported in xgec */
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = TgecConfigLengthCheck;
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigException = TgecConfigException;
|
|
|
|
#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
|
|
p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround= TgecConfigSkipFman11Workaround;
|
|
#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_SetException = TgecSetExcpetion;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = TgecEnable1588TimeStamp;
|
|
p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = TgecDisable1588TimeStamp;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = TgecSetPromiscuous;
|
|
p_FmMacControllerDriver->f_FM_MAC_AdjustLink = NULL;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_Enable = TgecEnable;
|
|
p_FmMacControllerDriver->f_FM_MAC_Disable = TgecDisable;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = TgecTxMacPause;
|
|
p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = TgecRxIgnoreMacPause;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_ResetCounters = TgecResetCounters;
|
|
p_FmMacControllerDriver->f_FM_MAC_GetStatistics = TgecGetStatistics;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = TgecModifyMacAddress;
|
|
p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = TgecAddHashMacAddress;
|
|
p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = TgecDelHashMacAddress;
|
|
p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = TgecAddExactMatchMacAddress;
|
|
p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = TgecDelExactMatchMacAddress;
|
|
p_FmMacControllerDriver->f_FM_MAC_GetId = TgecGetId;
|
|
p_FmMacControllerDriver->f_FM_MAC_GetVersion = TgecGetVersion;
|
|
p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = TgecGetMaxFrameLength;
|
|
|
|
p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = TGEC_MII_WritePhyReg;
|
|
p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = TGEC_MII_ReadPhyReg;
|
|
|
|
#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
|
|
p_FmMacControllerDriver->f_FM_MAC_DumpRegs = TgecDumpRegs;
|
|
#endif /* (defined(DEBUG_ERRORS) && ... */
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Tgec Config Main Entry */
|
|
/*****************************************************************************/
|
|
|
|
/* .............................................................................. */
|
|
|
|
t_Handle TGEC_Config(t_FmMacParams *p_FmMacParam)
|
|
{
|
|
t_Tgec *p_Tgec;
|
|
t_TgecDriverParam *p_TgecDriverParam;
|
|
uintptr_t baseAddr;
|
|
uint8_t i;
|
|
|
|
SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
|
|
|
|
baseAddr = p_FmMacParam->baseAddr;
|
|
/* allocate memory for the UCC GETH data structure. */
|
|
p_Tgec = (t_Tgec *) XX_Malloc(sizeof(t_Tgec));
|
|
if (!p_Tgec)
|
|
{
|
|
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver structure"));
|
|
return NULL;
|
|
}
|
|
/* Zero out * p_Tgec */
|
|
memset(p_Tgec, 0, sizeof(t_Tgec));
|
|
InitFmMacControllerDriver(&p_Tgec->fmMacControllerDriver);
|
|
|
|
/* allocate memory for the 10G MAC driver parameters data structure. */
|
|
p_TgecDriverParam = (t_TgecDriverParam *) XX_Malloc(sizeof(t_TgecDriverParam));
|
|
if (!p_TgecDriverParam)
|
|
{
|
|
REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver parameters"));
|
|
TgecFree(p_Tgec);
|
|
return NULL;
|
|
}
|
|
/* Zero out */
|
|
memset(p_TgecDriverParam, 0, sizeof(t_TgecDriverParam));
|
|
|
|
/* Plant parameter structure pointer */
|
|
p_Tgec->p_TgecDriverParam = p_TgecDriverParam;
|
|
|
|
SetDefaultParam(p_TgecDriverParam);
|
|
|
|
for (i=0; i < sizeof(p_FmMacParam->addr); i++)
|
|
p_Tgec->addr |= ((uint64_t)p_FmMacParam->addr[i] << ((5-i) * 8));
|
|
|
|
p_Tgec->p_MemMap = (t_TgecMemMap *)UINT_TO_PTR(baseAddr);
|
|
p_Tgec->p_MiiMemMap = (t_TgecMiiAccessMemMap *)UINT_TO_PTR(baseAddr + TGEC_TO_MII_OFFSET);
|
|
p_Tgec->enetMode = p_FmMacParam->enetMode;
|
|
p_Tgec->macId = p_FmMacParam->macId;
|
|
p_Tgec->exceptions = DEFAULT_exceptions;
|
|
p_Tgec->mdioIrq = p_FmMacParam->mdioIrq;
|
|
p_Tgec->f_Exception = p_FmMacParam->f_Exception;
|
|
p_Tgec->f_Event = p_FmMacParam->f_Event;
|
|
p_Tgec->h_App = p_FmMacParam->h_App;
|
|
|
|
return p_Tgec;
|
|
}
|