freebsd-dev/sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c
Justin Hibbits 0aeed3e993 Add support for the Freescale dTSEC DPAA-based ethernet controller.
Freescale's QorIQ line includes a new ethernet controller, based on their
Datapath Acceleration Architecture (DPAA).  This uses a combination of a Frame
manager, Buffer manager, and Queue manager to improve performance across all
interfaces by being able to pass data directly between hardware acceleration
interfaces.

As part of this import, Freescale's Netcomm Software (ncsw) driver is imported.
This was an attempt by Freescale to create an OS-agnostic sub-driver for
managing the hardware, using shims to interface to the OS-specific APIs.  This
work was abandoned, and Freescale's primary work is in the Linux driver (dual
BSD/GPL license).  Hence, this was imported directly to sys/contrib, rather than
going through the vendor area.  Going forward, FreeBSD-specific changes may be
made to the ncsw code, diverging from the upstream in potentially incompatible
ways.  An alternative could be to import the Linux driver itself, using the
linuxKPI layer, as that would maintain parity with the vendor-maintained driver.
However, the Linux driver has not been evaluated for reliability yet, and may
have issues with the import, whereas the ncsw-based driver in this commit was
completed by Semihalf 4 years ago, and is very stable.

Other SoC modules based on DPAA, which could be added in the future:
* Security and Encryption engine (SEC4.x, SEC5.x)
* RAID engine

Additional work to be done:
* Implement polling mode
* Test vlan support
* Add support for the Pattern Matching Engine, which can do regular expression
  matching on packets.

This driver has been tested on the P5020 QorIQ SoC.  Others listed in the
dtsec(4) manual page are expected to work as the same DPAA engine is included in
all.

Obtained from:	Semihalf
Relnotes:	Yes
Sponsored by:	Alex Perez/Inertial Computing
2016-02-29 03:38:00 +00:00

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, &ethAddr, 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;
}