summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c')
-rw-r--r--sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c1268
1 files changed, 1268 insertions, 0 deletions
diff --git a/sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c b/sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c
new file mode 100644
index 0000000..cbe3535
--- /dev/null
+++ b/sys/contrib/ncsw/Peripherals/FM/MAC/tgec.c
@@ -0,0 +1,1268 @@
+/* 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;
+}
OpenPOWER on IntegriCloud