summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fman/Peripherals
diff options
context:
space:
mode:
authorMandy Lavi <mandy.lavi@freescale.com>2013-03-24 16:40:18 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-08 23:07:26 (GMT)
commit3cc514986cb4e457458cc826288b6c2107c97907 (patch)
tree2985e48afc5dd20f44d51ef6aafdae917ce2698f /drivers/net/ethernet/freescale/fman/Peripherals
parent5767d52cec831b0e2927d34e91acd738cc1cb0ef (diff)
downloadlinux-fsl-qoriq-3cc514986cb4e457458cc826288b6c2107c97907.tar.xz
fmd: fmd19 integration
Add fmd19 codebase, plus a minimal set of sources from dpaa-eth, necessary for bare compilation Change-Id: I390df8717671204e3d98a987135393bef4534e95 Signed-off-by: Mandy Lavi <mandy.lavi@freescale.com> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/1029 Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com> Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/fman/Peripherals')
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c1192
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile21
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c1513
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h245
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c109
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h45
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c628
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h222
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c119
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h43
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c818
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c149
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c427
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c355
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h102
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c1036
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h104
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c240
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h73
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c1018
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h151
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c139
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h80
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile22
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile19
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h360
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c6940
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h390
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c3263
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h206
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c4193
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h480
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c2114
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h540
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h280
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c1927
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h165
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c457
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h193
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c993
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h104
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c888
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c124
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c5724
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h945
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c754
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c878
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h216
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c857
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h131
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c6162
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h897
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h464
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c175
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h1103
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h90
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h154
61 files changed, 51097 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile
new file mode 100644
index 0000000..bcbc72e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Hc.o
+
+fsl-ncsw-Hc-objs := hc.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c
new file mode 100644
index 0000000..ed3674f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c
@@ -0,0 +1,1192 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "sprint_ext.h"
+#include "string_ext.h"
+
+#include "fm_common.h"
+#include "fm_hc.h"
+
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_dataMemId 0
+
+#define HC_HCOR_OPCODE_PLCR_PRFL 0x0
+#define HC_HCOR_OPCODE_KG_SCM 0x1
+#define HC_HCOR_OPCODE_SYNC 0x2
+#define HC_HCOR_OPCODE_CC 0x3
+#define HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT 0x5
+#define HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT 0x10
+#define HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION 0x11
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT 24
+#define HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT 24
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT 16
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK 0xF
+#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT 24
+#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID 16
+
+#define HC_HCOR_GBL 0x20000000
+
+#define HC_HCOR_KG_SCHEME_COUNTER 0x00000400
+
+#if (DPAA_VERSION == 10)
+#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFF800
+#else
+#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFFE00
+#endif /* (DPAA_VERSION == 10) */
+
+#define SIZE_OF_HC_FRAME_PORT_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdKgPortRegs))
+#define SIZE_OF_HC_FRAME_SCHEME_REGS sizeof(t_HcFrame)
+#define SIZE_OF_HC_FRAME_PROFILES_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdPlcrProfileRegs))
+#define SIZE_OF_HC_FRAME_PROFILE_CNT (sizeof(t_HcFrame)-sizeof(t_FmPcdPlcrProfileRegs)+sizeof(uint32_t))
+#define SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC 16
+
+#define HC_CMD_POOL_SIZE (INTG_MAX_NUM_OF_CORES)
+
+#define BUILD_FD(len) \
+do { \
+ memset(&fmFd, 0, sizeof(t_DpaaFD)); \
+ DPAA_FD_SET_ADDR(&fmFd, p_HcFrame); \
+ DPAA_FD_SET_OFFSET(&fmFd, 0); \
+ DPAA_FD_SET_LENGTH(&fmFd, len); \
+} while (0)
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct t_FmPcdKgPortRegs {
+ volatile uint32_t spReg;
+ volatile uint32_t cppReg;
+} _PackedType t_FmPcdKgPortRegs;
+
+typedef _Packed struct t_HcFrame {
+ volatile uint32_t opcode;
+ volatile uint32_t actionReg;
+ volatile uint32_t extraReg;
+ volatile uint32_t commandSequence;
+ union {
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_scheme_regs schemeRegsWithoutCounter;
+ t_FmPcdPlcrProfileRegs profileRegs;
+ volatile uint32_t singleRegForWrite; /* for writing SP, CPP, profile counter */
+ t_FmPcdKgPortRegs portRegsForRead;
+ volatile uint32_t clsPlanEntries[CLS_PLAN_NUM_PER_GRP];
+ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeout;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeout;
+ } hcSpecificData;
+} _PackedType t_HcFrame;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+typedef struct t_FmHc {
+ t_Handle h_FmPcd;
+ t_Handle h_HcPortDev;
+ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< A callback for enqueuing frames to the QM */
+ t_Handle h_QmArg; /**< A handle to the QM module */
+ uint8_t dataMemId; /**< Memory partition ID for data buffers */
+
+ uint32_t seqNum[HC_CMD_POOL_SIZE]; /* FIFO of seqNum to use when
+ taking buffer */
+ uint32_t nextSeqNumLocation; /* seqNum location in seqNum[] for next buffer */
+ volatile bool enqueued[HC_CMD_POOL_SIZE]; /* HC is active - frame is enqueued
+ and not confirmed yet */
+ t_HcFrame *p_Frm[HC_CMD_POOL_SIZE];
+} t_FmHc;
+
+
+static t_Error FillBufPool(t_FmHc *p_FmHc)
+{
+ uint32_t i;
+
+ ASSERT_COND(p_FmHc);
+
+ for (i = 0; i < HC_CMD_POOL_SIZE; i++)
+ {
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart((sizeof(t_HcFrame) + (16 - (sizeof(t_FmHc) % 16))),
+ p_FmHc->dataMemId,
+ 16);
+#else
+ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart(sizeof(t_HcFrame),
+ p_FmHc->dataMemId,
+ 16);
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+ if (!p_FmHc->p_Frm[i])
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM HC frames!"));
+ }
+
+ /* Initialize FIFO of seqNum to use during GetBuf */
+ for (i = 0; i < HC_CMD_POOL_SIZE; i++)
+ {
+ p_FmHc->seqNum[i] = i;
+ }
+ p_FmHc->nextSeqNumLocation = 0;
+
+ return E_OK;
+}
+
+static __inline__ t_HcFrame * GetBuf(t_FmHc *p_FmHc, uint32_t *p_SeqNum)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmHc);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+
+ if (p_FmHc->nextSeqNumLocation == HC_CMD_POOL_SIZE)
+ {
+ /* No more buffers */
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ return NULL;
+ }
+
+ *p_SeqNum = p_FmHc->seqNum[p_FmHc->nextSeqNumLocation];
+ p_FmHc->nextSeqNumLocation++;
+
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ return p_FmHc->p_Frm[*p_SeqNum];
+}
+
+static __inline__ void PutBuf(t_FmHc *p_FmHc, t_HcFrame *p_Buf, uint32_t seqNum)
+{
+ uint32_t intFlags;
+
+ UNUSED(p_Buf);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ ASSERT_COND(p_FmHc->nextSeqNumLocation);
+ p_FmHc->nextSeqNumLocation--;
+ p_FmHc->seqNum[p_FmHc->nextSeqNumLocation] = seqNum;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+}
+
+static __inline__ t_Error EnQFrm(t_FmHc *p_FmHc, t_DpaaFD *p_FmFd, uint32_t seqNum)
+{
+ t_Error err = E_OK;
+ uint32_t intFlags;
+ uint32_t timeout=100;
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ ASSERT_COND(!p_FmHc->enqueued[seqNum]);
+ p_FmHc->enqueued[seqNum] = TRUE;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ DBG(TRACE, ("Send Hc, SeqNum %d, buff@0x%x, fd offset 0x%x",
+ seqNum,
+ DPAA_FD_GET_ADDR(p_FmFd),
+ DPAA_FD_GET_OFFSET(p_FmFd)));
+ err = p_FmHc->f_QmEnqueue(p_FmHc->h_QmArg, (void *)p_FmFd);
+ if (err)
+ RETURN_ERROR(MINOR, err, ("HC enqueue failed"));
+
+ while (p_FmHc->enqueued[seqNum] && --timeout)
+ XX_UDelay(100);
+
+ if (!timeout)
+ RETURN_ERROR(MINOR, E_TIMEOUT, ("HC Callback, timeout exceeded"));
+
+ return err;
+}
+
+
+t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams)
+{
+ t_FmHc *p_FmHc;
+ t_FmPortParams fmPortParam;
+ t_Error err;
+
+ p_FmHc = (t_FmHc *)XX_Malloc(sizeof(t_FmHc));
+ if (!p_FmHc)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC obj"));
+ return NULL;
+ }
+ memset(p_FmHc,0,sizeof(t_FmHc));
+
+ p_FmHc->h_FmPcd = p_FmHcParams->h_FmPcd;
+ p_FmHc->f_QmEnqueue = p_FmHcParams->params.f_QmEnqueue;
+ p_FmHc->h_QmArg = p_FmHcParams->params.h_QmArg;
+ p_FmHc->dataMemId = DEFAULT_dataMemId;
+
+ err = FillBufPool(p_FmHc);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ if (!FmIsMaster(p_FmHcParams->h_Fm))
+ return (t_Handle)p_FmHc;
+
+ memset(&fmPortParam, 0, sizeof(fmPortParam));
+ fmPortParam.baseAddr = p_FmHcParams->params.portBaseAddr;
+ fmPortParam.portType = e_FM_PORT_TYPE_OH_HOST_COMMAND;
+ fmPortParam.portId = p_FmHcParams->params.portId;
+ fmPortParam.liodnBase = p_FmHcParams->params.liodnBase;
+ fmPortParam.h_Fm = p_FmHcParams->h_Fm;
+
+ fmPortParam.specificParams.nonRxParams.errFqid = p_FmHcParams->params.errFqid;
+ fmPortParam.specificParams.nonRxParams.dfltFqid = p_FmHcParams->params.confFqid;
+ fmPortParam.specificParams.nonRxParams.qmChannel = p_FmHcParams->params.qmChannel;
+
+ p_FmHc->h_HcPortDev = FM_PORT_Config(&fmPortParam);
+ if (!p_FmHc->h_HcPortDev)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM HC port!"));
+ XX_Free(p_FmHc);
+ return NULL;
+ }
+
+ /* final init */
+ err = FM_PORT_Init(p_FmHc->h_HcPortDev);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, ("FM HC port init!"));
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ err = FM_PORT_Enable(p_FmHc->h_HcPortDev);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, ("FM HC port enable!"));
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ return (t_Handle)p_FmHc;
+}
+
+t_Handle FmGcGetHcPortDevH(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc *)h_FmHc;
+
+ return (p_FmHc) ? p_FmHc->h_HcPortDev : NULL;
+}
+
+void FmHcFree(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ int i;
+
+ if (!p_FmHc)
+ return;
+
+ for (i=0; i<HC_CMD_POOL_SIZE; i++)
+ if (p_FmHc->p_Frm[i])
+ XX_FreeSmart(p_FmHc->p_Frm[i]);
+ else
+ break;
+
+ if (p_FmHc->h_HcPortDev)
+ FM_PORT_Free(p_FmHc->h_HcPortDev);
+
+ XX_Free(p_FmHc);
+}
+
+/*****************************************************************************/
+t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc,
+ uint8_t memId)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+
+ p_FmHc->dataMemId = memId;
+
+ for (i=0; i<HC_CMD_POOL_SIZE; i++)
+ if (p_FmHc->p_Frm[i])
+ XX_FreeSmart(p_FmHc->p_Frm[i]);
+
+ return FillBufPool(p_FmHc);
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FmHcDumpRegs(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmHc->h_HcPortDev, E_INVALID_HANDLE);
+
+ return FM_PORT_DumpRegs(p_FmHc->h_HcPortDev);
+
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmHc);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ p_HcFrame = (t_HcFrame *)PTR_MOVE(DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd));
+
+ DBG(TRACE, ("Hc Conf, SeqNum %d, FD@0x%x, fd offset 0x%x",
+ p_HcFrame->commandSequence, DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd)));
+
+ if (!(p_FmHc->enqueued[p_HcFrame->commandSequence]))
+ REPORT_ERROR(MINOR, E_INVALID_FRAME, ("Not an Host-Command frame received!"));
+ else
+ p_FmHc->enqueued[p_HcFrame->commandSequence] = FALSE;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+}
+
+t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc,
+ t_Handle h_Scheme,
+ struct fman_kg_scheme_regs *p_SchemeRegs,
+ bool updateCounter)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t physicalSchemeId;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, updateCounter);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memcpy(&p_HcFrame->hcSpecificData.schemeRegs, p_SchemeRegs, sizeof(struct fman_kg_scheme_regs));
+ if (!updateCounter)
+ {
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv0 = p_SchemeRegs->kgse_dv0;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv1 = p_SchemeRegs->kgse_dv1;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_ccbs = p_SchemeRegs->kgse_ccbs;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mv = p_SchemeRegs->kgse_mv;
+ }
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memset(&p_HcFrame->hcSpecificData.schemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t tmpReg32 = 0;
+ uint32_t seqNum;
+
+ /* Scheme is locked by calling routine */
+ /* WARNING - this lock will not be efficient if other HC routine will attempt to change
+ * "kgse_mode" or "kgse_om" without locking scheme !
+ */
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (!FmPcdKgGetPointedOwners(p_FmHc->h_FmPcd, relativeSchemeId) ||
+ !(FmPcdKgGetRequiredAction(p_FmHc->h_FmPcd, relativeSchemeId) & requiredAction))
+ {
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) &&
+ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_PLCR))
+ {
+ if ((FmPcdKgIsDirectPlcr(p_FmHc->h_FmPcd, relativeSchemeId) == FALSE) ||
+ (FmPcdKgIsDistrOnPlcrProfile(p_FmHc->h_FmPcd, relativeSchemeId) == TRUE))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
+ err = FmPcdPlcrCcGetSetParams(p_FmHc->h_FmPcd, FmPcdKgGetRelativeProfileId(p_FmHc->h_FmPcd, relativeSchemeId), requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else /* From here we deal with KG-Schemes only */
+ {
+ /* Pre change general code */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* specific change */
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) &&
+ ((FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_DONE) &&
+ (FmPcdKgGetDoneAction(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_ENQ_FRAME)))
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ }
+
+ if ((requiredAction & UPDATE_KG_NIA_CC_WA) &&
+ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_CC))
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ tmpReg32 &= ~NIA_FM_CTL_AC_CC;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_FM_CTL_AC_PRE_CC;
+ }
+
+ if (requiredAction & UPDATE_KG_OPT_MODE)
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_om = value;
+
+ if (requiredAction & UPDATE_KG_NIA)
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
+ tmpReg32 |= value;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32;
+ }
+
+ /* Post change general code */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ return E_OK;
+}
+
+uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t retVal;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t seqNum;
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ return 0;
+ }
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ return 0;
+ }
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+ if (err != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+
+ if (!FmPcdKgHwSchemeIsValid(p_HcFrame->hcSpecificData.schemeRegs.kgse_mode))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is invalid"));
+ return 0;
+ }
+
+ retVal = p_HcFrame->hcSpecificData.schemeRegs.kgse_spc;
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ return retVal;
+}
+
+t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ uint32_t seqNum;
+
+ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_COUNTER;
+ /* write counter */
+ p_HcFrame->hcSpecificData.singleRegForWrite = value;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t i;
+ uint32_t seqNum;
+ t_Error err = E_OK;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ for (i = p_Set->baseEntry; i < (p_Set->baseEntry+p_Set->numOfClsPlanEntries); i+=8)
+ {
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memcpy((void*)&p_HcFrame->hcSpecificData.clsPlanEntries, (void *)&p_Set->vectors[i-p_Set->baseEntry], CLS_PLAN_NUM_PER_GRP*sizeof(uint32_t));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t grpId)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+
+ p_ClsPlanSet->baseEntry = FmPcdKgGetClsPlanGrpBase(p_FmHc->h_FmPcd, grpId);
+ p_ClsPlanSet->numOfClsPlanEntries = FmPcdKgGetClsPlanGrpSize(p_FmHc->h_FmPcd, grpId);
+ ASSERT_COND(p_ClsPlanSet->numOfClsPlanEntries <= FM_PCD_MAX_NUM_OF_CLS_PLANS);
+
+ if (FmHcPcdKgSetClsPlan(p_FmHc, p_ClsPlanSet) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ XX_Free(p_ClsPlanSet);
+
+ FmPcdKgDestroyClsPlanGrp(p_FmHc->h_FmPcd, grpId);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams )
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT);
+ memcpy(&p_HcFrame->hcSpecificData.ccCapwapReassmTimeout, p_CcCapwapReassmTimeoutParams, sizeof(t_FmPcdCcCapwapReassmTimeoutParams));
+ p_HcFrame->commandSequence = seqNum;
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION);
+ p_HcFrame->actionReg = (uint32_t)(((fill == TRUE) ? 0 : 1) << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT);
+ p_HcFrame->actionReg |= p_FmPcdCcFragScratchPoolCmdParams->bufferPoolId << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID;
+ if (fill == TRUE)
+ {
+ p_HcFrame->extraReg = p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers;
+ }
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers = p_HcFrame->extraReg;
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return E_OK;
+}
+
+t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT);
+ p_HcFrame->actionReg = (uint32_t)((p_CcIpReassmTimeoutParams->activate ? 0 : 1) << HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT);
+ p_HcFrame->extraReg = (p_CcIpReassmTimeoutParams->tsbs << HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT) | p_CcIpReassmTimeoutParams->iprcpt;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ *p_Result = (uint8_t)
+ ((p_HcFrame->actionReg >> HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT) & HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t tmpReg32 = 0;
+ uint32_t requiredActionTmp, pointedOwnersTmp;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ /* Profile is locked by calling routine */
+ /* WARNING - this lock will not be efficient if other HC routine will attempt to change
+ * "fmpl_pegnia" "fmpl_peynia" or "fmpl_pernia" without locking Profile !
+ */
+
+ requiredActionTmp = FmPcdPlcrGetRequiredAction(p_FmHc->h_FmPcd, absoluteProfileId);
+ pointedOwnersTmp = FmPcdPlcrGetPointedOwners(p_FmHc->h_FmPcd, absoluteProfileId);
+
+ if (!pointedOwnersTmp || !(requiredActionTmp & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ /* first read scheme and check that it is valid */
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegnia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(TRUE, FALSE, FALSE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_peynia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, TRUE, FALSE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pernia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, FALSE, TRUE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ }
+ }
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ uint16_t profileIndx;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ profileIndx = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx);
+ p_HcFrame->extraReg = 0x00008000;
+ memcpy(&p_HcFrame->hcSpecificData.profileRegs, p_PlcrRegs, sizeof(t_FmPcdPlcrProfileRegs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= 0x00008000;
+ p_HcFrame->extraReg = 0x00008000;
+ memset(&p_HcFrame->hcSpecificData.profileRegs, 0, sizeof(t_FmPcdPlcrProfileRegs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value)
+{
+
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildCounterProfileReg(counter);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = value;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t retVal = 0;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ return 0;
+ }
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+ if (err != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegpc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_peypc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perpc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perypc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perrpc;
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return retVal;
+}
+
+t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ /* first read SP register */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PORT_REGS);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* spReg is the first reg, so we can use it both for read and for write */
+ if (add)
+ p_HcFrame->hcSpecificData.portRegsForRead.spReg |= spReg;
+ else
+ p_HcFrame->hcSpecificData.portRegsForRead.spReg &= ~spReg;
+
+ p_HcFrame->actionReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ /* first read SP register */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->hcSpecificData.singleRegForWrite = cppReg;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC);
+ p_HcFrame->actionReg = newAdAddrOffset;
+ p_HcFrame->actionReg |= 0xc0000000;
+ p_HcFrame->extraReg = oldAdAddrOffset;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile
new file mode 100644
index 0000000..a018ab2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-MAC.o
+
+fsl-ncsw-MAC-objs := dtsec.o dtsec_mii_acc.o fm_mac.o tgec.o tgec_mii_acc.o \
+ fman_dtsec.o fman_dtsec_mii_acc.o fman_memac.o \
+ fman_tgec.o fman_crc32.o
+
+ifeq ($(CONFIG_FMAN_T4240),y)
+fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o
+endif
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c
new file mode 100644
index 0000000..e4cb509
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c
@@ -0,0 +1,1513 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 dtsec.c
+
+ @Description FM dTSEC ...
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "xx_ext.h"
+#include "endian_ext.h"
+#include "debug_ext.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec.h"
+
+
+/*****************************************************************************/
+/* Internal routines */
+/*****************************************************************************/
+
+static t_Error CheckInitParameters(t_Dtsec *p_Dtsec)
+{
+ if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds"));
+ if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs"));
+ if (p_Dtsec->addr == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address"));
+ if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) &&
+ p_Dtsec->p_DtsecDriverParam->halfdup_on)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex"));
+ if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode"));
+#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */
+ if (p_Dtsec->p_DtsecDriverParam->rx_preamble)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn"));
+#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
+ if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes"));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on &&
+ (p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable"));
+ if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc )
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept "));
+ if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend > MAX_PACKET_ALIGNMENT)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT ));
+ if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1 > MAX_INTER_PACKET_GAP) ||
+ ((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) ||
+ ((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW ));
+
+ /* If Auto negotiation process is disabled, need to */
+ /* Set up the PHY using the MII Management Interface */
+ if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS));
+ if (!p_Dtsec->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception"));
+ if (!p_Dtsec->f_Event)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event"));
+
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (p_Dtsec->p_DtsecDriverParam->rx_len_check)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(ethAddr, crc);
+
+ crc = GetMirror32(crc);
+
+ return crc;
+}
+
+/* ......................................................................... */
+
+static void UpdateStatistics(t_Dtsec *p_Dtsec)
+{
+ uint32_t car1, car2;
+
+ dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2);
+
+ if (car1)
+ {
+ if (car1 & CAR1_TR64)
+ p_Dtsec->internalStatistics.tr64 += VAL22BIT;
+ if (car1 & CAR1_TR127)
+ p_Dtsec->internalStatistics.tr127 += VAL22BIT;
+ if (car1 & CAR1_TR255)
+ p_Dtsec->internalStatistics.tr255 += VAL22BIT;
+ if (car1 & CAR1_TR511)
+ p_Dtsec->internalStatistics.tr511 += VAL22BIT;
+ if (car1 & CAR1_TRK1)
+ p_Dtsec->internalStatistics.tr1k += VAL22BIT;
+ if (car1 & CAR1_TRMAX)
+ p_Dtsec->internalStatistics.trmax += VAL22BIT;
+ if (car1 & CAR1_TRMGV)
+ p_Dtsec->internalStatistics.trmgv += VAL22BIT;
+ if (car1 & CAR1_RBYT)
+ p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT;
+ if (car1 & CAR1_RPKT)
+ p_Dtsec->internalStatistics.rpkt += VAL22BIT;
+ if (car1 & CAR1_RMCA)
+ p_Dtsec->internalStatistics.rmca += VAL22BIT;
+ if (car1 & CAR1_RBCA)
+ p_Dtsec->internalStatistics.rbca += VAL22BIT;
+ if (car1 & CAR1_RXPF)
+ p_Dtsec->internalStatistics.rxpf += VAL16BIT;
+ if (car1 & CAR1_RALN)
+ p_Dtsec->internalStatistics.raln += VAL16BIT;
+ if (car1 & CAR1_RFLR)
+ p_Dtsec->internalStatistics.rflr += VAL16BIT;
+ if (car1 & CAR1_RCDE)
+ p_Dtsec->internalStatistics.rcde += VAL16BIT;
+ if (car1 & CAR1_RCSE)
+ p_Dtsec->internalStatistics.rcse += VAL16BIT;
+ if (car1 & CAR1_RUND)
+ p_Dtsec->internalStatistics.rund += VAL16BIT;
+ if (car1 & CAR1_ROVR)
+ p_Dtsec->internalStatistics.rovr += VAL16BIT;
+ if (car1 & CAR1_RFRG)
+ p_Dtsec->internalStatistics.rfrg += VAL16BIT;
+ if (car1 & CAR1_RJBR)
+ p_Dtsec->internalStatistics.rjbr += VAL16BIT;
+ if (car1 & CAR1_RDRP)
+ p_Dtsec->internalStatistics.rdrp += VAL16BIT;
+ }
+ if (car2)
+ {
+ if (car2 & CAR2_TFCS)
+ p_Dtsec->internalStatistics.tfcs += VAL12BIT;
+ if (car2 & CAR2_TBYT)
+ p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT;
+ if (car2 & CAR2_TPKT)
+ p_Dtsec->internalStatistics.tpkt += VAL22BIT;
+ if (car2 & CAR2_TMCA)
+ p_Dtsec->internalStatistics.tmca += VAL22BIT;
+ if (car2 & CAR2_TBCA)
+ p_Dtsec->internalStatistics.tbca += VAL22BIT;
+ if (car2 & CAR2_TXPF)
+ p_Dtsec->internalStatistics.txpf += VAL16BIT;
+ if (car2 & CAR2_TDRP)
+ p_Dtsec->internalStatistics.tdrp += VAL16BIT;
+ }
+}
+
+/* .............................................................................. */
+
+static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0);
+
+ return dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
+}
+
+/* .............................................................................. */
+
+static void DtsecIsr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ /* do not handle MDIO events */
+ event = dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)));
+
+ event &= dtsec_get_interrupt_mask(p_DtsecMemMap);
+
+ dtsec_ack_event(p_DtsecMemMap, event);
+
+ if (event & DTSEC_IMASK_BREN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX);
+ if (event & DTSEC_IMASK_RXCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL);
+ if (event & DTSEC_IMASK_MSROEN)
+ UpdateStatistics(p_Dtsec);
+ if (event & DTSEC_IMASK_GTSCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
+ if (event & DTSEC_IMASK_BTEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX);
+ if (event & DTSEC_IMASK_TXCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL);
+ if (event & DTSEC_IMASK_TXEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR);
+ if (event & DTSEC_IMASK_LCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL);
+ if (event & DTSEC_IMASK_CRLEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT);
+ if (event & DTSEC_IMASK_XFUNEN)
+ {
+#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ {
+ uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i;
+ /* a. Write 0x00E0_0C00 to DTSEC_ID */
+ /* This is a read only regidter */
+
+ /* b. Read and save the value of TPKT */
+ tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt);
+
+ /* c. Read the register at dTSEC address offset 0x32C */
+ tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
+
+ /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */
+ if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F))
+ {
+ /* If they are not equal, save the value of this register and wait for at least
+ * MAXFRM*16 ns */
+ XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1)));
+ }
+
+ /* e. Read and save TPKT again and read the register at dTSEC address offset
+ 0x32C again*/
+ tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt);
+ tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
+
+ /* f. Compare the value of TPKT saved in step b to value read in step e. Also
+ compare bits [9:15] of the register at offset 0x32C saved in step d to the value
+ of bits [9:15] saved in step e. If the two registers values are unchanged, then
+ the transmit portion of the dTSEC controller is locked up and the user should
+ proceed to the recover sequence. */
+ if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000)))
+ {
+ /* recover sequence */
+
+ /* a.Write a 1 to RCTRL[GRS]*/
+
+ WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS);
+
+ /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */
+ for (i = 0 ; i < 100 ; i++ )
+ {
+ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
+ break;
+ XX_UDelay(1);
+ }
+ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
+ WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN);
+ else
+ DBG(INFO,("Rx lockup due to dTSEC Tx lockup"));
+
+ /* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/
+ FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId);
+
+ /* d.Wait 4 Tx clocks (32 ns) */
+ XX_UDelay(1);
+
+ /* e.Write a 0 to bit n of FM_RSTC. */
+ /* cleared by FMAN */
+ }
+ }
+#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
+
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN);
+ }
+ if (event & DTSEC_IMASK_MAGEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT);
+ if (event & DTSEC_IMASK_GRSCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
+ if (event & DTSEC_IMASK_TDPEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR);
+ if (event & DTSEC_IMASK_RDPEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR);
+
+ /* - masked interrupts */
+ ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN));
+ ASSERT_COND(!(event & DTSEC_IMASK_IFERREN));
+}
+
+static void DtsecMdioIsr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ event = GET_UINT32(p_DtsecMemMap->ievent);
+ /* handle only MDIO events */
+ event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN);
+ if (event)
+ {
+ event &= GET_UINT32(p_DtsecMemMap->imask);
+
+ WRITE_UINT32(p_DtsecMemMap->ievent, event);
+
+ if (event & DTSEC_IMASK_MMRDEN)
+ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET);
+ if (event & DTSEC_IMASK_MMWREN)
+ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET);
+ }
+}
+
+static void Dtsec1588Isr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ if (p_Dtsec->ptpTsuEnabled)
+ {
+ event = dtsec_check_and_clear_tmr_event(p_DtsecMemMap);
+
+ if (event)
+ {
+ ASSERT_COND(event & TMR_PEVENT_TSRE);
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR);
+ }
+ }
+}
+
+/* ........................................................................... */
+
+static void FreeInitResources(t_Dtsec *p_Dtsec)
+{
+ /*TODO - need to ask why with mdioIrq != 0*/
+ if ((p_Dtsec->mdioIrq != 0) && (p_Dtsec->mdioIrq != NO_IRQ))
+ {
+ XX_DisableIntr(p_Dtsec->mdioIrq);
+ XX_FreeIntr(p_Dtsec->mdioIrq);
+ }
+ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR);
+ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL);
+
+ /* release the driver's group hash table */
+ FreeHashTable(p_Dtsec->p_MulticastAddrHash);
+ p_Dtsec->p_MulticastAddrHash = NULL;
+
+ /* release the driver's individual hash table */
+ FreeHashTable(p_Dtsec->p_UnicastAddrHash);
+ p_Dtsec->p_UnicastAddrHash = NULL;
+}
+
+/* ........................................................................... */
+
+static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode)
+{
+ struct dtsec_regs *p_MemMap;
+
+ ASSERT_COND(p_Dtsec);
+
+ p_MemMap = p_Dtsec->p_MemMap;
+ ASSERT_COND(p_MemMap);
+
+ /* Assert the graceful transmit stop bit */
+ if (mode & e_COMM_MODE_RX)
+ {
+ dtsec_stop_rx(p_MemMap);
+
+#ifdef FM_GRS_ERRATA_DTSEC_A002
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ XX_UDelay(100);
+#else /* FM_GRS_ERRATA_DTSEC_A002 */
+#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+ XX_UDelay(10);
+#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
+#endif /* FM_GRS_ERRATA_DTSEC_A002 */
+ }
+
+ if (mode & e_COMM_MODE_TX)
+#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ DBG(INFO, ("GTS not supported due to DTSEC_A004 errata."));
+#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+ DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata."));
+#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+ dtsec_stop_tx(p_MemMap);
+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode)
+{
+ struct dtsec_regs *p_MemMap;
+
+ ASSERT_COND(p_Dtsec);
+ p_MemMap = p_Dtsec->p_MemMap;
+ ASSERT_COND(p_MemMap);
+
+ /* clear the graceful receive stop bit */
+ if (mode & e_COMM_MODE_TX)
+ dtsec_start_tx(p_MemMap);
+
+ if (mode & e_COMM_MODE_RX)
+ dtsec_start_rx(p_MemMap);
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* dTSEC Configs modification functions */
+/*****************************************************************************/
+
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal)
+{
+
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->loopback = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal;
+
+ return E_OK;
+}
+
+static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
+ {
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Dtsec->exceptions |= bitMask;
+ else
+ p_Dtsec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ else
+ {
+ if (!p_Dtsec->ptpTsuEnabled)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
+ switch (exception){
+ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ p_Dtsec->enTsuErrExeption = TRUE;
+ else
+ p_Dtsec->enTsuErrExeption = FALSE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ }
+ return E_OK;
+}
+/*****************************************************************************/
+/* dTSEC Run Time API functions */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ dtsec_enable(p_Dtsec->p_MemMap,
+ (bool)!!(mode & e_COMM_MODE_RX),
+ (bool)!!(mode & e_COMM_MODE_TX));
+
+ GracefulRestart(p_Dtsec, mode);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ GracefulStop(p_Dtsec, mode);
+
+ dtsec_disable(p_Dtsec->p_MemMap,
+ (bool)!!(mode & e_COMM_MODE_RX),
+ (bool)!!(mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ UNUSED(priority);UNUSED(threshTime);
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ if (pauseTime <= 320)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("This pause-time value of %d is illegal due to errata dTSEC-A003!"
+ " value should be greater than 320."));
+#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
+
+ dtsec_set_tx_pause_time(p_Dtsec->p_MemMap, pauseTime);
+ return E_OK;
+}
+
+/* .............................................................................. */
+/* backward compatibility. will be removed in the future. */
+static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)
+{
+ return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ bool accept_pause = !en;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->ptpTsuEnabled = TRUE;
+ dtsec_set_ts(p_Dtsec->p_MemMap, TRUE);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->ptpTsuEnabled = FALSE;
+ dtsec_set_ts(p_Dtsec->p_MemMap, FALSE);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_regs *p_DtsecMemMap;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled"));
+
+ memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics));
+
+ if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS)
+ {
+ p_Statistics->eStatPkts64 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64)
+ + p_Dtsec->internalStatistics.tr64;
+ p_Statistics->eStatPkts65to127 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127)
+ + p_Dtsec->internalStatistics.tr127;
+ p_Statistics->eStatPkts128to255 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255)
+ + p_Dtsec->internalStatistics.tr255;
+ p_Statistics->eStatPkts256to511 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511)
+ + p_Dtsec->internalStatistics.tr511;
+ p_Statistics->eStatPkts512to1023 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K)
+ + p_Dtsec->internalStatistics.tr1k;
+ p_Statistics->eStatPkts1024to1518 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX)
+ + p_Dtsec->internalStatistics.trmax;
+ p_Statistics->eStatPkts1519to1522 = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV)
+ + p_Dtsec->internalStatistics.trmgv;
+
+ /* MIB II */
+ p_Statistics->ifInOctets = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT)
+ + p_Dtsec->internalStatistics.rbyt;
+ p_Statistics->ifInPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT)
+ + p_Dtsec->internalStatistics.rpkt;
+ p_Statistics->ifInUcastPkts = 0;
+ p_Statistics->ifInMcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA)
+ + p_Dtsec->internalStatistics.rmca;
+ p_Statistics->ifInBcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA)
+ + p_Dtsec->internalStatistics.rbca;
+ p_Statistics->ifOutOctets = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT)
+ + p_Dtsec->internalStatistics.tbyt;
+ p_Statistics->ifOutPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT)
+ + p_Dtsec->internalStatistics.tpkt;
+ p_Statistics->ifOutUcastPkts = 0;
+ p_Statistics->ifOutMcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA)
+ + p_Dtsec->internalStatistics.tmca;
+ p_Statistics->ifOutBcastPkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA)
+ + p_Dtsec->internalStatistics.tbca;
+ }
+
+ p_Statistics->eStatFragments = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG)
+ + p_Dtsec->internalStatistics.rfrg;
+ p_Statistics->eStatJabbers = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR)
+ + p_Dtsec->internalStatistics.rjbr;
+ p_Statistics->eStatsDropEvents = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP)
+ + p_Dtsec->internalStatistics.rdrp;
+ p_Statistics->eStatCRCAlignErrors = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN)
+ + p_Dtsec->internalStatistics.raln;
+ p_Statistics->eStatUndersizePkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND)
+ + p_Dtsec->internalStatistics.rund;
+ p_Statistics->eStatOversizePkts = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR)
+ + p_Dtsec->internalStatistics.rovr;
+ p_Statistics->reStatPause = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF)
+ + p_Dtsec->internalStatistics.rxpf;
+ p_Statistics->teStatPause = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF)
+ + p_Dtsec->internalStatistics.txpf;
+ p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents;
+ p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors
+ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr
+ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde
+ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse;
+
+ p_Statistics->ifOutDiscards = dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP)
+ + p_Dtsec->internalStatistics.tdrp;
+ p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards /**< Number of frames transmitted with error: */
+ + dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS)
+ + p_Dtsec->internalStatistics.tfcs;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ /* Initialize MAC Station Address registers (1 & 2) */
+ /* Station address have to be swapped (big endian to little endian */
+ p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);
+ dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecResetCounters (t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ /* clear HW counters */
+ dtsec_reset_stat(p_Dtsec->p_MemMap);
+
+ /* clear SW counters holding carries */
+ memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ 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 < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ if (p_Dtsec->indAddrRegUsed[paddrNum])
+ if (p_Dtsec->paddr[paddrNum] == ethAddr)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+
+ /* Find first unused PADDR */
+ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ if (!(p_Dtsec->indAddrRegUsed[paddrNum]))
+ {
+ /* mark this PADDR as used */
+ p_Dtsec->indAddrRegUsed[paddrNum] = TRUE;
+ /* store address */
+ p_Dtsec->paddr[paddrNum] = ethAddr;
+
+ /* put in hardware */
+ dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(&ethAddr), paddrNum);
+ p_Dtsec->numOfIndAddrInRegs++;
+
+ return E_OK;
+ }
+
+ /* No free PADDR */
+ RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* Find used PADDR containing this address */
+ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if ((p_Dtsec->indAddrRegUsed[paddrNum]) &&
+ (p_Dtsec->paddr[paddrNum] == ethAddr))
+ {
+ /* mark this PADDR as not used */
+ p_Dtsec->indAddrRegUsed[paddrNum] = FALSE;
+ /* clear in hardware */
+ dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum);
+ p_Dtsec->numOfIndAddrInRegs--;
+
+ return E_OK;
+ }
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_EthHashEntry *p_HashEntry;
+ uint64_t ethAddr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ ghtx = (bool)((dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
+ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
+
+ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
+
+ crc = GetMacAddrHashCode(ethAddr);
+
+ /* considering the 9 highest order bits in crc H[8:0]:
+ * if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
+ * and H[5:1] (next 5 bits) identify the hash bit
+ * if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
+ * and H[4:0] (next 5 bits) identify the hash bit.
+ *
+ * In bucket index output the low 5 bits identify the hash register bit,
+ * while the higher 4 bits identify the hash register
+ */
+
+ if (ghtx)
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE);
+
+ /* 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);
+
+ if (ethAddr & MAC_GROUP_ADDRESS)
+ /* Group Address */
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]));
+ else
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_List *p_Pos;
+ t_EthHashEntry *p_HashEntry = NULL;
+ uint64_t ethAddr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ ghtx = (bool)((dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
+ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
+
+ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
+
+ crc = GetMacAddrHashCode(ethAddr);
+
+ if (ghtx)
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ if (ethAddr & MAC_GROUP_ADDRESS)
+ {
+ /* Group Address */
+ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
+ {
+ 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_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
+ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
+ }
+ else
+ {
+ /* Individual Address */
+ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
+ {
+ 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_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
+ dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
+ }
+
+ /* address does not exist */
+ ASSERT_COND(p_HashEntry != NULL);
+
+ return E_OK;
+}
+
+void DtsecRestartTbiAN(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ if (!p_Dtsec)
+ return;
+
+ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0,
+ PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal);
+ dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->statisticsLevel = statisticsLevel;
+
+ err = (t_Error)dtsec_set_stat_level(p_Dtsec->p_MemMap,
+ (enum mac_stat_level)statisticsLevel);
+ if (err != E_OK)
+ return err;
+
+ switch (statisticsLevel)
+ {
+ case (e_FM_MAC_NONE_STATISTICS):
+ p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN;
+ break;
+ case (e_FM_MAC_PARTIAL_STATISTICS):
+ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
+ break;
+ case (e_FM_MAC_FULL_STATISTICS):
+ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_Error err;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed);
+ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
+ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
+ p_Dtsec->halfDuplex = !fullDuplex;
+
+ err = (t_Error)dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex);
+
+ if (err == E_CONFLICT)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode"));
+
+ return err;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint16_t tmpReg16;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16);
+ tmpReg16 |= (PHY_CR_RESET_AN);
+ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16);
+
+ return E_OK;
+}
+
+/*************************************************************************************/
+/* .............................................................................. */
+
+static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ *macId = p_Dtsec->macId;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ *macVersion = dtsec_get_revision(p_Dtsec->p_MemMap);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
+ {
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Dtsec->exceptions |= bitMask;
+ else
+ p_Dtsec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ if (enable)
+ dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask);
+ else
+ dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask);
+ }
+ else
+ {
+ if (!p_Dtsec->ptpTsuEnabled)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
+ switch (exception)
+ {
+ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ {
+ p_Dtsec->enTsuErrExeption = TRUE;
+ dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap);
+ } else {
+ p_Dtsec->enTsuErrExeption = FALSE;
+ dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ }
+
+ return E_OK;
+}
+
+
+
+/* ........................................................................... */
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static t_Error DtsecDumpRegs(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_Dtsec->p_MemMap)
+ {
+
+ DUMP_TITLE(p_Dtsec->p_MemMap, ("dTSEC %d: ", p_Dtsec->macId));
+ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id);
+ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id2);
+ DUMP_VAR(p_Dtsec->p_MemMap, ievent);
+ DUMP_VAR(p_Dtsec->p_MemMap, imask);
+ DUMP_VAR(p_Dtsec->p_MemMap, ecntrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, ptv);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pevent);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pemask);
+ DUMP_VAR(p_Dtsec->p_MemMap, tctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, rctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, maccfg1);
+ DUMP_VAR(p_Dtsec->p_MemMap, maccfg2);
+ DUMP_VAR(p_Dtsec->p_MemMap, ipgifg);
+ DUMP_VAR(p_Dtsec->p_MemMap, hafdup);
+ DUMP_VAR(p_Dtsec->p_MemMap, maxfrm);
+
+ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr1);
+ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr2);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ {
+ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match1);
+ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match2);
+ }
+ DUMP_VAR(p_Dtsec->p_MemMap, car1);
+ DUMP_VAR(p_Dtsec->p_MemMap, car2);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+/*****************************************************************************/
+/* dTSEC Init & Free API */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+static t_Error DtsecInit(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_cfg *p_DtsecDriverParam;
+ t_Error err;
+ uint16_t maxFrmLn;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ t_EnetAddr ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo);
+ CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters);
+
+ p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam;
+ p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on;
+
+ enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
+ MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr);
+
+ err = (t_Error)dtsec_init(p_Dtsec->p_MemMap,
+ p_DtsecDriverParam,
+ enet_interface,
+ enet_speed,
+ (uint8_t*)ethAddr,
+ p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev,
+ p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev,
+ p_Dtsec->exceptions);
+ if (err)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode"));
+ }
+
+ DTSEC_MII_Init(h_Dtsec);
+
+ if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII)
+ {
+ uint16_t tmpReg16;
+
+ /* Configure the TBI PHY Control Register */
+ tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
+
+ tmpReg16 = PHY_TBICON_CLK_SEL;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
+
+ tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
+
+ if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX)
+ tmpReg16 = PHY_TBIANA_1000X;
+ else
+ tmpReg16 = PHY_TBIANA_SGMII;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16);
+
+ tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
+ }
+
+ /* Max Frame Length */
+ maxFrmLn = dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
+ err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G,
+ p_Dtsec->fmMacControllerDriver.macId, maxFrmLn);
+
+ p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE);
+ if (!p_Dtsec->p_MulticastAddrHash) {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED"));
+ }
+
+ p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Dtsec->p_UnicastAddrHash)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED"));
+ }
+
+ /* register err intr handler for dtsec to FPM (err)*/
+ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
+ e_FM_MOD_1G_MAC,
+ p_Dtsec->macId,
+ e_FM_INTR_TYPE_ERR,
+ DtsecIsr,
+ p_Dtsec);
+ /* register 1588 intr handler for TMR to FPM (normal)*/
+ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
+ e_FM_MOD_1G_MAC,
+ p_Dtsec->macId,
+ e_FM_INTR_TYPE_NORMAL,
+ Dtsec1588Isr,
+ p_Dtsec);
+ /* register normal intr handler for dtsec to main interrupt controller. */
+ if (p_Dtsec->mdioIrq != NO_IRQ)
+ {
+ XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec);
+ XX_EnableIntr(p_Dtsec->mdioIrq);
+ }
+
+ XX_Free(p_DtsecDriverParam);
+ p_Dtsec->p_DtsecDriverParam = NULL;
+
+ err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS);
+ if (err)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, err, ("Undefined statistics level"));
+ }
+
+ return E_OK;
+}
+
+/* ........................................................................... */
+
+static t_Error DtsecFree(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+
+ FreeInitResources(p_Dtsec);
+
+ if (p_Dtsec->p_DtsecDriverParam)
+ {
+ XX_Free(p_Dtsec->p_DtsecDriverParam);
+ p_Dtsec->p_DtsecDriverParam = NULL;
+ }
+ XX_Free (h_Dtsec);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
+{
+ p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit;
+ p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = DtsecConfigPadAndCrc;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = DtsecConfigHalfDuplex;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = DtsecConfigLengthCheck;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr = DtsecConfigTbiPhyAddr;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigException = DtsecConfigException;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable;
+ p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = DtsecSetPromiscuous;
+ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = DtsecAdjustLink;
+ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = DtsecRestartAutoneg;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp;
+ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause;
+ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause;
+
+ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters;
+ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics;
+
+ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = DtsecModifyMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = DtsecAddHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = DtsecDelHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = DtsecAddExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = DtsecDelExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_GetId = DtsecGetId;
+ p_FmMacControllerDriver->f_FM_MAC_GetVersion = DtsecGetVersion;
+ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = DtsecGetMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg;
+ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = DtsecDumpRegs;
+#endif /* (defined(DEBUG_ERRORS) && ... */
+}
+
+
+/*****************************************************************************/
+/* dTSEC Config Main Entry */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam)
+{
+ t_Dtsec *p_Dtsec;
+ struct dtsec_cfg *p_DtsecDriverParam;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
+
+ baseAddr = p_FmMacParam->baseAddr;
+
+ /* allocate memory for the UCC GETH data structure. */
+ p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec));
+ if (!p_Dtsec)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure"));
+ return NULL;
+ }
+ memset(p_Dtsec, 0, sizeof(t_Dtsec));
+ InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver);
+
+ /* allocate memory for the dTSEC driver parameters data structure. */
+ p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg));
+ if (!p_DtsecDriverParam)
+ {
+ XX_Free(p_Dtsec);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters"));
+ return NULL;
+ }
+ memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam;
+
+ dtsec_defconfig(p_DtsecDriverParam);
+
+ p_Dtsec->p_MemMap = (struct dtsec_regs *)UINT_TO_PTR(baseAddr);
+ p_Dtsec->p_MiiMemMap = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET);
+ p_Dtsec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+ p_Dtsec->enetMode = p_FmMacParam->enetMode;
+ p_Dtsec->macId = p_FmMacParam->macId;
+ p_Dtsec->exceptions = DEFAULT_exceptions;
+ p_Dtsec->mdioIrq = p_FmMacParam->mdioIrq;
+ p_Dtsec->f_Exception = p_FmMacParam->f_Exception;
+ p_Dtsec->f_Event = p_FmMacParam->f_Event;
+ p_Dtsec->h_App = p_FmMacParam->h_App;
+ p_Dtsec->ptpTsuEnabled = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en;
+ p_Dtsec->enTsuErrExeption = p_Dtsec->p_DtsecDriverParam->ptp_exception_en;
+ p_Dtsec->tbi_phy_addr = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr;
+
+ return p_Dtsec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h
new file mode 100644
index 0000000..01296dd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 dtsec.h
+
+ @Description FM dTSEC ...
+*//***************************************************************************/
+#ifndef __DTSEC_H
+#define __DTSEC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "enet_ext.h"
+
+#include "dtsec_mii_acc.h"
+#include "fm_mac.h"
+
+
+#define DEFAULT_exceptions \
+ ((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_1G_BAB_RX: \
+ bitMask = DTSEC_IMASK_BREN; break; \
+ case e_FM_MAC_EX_1G_RX_CTL: \
+ bitMask = DTSEC_IMASK_RXCEN; break; \
+ case e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: \
+ bitMask = DTSEC_IMASK_GTSCEN ; break; \
+ case e_FM_MAC_EX_1G_BAB_TX: \
+ bitMask = DTSEC_IMASK_BTEN ; break; \
+ case e_FM_MAC_EX_1G_TX_CTL: \
+ bitMask = DTSEC_IMASK_TXCEN ; break; \
+ case e_FM_MAC_EX_1G_TX_ERR: \
+ bitMask = DTSEC_IMASK_TXEEN ; break; \
+ case e_FM_MAC_EX_1G_LATE_COL: \
+ bitMask = DTSEC_IMASK_LCEN ; break; \
+ case e_FM_MAC_EX_1G_COL_RET_LMT: \
+ bitMask = DTSEC_IMASK_CRLEN ; break; \
+ case e_FM_MAC_EX_1G_TX_FIFO_UNDRN: \
+ bitMask = DTSEC_IMASK_XFUNEN ; break; \
+ case e_FM_MAC_EX_1G_MAG_PCKT: \
+ bitMask = DTSEC_IMASK_MAGEN ; break; \
+ case e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET: \
+ bitMask = DTSEC_IMASK_MMRDEN; break; \
+ case e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET: \
+ bitMask = DTSEC_IMASK_MMWREN ; break; \
+ case e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: \
+ bitMask = DTSEC_IMASK_GRSCEN; break; \
+ case e_FM_MAC_EX_1G_TX_DATA_ERR: \
+ bitMask = DTSEC_IMASK_TDPEEN; break; \
+ case e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL: \
+ bitMask = DTSEC_IMASK_MSROEN ; break; \
+ default: bitMask = 0;break;}
+
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+
+/********************* From mac ext ******************************************/
+typedef uint32_t t_ErrorDisable;
+
+#define ERROR_DISABLE_TRANSMIT 0x00400000
+#define ERROR_DISABLE_LATE_COLLISION 0x00040000
+#define ERROR_DISABLE_COLLISION_RETRY_LIMIT 0x00020000
+#define ERROR_DISABLE_TxFIFO_UNDERRUN 0x00010000
+#define ERROR_DISABLE_TxABORT 0x00008000
+#define ERROR_DISABLE_INTERFACE 0x00004000
+#define ERROR_DISABLE_TxDATA_PARITY 0x00000002
+#define ERROR_DISABLE_RxDATA_PARITY 0x00000001
+
+/*****************************************************************************/
+#define DTSEC_NUM_OF_PADDRS 15 /* number of pattern match registers (entries) */
+
+#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */
+
+#define HASH_TABLE_SIZE 256 /* Hash table size (= 32 bits * 8 regs) */
+
+#define HASH_TABLE_SIZE 256 /* Hash table size (32 bits * 8 regs) */
+#define EXTENDED_HASH_TABLE_SIZE 512 /* Extended Hash table size (32 bits * 16 regs) */
+
+#define DTSEC_TO_MII_OFFSET 0x1000 /* number of pattern match registers (entries) */
+
+#define MAX_PHYS 32 /* maximum number of phys */
+
+#define VAL32BIT 0x100000000LL
+#define VAL22BIT 0x00400000
+#define VAL16BIT 0x00010000
+#define VAL12BIT 0x00001000
+
+/* PHY Control Register */
+#define PHY_CR_PHY_RESET 0x8000
+#define PHY_CR_LOOPBACK 0x4000
+#define PHY_CR_SPEED0 0x2000
+#define PHY_CR_ANE 0x1000
+#define PHY_CR_RESET_AN 0x0200
+#define PHY_CR_FULLDUPLEX 0x0100
+#define PHY_CR_SPEED1 0x0040
+
+#define PHY_TBICON_SRESET 0x8000
+#define PHY_TBICON_CLK_SEL 0x0020
+
+#define PHY_TBIANA_SGMII 0x4001
+#define PHY_TBIANA_1000X 0x01a0
+
+
+/* CAR1/2 bits */
+#define CAR1_TR64 0x80000000
+#define CAR1_TR127 0x40000000
+#define CAR1_TR255 0x20000000
+#define CAR1_TR511 0x10000000
+#define CAR1_TRK1 0x08000000
+#define CAR1_TRMAX 0x04000000
+#define CAR1_TRMGV 0x02000000
+
+#define CAR1_RBYT 0x00010000
+#define CAR1_RPKT 0x00008000
+#define CAR1_RMCA 0x00002000
+#define CAR1_RBCA 0x00001000
+#define CAR1_RXPF 0x00000400
+#define CAR1_RALN 0x00000100
+#define CAR1_RFLR 0x00000080
+#define CAR1_RCDE 0x00000040
+#define CAR1_RCSE 0x00000020
+#define CAR1_RUND 0x00000010
+#define CAR1_ROVR 0x00000008
+#define CAR1_RFRG 0x00000004
+#define CAR1_RJBR 0x00000002
+#define CAR1_RDRP 0x00000001
+
+#define CAR2_TFCS 0x00040000
+#define CAR2_TBYT 0x00002000
+#define CAR2_TPKT 0x00001000
+#define CAR2_TMCA 0x00000800
+#define CAR2_TBCA 0x00000400
+#define CAR2_TXPF 0x00000200
+#define CAR2_TDRP 0x00000001
+
+typedef struct t_InternalStatistics
+{
+ uint64_t tr64;
+ uint64_t tr127;
+ uint64_t tr255;
+ uint64_t tr511;
+ uint64_t tr1k;
+ uint64_t trmax;
+ uint64_t trmgv;
+ uint64_t rfrg;
+ uint64_t rjbr;
+ uint64_t rdrp;
+ uint64_t raln;
+ uint64_t rund;
+ uint64_t rovr;
+ uint64_t rxpf;
+ uint64_t txpf;
+ uint64_t rbyt;
+ uint64_t rpkt;
+ uint64_t rmca;
+ uint64_t rbca;
+ uint64_t rflr;
+ uint64_t rcde;
+ uint64_t rcse;
+ uint64_t tbyt;
+ uint64_t tpkt;
+ uint64_t tmca;
+ uint64_t tbca;
+ uint64_t tdrp;
+ uint64_t tfcs;
+} t_InternalStatistics;
+
+typedef struct {
+ t_FmMacControllerDriver fmMacControllerDriver;
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct dtsec_regs *p_MemMap; /**< pointer to dTSEC memory mapped registers. */
+ struct dtsec_mii_reg *p_MiiMemMap; /**< pointer to dTSEC MII memory mapped registers. */
+ uint64_t addr; /**< MAC address of device; */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[DTSEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[DTSEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ bool halfDuplex;
+ t_InternalStatistics internalStatistics;
+ t_EthHash *p_MulticastAddrHash; /* pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /* pointer to driver's individual address hash table */
+ uint8_t macId;
+ uint8_t tbi_phy_addr;
+ uint32_t exceptions;
+ bool ptpTsuEnabled;
+ bool enTsuErrExeption;
+ e_FmMacStatisticsLevel statisticsLevel;
+ struct dtsec_cfg *p_DtsecDriverParam;
+} t_Dtsec;
+
+
+#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c
new file mode 100644
index 0000000..371e1f9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 dtsec_mii_acc.c
+
+ @Description FM dtsec MII register access MAC ...
+*//***************************************************************************/
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+
+/*****************************************************************************/
+t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_mii_reg *miiregs;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ miiregs = p_Dtsec->p_MiiMemMap;
+
+ err = (t_Error)dtsec_mii_write_reg(miiregs, phyAddr, reg, data);
+
+ return err;
+}
+
+/*****************************************************************************/
+t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_mii_reg *miiregs;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ miiregs = p_Dtsec->p_MiiMemMap;
+
+ err = (t_Error)dtsec_mii_read_reg(miiregs, phyAddr, reg, p_Data);
+
+ if (*p_Data == 0xffff)
+ RETURN_ERROR(MINOR, E_NO_DEVICE,
+ ("Read wrong data (0xffff): phyAddr 0x%x, reg 0x%x",
+ phyAddr, reg));
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return err;
+}
+
+t_Error DTSEC_MII_Init(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_mii_reg *miiregs;
+ uint16_t dtsec_freq;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ miiregs = p_Dtsec->p_MiiMemMap;
+ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1);
+
+ dtsec_mii_init(miiregs, dtsec_freq);
+
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h
new file mode 100644
index 0000000..d5dd39a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __DTSEC_MII_ACC_H
+#define __DTSEC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+t_Error DTSEC_MII_Init(t_Handle h_Dtsec);
+
+
+#endif /* __DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c
new file mode 100644
index 0000000..e2deaa2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_mac.c
+
+ @Description FM MAC ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "error_ext.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_mac.h"
+
+
+/* ......................................................................... */
+
+t_Handle FM_MAC_Config (t_FmMacParams *p_FmMacParam)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_INVALID_HANDLE, NULL);
+
+#if (DPAA_VERSION == 10)
+ if (ENET_SPEED_FROM_MODE(p_FmMacParam->enetMode) < e_ENET_SPEED_10000)
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)DTSEC_Config(p_FmMacParam);
+ else
+#if FM_MAX_NUM_OF_10G_MACS > 0
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)TGEC_Config(p_FmMacParam);
+#else
+ p_FmMacControllerDriver = NULL;
+#endif /* FM_MAX_NUM_OF_10G_MACS > 0 */
+#else
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)MEMAC_Config(p_FmMacParam);
+#endif /* (DPAA_VERSION == 10) */
+
+ if (!p_FmMacControllerDriver)
+ return NULL;
+
+ p_FmMacControllerDriver->h_Fm = p_FmMacParam->h_Fm;
+ p_FmMacControllerDriver->enetMode = p_FmMacParam->enetMode;
+ p_FmMacControllerDriver->macId = p_FmMacParam->macId;
+ p_FmMacControllerDriver->resetOnInit = DEFAULT_resetOnInit;
+
+ if ((p_FmMacControllerDriver->clkFreq = FmGetClockFreq(p_FmMacControllerDriver->h_Fm)) == 0)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Can't get clock for MAC!"));
+ return NULL;
+ }
+
+ return (t_Handle)p_FmMacControllerDriver;
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Init (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->resetOnInit &&
+ !p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit &&
+ (FmResetMac(p_FmMacControllerDriver->h_Fm,
+ ((ENET_INTERFACE_FROM_MODE(p_FmMacControllerDriver->enetMode) == e_ENET_IF_XGMII) ?
+ e_FM_MAC_10G : e_FM_MAC_1G),
+ p_FmMacControllerDriver->macId) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't reset MAC!"));
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Init)
+ return p_FmMacControllerDriver->f_FM_MAC_Init(h_FmMac);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Free (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Free)
+ return p_FmMacControllerDriver->f_FM_MAC_Free(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigResetOnInit (t_Handle h_FmMac, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit(h_FmMac, enable);
+
+ p_FmMacControllerDriver->resetOnInit = enable;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigLoopback (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigMaxFrameLength (t_Handle h_FmMac, uint16_t newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength(h_FmMac, newVal);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigWan (t_Handle h_FmMac, bool flag)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigWan)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigWan(h_FmMac, flag);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigPadAndCrc (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigHalfDuplex (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigTbiPhyAddr (t_Handle h_FmMac, uint8_t newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigLengthCheck (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigException (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigException)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigException(h_FmMac, ex, enable);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+
+/*****************************************************************************/
+/* Run Time Control */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Enable (t_Handle h_FmMac, e_CommMode mode)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Enable)
+ return p_FmMacControllerDriver->f_FM_MAC_Enable(h_FmMac, mode);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Disable (t_Handle h_FmMac, e_CommMode mode)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Disable)
+ return p_FmMacControllerDriver->f_FM_MAC_Disable(h_FmMac, mode);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Enable1588TimeStamp (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp)
+ return p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Disable1588TimeStamp (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp)
+ return p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac,
+ uint16_t pauseTime)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames(h_FmMac,
+ pauseTime);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames(h_FmMac,
+ priority,
+ pauseTime,
+ threshTime);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetRxIgnorePauseFrames (t_Handle h_FmMac, bool en)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames(h_FmMac, en);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ResetCounters (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ResetCounters)
+ return p_FmMacControllerDriver->f_FM_MAC_ResetCounters(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetException)
+ return p_FmMacControllerDriver->f_FM_MAC_SetException(h_FmMac, ex, enable);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetStatistics (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetStatistics)
+ return p_FmMacControllerDriver->f_FM_MAC_SetStatistics(h_FmMac, statisticsLevel);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetStatistics (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetStatistics)
+ return p_FmMacControllerDriver->f_FM_MAC_GetStatistics(h_FmMac, p_Statistics);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ModifyMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AddHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RemoveHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AddExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RemovelExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetVesrion (t_Handle h_FmMac, uint32_t *macVresion)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetVersion)
+ return p_FmMacControllerDriver->f_FM_MAC_GetVersion(h_FmMac, macVresion);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetId (t_Handle h_FmMac, uint32_t *macId)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetId)
+ return p_FmMacControllerDriver->f_FM_MAC_GetId(h_FmMac, macId);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetPromiscuous (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous)
+ return p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AdjustLink)
+ return p_FmMacControllerDriver->f_FM_MAC_AdjustLink(h_FmMac, speed, fullDuplex);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg)
+ return p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_MII_WritePhyReg (t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg)
+ return p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg(h_FmMac, phyAddr, reg, data);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg)
+ return p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg(h_FmMac, phyAddr, reg, p_Data);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+uint16_t FM_MAC_GetMaxFrameLength(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacControllerDriver, E_INVALID_HANDLE, 0);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength)
+ return p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength(h_FmMac);
+
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ return 0;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/*****************************************************************************/
+t_Error FM_MAC_DumpRegs(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_DumpRegs)
+ return p_FmMacControllerDriver->f_FM_MAC_DumpRegs(h_FmMac);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h
new file mode 100644
index 0000000..94f7b09
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_mac.h
+
+ @Description FM MAC ...
+*//***************************************************************************/
+#ifndef __FM_MAC_H
+#define __FM_MAC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "fm_mac_ext.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_MAC
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+
+
+#define DEFAULT_halfDuplex FALSE
+#define DEFAULT_padAndCrcEnable TRUE
+#define DEFAULT_resetOnInit FALSE
+
+
+typedef struct {
+ uint64_t addr; /* Ethernet Address */
+ t_List node;
+} t_EthHashEntry;
+#define ETH_HASH_ENTRY_OBJ(ptr) LIST_OBJECT(ptr, t_EthHashEntry, node)
+
+typedef struct {
+ uint16_t size;
+ t_List *p_Lsts;
+} t_EthHash;
+
+typedef struct {
+ t_Error (*f_FM_MAC_Init) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Free) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_SetStatistics) (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel);
+ t_Error (*f_FM_MAC_ConfigLoopback) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigMaxFrameLength) (t_Handle h_FmMac, uint16_t newVal);
+ t_Error (*f_FM_MAC_ConfigWan) (t_Handle h_FmMac, bool flag);
+ t_Error (*f_FM_MAC_ConfigPadAndCrc) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigHalfDuplex) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigLengthCheck) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigTbiPhyAddr) (t_Handle h_FmMac, uint8_t newVal);
+ t_Error (*f_FM_MAC_ConfigException) (t_Handle h_FmMac, e_FmMacExceptions, bool enable);
+ t_Error (*f_FM_MAC_ConfigResetOnInit) (t_Handle h_FmMac, bool enable);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ t_Error (*f_FM_MAC_ConfigSkipFman11Workaround) (t_Handle h_FmMac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ t_Error (*f_FM_MAC_SetException) (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable);
+
+ t_Error (*f_FM_MAC_Enable) (t_Handle h_FmMac, e_CommMode mode);
+ t_Error (*f_FM_MAC_Disable) (t_Handle h_FmMac, e_CommMode mode);
+ t_Error (*f_FM_MAC_Enable1588TimeStamp) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Disable1588TimeStamp) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Reset) (t_Handle h_FmMac, bool wait);
+
+ t_Error (*f_FM_MAC_SetTxAutoPauseFrames) (t_Handle h_FmMac,
+ uint16_t pauseTime);
+ t_Error (*f_FM_MAC_SetTxPauseFrames) (t_Handle h_FmMac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime);
+ t_Error (*f_FM_MAC_SetRxIgnorePauseFrames) (t_Handle h_FmMac, bool en);
+
+ t_Error (*f_FM_MAC_ResetCounters) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_GetStatistics) (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics);
+
+ t_Error (*f_FM_MAC_ModifyMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_AddHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_RemoveHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_AddExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_RemovelExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+ t_Error (*f_FM_MAC_SetPromiscuous) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_AdjustLink) (t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex);
+ t_Error (*f_FM_MAC_RestartAutoneg) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_GetId) (t_Handle h_FmMac, uint32_t *macId);
+
+ t_Error (*f_FM_MAC_GetVersion) (t_Handle h_FmMac, uint32_t *macVersion);
+
+ uint16_t (*f_FM_MAC_GetMaxFrameLength) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_MII_WritePhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data);
+ t_Error (*f_FM_MAC_MII_ReadPhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_Error (*f_FM_MAC_DumpRegs) (t_Handle h_FmMac);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ t_Handle h_Fm;
+ t_FmRevisionInfo fmRevInfo;
+ e_EnetMode enetMode;
+ uint8_t macId;
+ bool resetOnInit;
+ uint16_t clkFreq;
+} t_FmMacControllerDriver;
+
+
+#if (DPAA_VERSION == 10)
+t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam);
+t_Handle TGEC_Config(t_FmMacParams *p_FmMacParams);
+#else
+t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam);
+#endif /* (DPAA_VERSION == 10) */
+uint16_t FM_MAC_GetMaxFrameLength(t_Handle FmMac);
+
+
+/* ........................................................................... */
+
+static __inline__ t_EthHashEntry *DequeueAddrFromHashEntry(t_List *p_AddrLst)
+{
+ t_EthHashEntry *p_HashEntry = NULL;
+ if (!LIST_IsEmpty(p_AddrLst))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_AddrLst->p_Next);
+ LIST_DelAndInit(&p_HashEntry->node);
+ }
+ return p_HashEntry;
+}
+
+/* ........................................................................... */
+
+static __inline__ void FreeHashTable(t_EthHash *p_Hash)
+{
+ t_EthHashEntry *p_HashEntry;
+ int i = 0;
+
+ if (p_Hash)
+ {
+ if (p_Hash->p_Lsts)
+ {
+ for (i=0; i<p_Hash->size; i++)
+ {
+ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]);
+ while (p_HashEntry)
+ {
+ XX_Free(p_HashEntry);
+ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]);
+ }
+ }
+
+ XX_Free(p_Hash->p_Lsts);
+ }
+
+ XX_Free(p_Hash);
+ }
+}
+
+/* ........................................................................... */
+
+static __inline__ t_EthHash * AllocHashTable(uint16_t size)
+{
+ uint32_t i;
+ t_EthHash *p_Hash;
+
+ /* Allocate address hash table */
+ p_Hash = (t_EthHash *)XX_Malloc(size*sizeof(t_EthHash *));
+ if (!p_Hash)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table"));
+ return NULL;
+ }
+ p_Hash->size = size;
+
+ p_Hash->p_Lsts = (t_List *)XX_Malloc(p_Hash->size*sizeof(t_List));
+ if (!p_Hash->p_Lsts)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table"));
+ XX_Free(p_Hash);
+ return NULL;
+ }
+
+ for (i=0 ; i<p_Hash->size; i++)
+ INIT_LIST(&p_Hash->p_Lsts[i]);
+
+ return p_Hash;
+}
+
+
+#endif /* __FM_MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c
new file mode 100644
index 0000000..b6a4ca2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "fman_crc32.h"
+#include "common/general.h"
+
+
+/* precomputed CRC values for address hashing */
+static const uint32_t crc_tbl[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */
+static inline uint8_t get_mirror8(uint8_t n)
+{
+ uint8_t mirror[16] = {
+ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+ };
+ return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])));
+}
+
+static inline uint32_t get_mirror32(uint32_t n)
+{
+ return ((uint32_t)get_mirror8((uint8_t)(n))<<24) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>8))<<16) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>16))<<8) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>24)));
+}
+
+uint32_t get_mac_addr_crc(uint64_t _addr)
+{
+ uint32_t i;
+ uint8_t data;
+ uint32_t crc;
+
+ /* CRC calculation */
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ data = (uint8_t)(_addr >> ((5-i)*8));
+ crc = crc ^ data;
+ crc = crc_tbl[crc&0xff] ^ (crc>>8);
+ }
+
+ crc = get_mirror32(crc);
+ return crc;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h
new file mode 100644
index 0000000..6e32fdc
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __FMAN_CRC32_H
+#define __FMAN_CRC32_H
+
+#include "common/general.h"
+
+
+uint32_t get_mac_addr_crc(uint64_t _addr);
+
+
+#endif /* __FMAN_CRC32_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c
new file mode 100644
index 0000000..2ba8554
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c
@@ -0,0 +1,818 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "fsl_fman_dtsec.h"
+
+
+void dtsec_stop_rx(struct dtsec_regs *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(&regs->rctrl) | RCTRL_GRS, &regs->rctrl);
+}
+
+void dtsec_stop_tx(struct dtsec_regs *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(&regs->tctrl) | DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void dtsec_start_tx(struct dtsec_regs *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void dtsec_start_rx(struct dtsec_regs *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS, &regs->rctrl);
+}
+
+void dtsec_defconfig(struct dtsec_cfg *cfg)
+{
+ cfg->halfdup_on = DEFAULT_HALFDUP_ON;
+ cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT;
+ cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW;
+ cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER;
+ cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF;
+ cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF;
+ cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL;
+ cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN;
+ cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST;
+ cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM;
+ cfg->rx_len_check = DEFAULT_RX_LEN_CHECK;
+ cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC;
+ cfg->tx_crc = DEFAULT_TX_CRC;
+ cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC;
+ cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME;
+ cfg->tbipa = DEFAULT_TBIPA; /* PHY address 0 is reserved (DPAA RM)*/
+ cfg->rx_prepend = DEFAULT_RX_PREPEND;
+ cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN;
+ cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN;
+ cfg->preamble_len = DEFAULT_PREAMBLE_LEN;
+ cfg->rx_preamble = DEFAULT_RX_PREAMBLE;
+ cfg->tx_preamble = DEFAULT_TX_PREAMBLE;
+ cfg->loopback = DEFAULT_LOOPBACK;
+ cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN;
+ cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN;
+ cfg->rx_flow = DEFAULT_RX_FLOW;
+ cfg->tx_flow = DEFAULT_TX_FLOW;
+ cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD;
+ cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD;
+ cfg->rx_promisc = DEFAULT_RX_PROMISC;
+ cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1;
+ cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2;
+ cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT;
+ cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG;
+ cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME;
+ cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR;
+}
+
+int dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg,
+ enum enet_interface iface_mode,
+ enum enet_speed iface_speed,
+ uint8_t *macaddr,
+ uint8_t fm_rev_maj,
+ uint8_t fm_rev_min,
+ uint32_t exception_mask)
+{
+ bool is_rgmii = FALSE;
+ bool is_sgmii = FALSE;
+ bool is_qsgmii = FALSE;
+ int i;
+ uint32_t tmp;
+
+UNUSED(fm_rev_maj);UNUSED(fm_rev_min);
+
+ /* let's start with a soft reset */
+ iowrite32be(MACCFG1_SOFT_RESET, &regs->maccfg1);
+ iowrite32be(0, &regs->maccfg1);
+
+ /*************dtsec_id2******************/
+ tmp = ioread32be(&regs->tsec_id2);
+
+ /* check RGMII support */
+ if (iface_mode == E_ENET_IF_RGMII ||
+ iface_mode == E_ENET_IF_RMII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ if (iface_mode == E_ENET_IF_SGMII ||
+ iface_mode == E_ENET_IF_MII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ /***************ECNTRL************************/
+
+ is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? TRUE : FALSE);
+ is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? TRUE : FALSE);
+ is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? TRUE : FALSE);
+
+ tmp = 0;
+ if (is_rgmii || iface_mode == E_ENET_IF_GMII)
+ tmp |= DTSEC_ECNTRL_GMIIM;
+ if (is_sgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM);
+ if (is_qsgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM |
+ DTSEC_ECNTRL_QSGMIIM);
+ if (is_rgmii)
+ tmp |= DTSEC_ECNTRL_RPM;
+ if (iface_speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+
+ iowrite32be(tmp, &regs->ecntrl);
+ /***************ECNTRL************************/
+
+ /***************TCTRL************************/
+ tmp = 0;
+ if (cfg->halfdup_on)
+ tmp |= DTSEC_TCTRL_THDF;
+ if (cfg->tx_time_stamp_en)
+ tmp |= DTSEC_TCTRL_TTSE;
+
+ iowrite32be(tmp, &regs->tctrl);
+
+ /***************TCTRL************************/
+
+ /***************PTV************************/
+ tmp = 0;
+
+#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1
+ if ((fm_rev_maj == 1) && (fm_rev_min == 0))
+ cfg->tx_pause_time += 2;
+#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */
+
+ if (cfg->tx_pause_time)
+ tmp |= cfg->tx_pause_time;
+ if (cfg->tx_pause_time_extd)
+ tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST;
+ iowrite32be(tmp, &regs->ptv);
+
+ /***************RCTRL************************/
+ tmp = 0;
+ tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16;
+ if (cfg->rx_ctrl_acc)
+ tmp |= RCTRL_CFA;
+ if (cfg->rx_group_hash_exd)
+ tmp |= RCTRL_GHTX;
+ if (cfg->rx_time_stamp_en)
+ tmp |= RCTRL_RTSE;
+ if (cfg->rx_drop_bcast)
+ tmp |= RCTRL_BC_REJ;
+ if (cfg->rx_short_frm)
+ tmp |= RCTRL_RSF;
+ if (cfg->rx_promisc)
+ tmp |= RCTRL_PROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+ /***************RCTRL************************/
+
+ /*
+ * Assign a Phy Address to the TBI (TBIPA).
+ * Done also in cases where TBI is not selected to avoid conflict with
+ * the external PHY's Physical address
+ */
+ iowrite32be(cfg->tbipa, &regs->tbipa);
+
+ /***************TMR_CTL************************/
+ iowrite32be(0, &regs->tmr_ctrl);
+
+ if (cfg->ptp_tsu_en) {
+ tmp = 0;
+ tmp |= TMR_PEVENT_TSRE;
+ iowrite32be(tmp, &regs->tmr_pevent);
+
+ if (cfg->ptp_exception_en) {
+ tmp = 0;
+ tmp |= TMR_PEMASK_TSREEN;
+ iowrite32be(tmp, &regs->tmr_pemask);
+ }
+ }
+
+ /***************MACCFG1***********************/
+ tmp = 0;
+ if (cfg->loopback)
+ tmp |= MACCFG1_LOOPBACK;
+ if (cfg->rx_flow)
+ tmp |= MACCFG1_RX_FLOW;
+ if (cfg->tx_flow)
+ tmp |= MACCFG1_TX_FLOW;
+ iowrite32be(tmp, &regs->maccfg1);
+
+ /***************MACCFG1***********************/
+
+ /***************MACCFG2***********************/
+ tmp = 0;
+
+ if (iface_speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (iface_speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+
+ tmp |= ((uint32_t) cfg->preamble_len & 0x0000000f)
+ << PREAMBLE_LENGTH_SHIFT;
+
+ if (cfg->rx_preamble)
+ tmp |= MACCFG2_PRE_AM_Rx_EN;
+ if (cfg->tx_preamble)
+ tmp |= MACCFG2_PRE_AM_Tx_EN;
+ if (cfg->rx_len_check)
+ tmp |= MACCFG2_LENGTH_CHECK;
+ if (cfg->tx_pad_crc)
+ tmp |= MACCFG2_PAD_CRC_EN;
+ if (cfg->tx_crc)
+ tmp |= MACCFG2_CRC_EN;
+ if (!cfg->halfdup_on)
+ tmp |= MACCFG2_FULL_DUPLEX;
+ iowrite32be(tmp, &regs->maccfg2);
+
+ /***************MACCFG2***********************/
+
+ /***************IPGIFG************************/
+ tmp = 0;
+ tmp = (((cfg->non_back_to_back_ipg1 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_1)
+ | ((cfg->non_back_to_back_ipg2 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_2)
+ | ((cfg->min_ifg_enforcement <<
+ IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT)
+ & IPGIFG_MIN_IFG_ENFORCEMENT)
+ | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG));
+ iowrite32be(tmp, &regs->ipgifg);
+
+ /***************IPGIFG************************/
+
+ /***************HAFDUP************************/
+ tmp = 0;
+
+ if (cfg->halfdup_alt_backoff_en)
+ tmp = (uint32_t)(HAFDUP_ALT_BEB |
+ ((cfg->halfdup_alt_backoff_val & 0x0000000f)
+ << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT));
+ if (cfg->halfdup_bp_no_backoff)
+ tmp |= HAFDUP_BP_NO_BACKOFF;
+ if (cfg->halfdup_no_backoff)
+ tmp |= HAFDUP_NO_BACKOFF;
+ if (cfg->halfdup_excess_defer)
+ tmp |= HAFDUP_EXCESS_DEFER;
+ tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT)
+ & HAFDUP_RETRANSMISSION_MAX);
+ tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW);
+
+ iowrite32be(tmp, &regs->hafdup);
+ /***************HAFDUP************************/
+
+ /***************MAXFRM************************/
+ /* Initialize MAXFRM */
+ iowrite32be(cfg->maximum_frame, &regs->maxfrm);
+
+ /***************MAXFRM************************/
+
+ /***************CAM1************************/
+ iowrite32be(0xffffffff, &regs->cam1);
+ iowrite32be(0xffffffff, &regs->cam2);
+
+ /***************IMASK************************/
+ iowrite32be(exception_mask, &regs->imask);
+ /***************IMASK************************/
+
+ /***************IEVENT************************/
+ iowrite32be(0xffffffff, &regs->ievent);
+
+ /***************MACSTNADDR1/2*****************/
+
+ tmp = (uint32_t)((macaddr[5] << 24) |
+ (macaddr[4] << 16) |
+ (macaddr[3] << 8) |
+ macaddr[2]);
+ iowrite32be(tmp, &regs->macstnaddr1);
+
+ tmp = (uint32_t)((macaddr[1] << 24) |
+ (macaddr[0] << 16));
+ iowrite32be(tmp, &regs->macstnaddr2);
+
+ /***************MACSTNADDR1/2*****************/
+
+ /*****************HASH************************/
+ for (i = 0; i < NUM_OF_HASH_REGS ; i++) {
+ /* Initialize IADDRx */
+ iowrite32be(0, &regs->igaddr[i]);
+ /* Initialize GADDRx */
+ iowrite32be(0, &regs->gaddr[i]);
+ }
+
+ dtsec_reset_stat(regs);
+
+ return 0;
+}
+
+uint16_t dtsec_get_max_frame_len(struct dtsec_regs *regs)
+{
+ return (uint16_t)ioread32be(&regs->maxfrm);
+}
+
+void dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length)
+{
+ iowrite32be(length, &regs->maxfrm);
+}
+
+void dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)((adr[5] << 24) |
+ (adr[4] << 16) |
+ (adr[3] << 8) |
+ adr[2]);
+ iowrite32be(tmp, &regs->macstnaddr1);
+
+ tmp = (uint32_t)((adr[1] << 24) |
+ (adr[0] << 16));
+ iowrite32be(tmp, &regs->macstnaddr2);
+}
+
+void dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr)
+{
+ uint32_t tmp1, tmp2;
+
+ tmp1 = ioread32be(&regs->macstnaddr1);
+ tmp2 = ioread32be(&regs->macstnaddr2);
+
+ macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16);
+ macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24);
+ macaddr[2] = (uint8_t)(tmp1 & 0x000000ff);
+ macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8);
+ macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16);
+ macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24);
+}
+
+void dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable)
+{
+ int reg_idx = (bucket >> 5) & 0xf;
+ int bit_idx = bucket & 0x1f;
+ uint32_t bit_mask = 0x80000000 >> bit_idx;
+ uint32_t *reg;
+
+ if (reg_idx > 7)
+ reg = &regs->gaddr[reg_idx-8];
+ else
+ reg = &regs->igaddr[reg_idx];
+
+ if (enable)
+ iowrite32be(ioread32be(reg) | bit_mask, reg);
+ else
+ iowrite32be(ioread32be(reg) & (~bit_mask), reg);
+}
+
+void dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast)
+{
+ int i;
+ bool ghtx;
+
+ ghtx = (bool)((ioread32be(&regs->rctrl) & RCTRL_GHTX) ? TRUE : FALSE);
+
+ if (ucast || (ghtx && mcast)) {
+ for (i = 0; i < NUM_OF_HASH_REGS; i++)
+ iowrite32be(0, &regs->igaddr[i]);
+ }
+ if (mcast) {
+ for (i = 0; i < NUM_OF_HASH_REGS; i++)
+ iowrite32be(0, &regs->gaddr[i]);
+ }
+}
+
+int dtsec_set_tbi_phy_addr(struct dtsec_regs *regs,
+ uint8_t addr)
+{
+ if (addr > 0 && addr < 32)
+ iowrite32be(addr, &regs->tbipa);
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int dtsec_adjust_link(struct dtsec_regs *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx)
+{
+ uint32_t tmp;
+
+ if ((speed == E_ENET_SPEED_1000) && !full_dx)
+ return -EINVAL;
+
+ tmp = ioread32be(&regs->maccfg2);
+ if (!full_dx)
+ tmp &= ~MACCFG2_FULL_DUPLEX;
+ else
+ tmp |= MACCFG2_FULL_DUPLEX;
+
+ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
+ if (speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+ iowrite32be(tmp, &regs->maccfg2);
+
+ tmp = ioread32be(&regs->ecntrl);
+ if (speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+ else
+ tmp &= ~DTSEC_ECNTRL_R100M;
+ iowrite32be(tmp, &regs->ecntrl);
+
+ return 0;
+}
+
+void dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_UPROM;
+ else
+ tmp &= ~RCTRL_UPROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+}
+
+void dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_MPROM;
+ else
+ tmp &= ~RCTRL_MPROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+}
+
+bool dtsec_get_clear_carry_regs(struct dtsec_regs *regs,
+ uint32_t *car1, uint32_t *car2)
+{
+ /* read carry registers */
+ *car1 = ioread32be(&regs->car1);
+ *car2 = ioread32be(&regs->car2);
+ /* clear carry registers */
+ if (*car1)
+ iowrite32be(*car1, &regs->car1);
+ if (*car2)
+ iowrite32be(*car2, &regs->car2);
+
+ return (bool)((*car1 | *car2) ? TRUE : FALSE);
+}
+
+
+void dtsec_reset_stat(struct dtsec_regs *regs)
+{
+ /* clear HW counters */
+ iowrite32be(ioread32be(&regs->ecntrl) |
+ DTSEC_ECNTRL_CLRCNT, &regs->ecntrl);
+}
+
+int dtsec_set_stat_level(struct dtsec_regs *regs, enum mac_stat_level level)
+{
+ switch (level) {
+ case E_MAC_STAT_NONE:
+ iowrite32be(0xffffffff, &regs->cam1);
+ iowrite32be(0xffffffff, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) & ~DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) & ~DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_PARTIAL:
+ iowrite32be(CAM1_ERRORS_ONLY, &regs->cam1);
+ iowrite32be(CAM2_ERRORS_ONLY, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_MIB_GRP1:
+ iowrite32be((uint32_t)~CAM1_MIB_GRP_1, &regs->cam1);
+ iowrite32be((uint32_t)~CAM2_MIB_GRP_1, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_FULL:
+ iowrite32be(0, &regs->cam1);
+ iowrite32be(0, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void dtsec_set_ts(struct dtsec_regs *regs, bool en)
+{
+ if (en) {
+ iowrite32be(ioread32be(&regs->rctrl) | RCTRL_RTSE,
+ &regs->rctrl);
+ iowrite32be(ioread32be(&regs->tctrl) | DTSEC_TCTRL_TTSE,
+ &regs->tctrl);
+ } else {
+ iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_RTSE,
+ &regs->rctrl);
+ iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_TTSE,
+ &regs->tctrl);
+ }
+}
+
+void dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maccfg1);
+
+ if (apply_rx)
+ tmp |= MACCFG1_RX_EN ;
+
+ if (apply_tx)
+ tmp |= MACCFG1_TX_EN ;
+
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+void dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, uint8_t paddr_num)
+{
+ iowrite32be(0, &regs->macaddr[paddr_num].exact_match1);
+ iowrite32be(0, &regs->macaddr[paddr_num].exact_match2);
+}
+
+void dtsec_add_addr_in_paddr(struct dtsec_regs *regs,
+ uint64_t addr,
+ uint8_t paddr_num)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)(addr);
+ /* swap */
+ tmp = (((tmp & 0x000000FF) << 24) |
+ ((tmp & 0x0000FF00) << 8) |
+ ((tmp & 0x00FF0000) >> 8) |
+ ((tmp & 0xFF000000) >> 24));
+ iowrite32be(tmp, &regs->macaddr[paddr_num].exact_match1);
+
+ tmp = (uint32_t)(addr>>32);
+ /* swap */
+ tmp = (((tmp & 0x000000FF) << 24) |
+ ((tmp & 0x0000FF00) << 8) |
+ ((tmp & 0x00FF0000) >> 8) |
+ ((tmp & 0xFF000000) >> 24));
+ iowrite32be(tmp, &regs->macaddr[paddr_num].exact_match2);
+}
+
+void dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maccfg1);
+
+ if (apply_rx)
+ tmp &= ~MACCFG1_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~MACCFG1_TX_EN;
+
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+void dtsec_set_tx_pause_time(struct dtsec_regs *regs, uint16_t time)
+{
+ uint32_t ptv = 0;
+
+ /* fixme: don't enable tx pause for half-duplex */
+
+ if (time) {
+ ptv = ioread32be(&regs->ptv);
+ ptv &= 0xffff0000;
+ ptv |= time & 0x0000ffff;
+ iowrite32be(ptv, &regs->ptv);
+
+ /* trigger the transmission of a flow-control pause frame */
+ iowrite32be(ioread32be(&regs->maccfg1) | MACCFG1_TX_FLOW,
+ &regs->maccfg1);
+ } else
+ iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
+ &regs->maccfg1);
+}
+
+void dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ /* todo: check if mac is set to full-duplex */
+
+ tmp = ioread32be(&regs->maccfg1);
+ if (en)
+ tmp |= MACCFG1_RX_FLOW;
+ else
+ tmp &= ~MACCFG1_RX_FLOW;
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+uint32_t dtsec_get_rctrl(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->rctrl);
+}
+
+uint32_t dtsec_get_revision(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->tsec_id);
+}
+
+uint32_t dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t dtsec_get_interrupt_mask(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+uint32_t dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs)
+{
+ uint32_t event;
+
+ event = ioread32be(&regs->tmr_pevent);
+ event &= ioread32be(&regs->tmr_pemask);
+
+ if (event)
+ iowrite32be(event, &regs->tmr_pevent);
+ return event;
+}
+
+void dtsec_enable_tmr_interrupt(struct dtsec_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->tmr_pemask) | TMR_PEMASK_TSREEN,
+ &regs->tmr_pemask);
+}
+
+void dtsec_disable_tmr_interrupt(struct dtsec_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->tmr_pemask) & ~TMR_PEMASK_TSREEN,
+ &regs->tmr_pemask);
+}
+
+void dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
+
+uint32_t dtsec_get_stat_counter(struct dtsec_regs *regs,
+ enum dtsec_stat_counters reg_name)
+{
+ uint32_t ret_val;
+
+ switch (reg_name) {
+ case E_DTSEC_STAT_TR64:
+ ret_val = ioread32be(&regs->tr64);
+ break;
+ case E_DTSEC_STAT_TR127:
+ ret_val = ioread32be(&regs->tr127);
+ break;
+ case E_DTSEC_STAT_TR255:
+ ret_val = ioread32be(&regs->tr255);
+ break;
+ case E_DTSEC_STAT_TR511:
+ ret_val = ioread32be(&regs->tr511);
+ break;
+ case E_DTSEC_STAT_TR1K:
+ ret_val = ioread32be(&regs->tr1k);
+ break;
+ case E_DTSEC_STAT_TRMAX:
+ ret_val = ioread32be(&regs->trmax);
+ break;
+ case E_DTSEC_STAT_TRMGV:
+ ret_val = ioread32be(&regs->trmgv);
+ break;
+ case E_DTSEC_STAT_RBYT:
+ ret_val = ioread32be(&regs->rbyt);
+ break;
+ case E_DTSEC_STAT_RPKT:
+ ret_val = ioread32be(&regs->rpkt);
+ break;
+ case E_DTSEC_STAT_RMCA:
+ ret_val = ioread32be(&regs->rmca);
+ break;
+ case E_DTSEC_STAT_RBCA:
+ ret_val = ioread32be(&regs->rbca);
+ break;
+ case E_DTSEC_STAT_RXPF:
+ ret_val = ioread32be(&regs->rxpf);
+ break;
+ case E_DTSEC_STAT_RALN:
+ ret_val = ioread32be(&regs->raln);
+ break;
+ case E_DTSEC_STAT_RFLR:
+ ret_val = ioread32be(&regs->rflr);
+ break;
+ case E_DTSEC_STAT_RCDE:
+ ret_val = ioread32be(&regs->rcde);
+ break;
+ case E_DTSEC_STAT_RCSE:
+ ret_val = ioread32be(&regs->rcse);
+ break;
+ case E_DTSEC_STAT_RUND:
+ ret_val = ioread32be(&regs->rund);
+ break;
+ case E_DTSEC_STAT_ROVR:
+ ret_val = ioread32be(&regs->rovr);
+ break;
+ case E_DTSEC_STAT_RFRG:
+ ret_val = ioread32be(&regs->rfrg);
+ break;
+ case E_DTSEC_STAT_RJBR:
+ ret_val = ioread32be(&regs->rjbr);
+ break;
+ case E_DTSEC_STAT_RDRP:
+ ret_val = ioread32be(&regs->rdrp);
+ break;
+ case E_DTSEC_STAT_TFCS:
+ ret_val = ioread32be(&regs->tfcs);
+ break;
+ case E_DTSEC_STAT_TBYT:
+ ret_val = ioread32be(&regs->tbyt);
+ break;
+ case E_DTSEC_STAT_TPKT:
+ ret_val = ioread32be(&regs->tpkt);
+ break;
+ case E_DTSEC_STAT_TMCA:
+ ret_val = ioread32be(&regs->tmca);
+ break;
+ case E_DTSEC_STAT_TBCA:
+ ret_val = ioread32be(&regs->tbca);
+ break;
+ case E_DTSEC_STAT_TXPF:
+ ret_val = ioread32be(&regs->txpf);
+ break;
+ case E_DTSEC_STAT_TNCL:
+ ret_val = ioread32be(&regs->tncl);
+ break;
+ case E_DTSEC_STAT_TDRP:
+ ret_val = ioread32be(&regs->tdrp);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c
new file mode 100644
index 0000000..b1b7bae
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "common/general.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+
+/**
+ * dtsec_mii_get_div() - calculates the value of the dtsec mii divider
+ * @dtsec_freq: dtsec clock frequency (in Mhz)
+ *
+ * This function calculates the dtsec mii clock divider that determines
+ * the MII MDC clock. MII MDC clock can work in the range of 2.5 to 12.5 Mhz.
+ * The output of this function is the value of MIIMCFG[MgmtClk] which
+ * implicitly determines the divider value.
+ * Note: the dTSEC system clock is equal to 1/2 of the FMan clock.
+ *
+ * The table below which reflects dtsec_mii_get_div() functionality
+ * shows the relations among dtsec_freq, MgmtClk, actual divider
+ * and the MII frequency:
+ *
+ * dtsec freq MgmtClk div MII freq
+ * [80..159] 0 (1/4)(1/8) [2.5 to 5.0]
+ * [160..319] 1 (1/4)(1/8) [5.0 to 10.0]
+ * [320..479] 2 (1/6)(1/8) [6.7 to 10.0]
+ * [480..639] 3 (1/8)(1/8) [7.5 to 10.0]
+ * [640..799] 4 (1/10)(1/8) [8.0 to 10.0]
+ * [800..959] 5 (1/14)(1/8) [7.1 to 8.5]
+ * [960..1119] 6 (1/20)(1/8) [6.0 to 7.0]
+ * [1120..1279] 7 (1/28)(1/8) [5.0 to 5.7]
+ * [1280..2800] 7 (1/28)(1/8) [5.7 to 12.5]
+ *
+ * Returns: the MIIMCFG[MgmtClk] appropriate value
+ */
+
+static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq)
+{
+ uint16_t mgmt_clk = (uint16_t)(dtsec_freq / 160);
+
+ if (mgmt_clk > 7)
+ mgmt_clk = 7;
+
+ return (uint8_t)mgmt_clk;
+}
+
+void dtsec_mii_reset(struct dtsec_mii_reg *regs)
+{
+ /* Reset the management interface */
+ iowrite32be(ioread32be(&regs->miimcfg) | MIIMCFG_RESET_MGMT,
+ &regs->miimcfg);
+ iowrite32be(ioread32be(&regs->miimcfg) & ~MIIMCFG_RESET_MGMT,
+ &regs->miimcfg);
+}
+
+void dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq)
+{
+ /* Setup the MII Mgmt clock speed */
+ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
+}
+
+int dtsec_mii_write_reg(struct dtsec_mii_reg *regs, uint8_t addr,
+ uint8_t reg, uint16_t data)
+{
+ uint32_t tmp;
+
+ /* Stop the MII management read cycle */
+ iowrite32be(0, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+
+ /* Setting up MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, &regs->miimadd);
+
+ /* Setting up MII Management Control Register with data */
+ iowrite32be((uint32_t)data, &regs->miimcon);
+ /* Dummy read to make sure MIIMCON is written */
+ tmp = ioread32be(&regs->miimcon);
+
+ /* Wait untill MII management write is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+ /* busy wait */;
+
+ return 0;
+}
+
+int dtsec_mii_read_reg(struct dtsec_mii_reg *regs, uint8_t addr,
+ uint8_t reg, uint16_t *data)
+{
+ uint32_t tmp;
+
+ /* Setting up the MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, &regs->miimadd);
+
+ /* Perform an MII management read cycle */
+ iowrite32be(MIIMCOM_READ_CYCLE, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+
+ /* Wait until MII management read is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+ /* busy wait */;
+
+ /* Read MII management status */
+ *data = (uint16_t)ioread32be(&regs->miimstat);
+
+ iowrite32be(0, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+
+ if (*data == 0xffff)
+ return -ENXIO;
+
+ return 0;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c
new file mode 100644
index 0000000..a63d06a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "fsl_fman_memac.h"
+
+
+uint32_t memac_get_event(struct memac_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+uint32_t memac_get_interrupt_mask(struct memac_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+void memac_ack_event(struct memac_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+void memac_set_promiscuous(struct memac_regs *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void memac_hardware_clear_addr_in_paddr(struct memac_regs *regs,
+ uint8_t paddr_num)
+{
+ if (paddr_num == 0) {
+ iowrite32be(0, &regs->mac_addr0.mac_addr_l);
+ iowrite32be(0, &regs->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_l);
+ iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_u);
+ }
+}
+
+void memac_hardware_add_addr_in_paddr(struct memac_regs *regs,
+ uint8_t *adr,
+ uint8_t paddr_num)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+
+ if (paddr_num == 0) {
+ iowrite32be(tmp0, &regs->mac_addr0.mac_addr_l);
+ iowrite32be(tmp1, &regs->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(tmp0, &regs->mac_addr[paddr_num-1].mac_addr_l);
+ iowrite32be(tmp1, &regs->mac_addr[paddr_num-1].mac_addr_u);
+ }
+}
+
+void memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (apply_rx)
+ tmp &= ~CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void memac_reset_counter(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->statn_config);
+
+ tmp |= STATS_CFG_CLR;
+
+ iowrite32be(tmp, &regs->statn_config);
+
+ while (ioread32be(&regs->statn_config) & STATS_CFG_CLR);
+}
+
+void memac_reset(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ tmp |= CMD_CFG_SW_RESET;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ while (ioread32be(&regs->command_config) & CMD_CFG_SW_RESET);
+}
+
+void memac_init(struct memac_regs *regs,
+ struct memac_cfg *cfg,
+ enum enet_interface enet_interface,
+ enum enet_speed enet_speed,
+ uint32_t exceptions)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0;
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CNT_FRM_EN;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->rx_sfd_any)
+ tmp |= CMD_CFG_SFD_ANY;
+ if (cfg->pad_enable)
+ tmp |= CMD_CFG_TX_PAD_EN;
+
+ tmp |= CMD_CFG_CRC_FWD;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+
+ /* Pause Time */
+ iowrite32be(cfg->pause_quanta, &regs->pause_quanta[0]);
+ iowrite32be(0, &regs->pause_thresh[0]);
+
+ /* interrupts */
+ iowrite32be(MEMAC_EVENTS_MASK, &regs->ievent);
+ iowrite32be(exceptions, &regs->imask);
+
+ /* IF_MODE */
+ tmp = 0;
+ switch (enet_interface) {
+ case E_ENET_IF_XGMII:
+ case E_ENET_IF_XFI:
+ tmp |= IF_MODE_XGMII;
+ break;
+ default:
+ tmp |= IF_MODE_GMII;
+ if (enet_interface == E_ENET_IF_RGMII)
+ tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
+ }
+ iowrite32be(tmp, &regs->if_mode);
+}
+
+void memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->imask);
+ if (enable)
+ tmp |= val;
+ else
+ tmp &= ~val;
+
+ iowrite32be(tmp, &regs->imask);
+}
+
+void memac_set_hash_table(struct memac_regs *regs, uint32_t val)
+{
+ iowrite32be(val, &regs->hashtable_ctrl);
+}
+
+uint16_t memac_get_max_frame_length(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maxfrm);
+
+ return(uint16_t)tmp;
+}
+
+
+void memac_set_tx_pause_frames(struct memac_regs *regs,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (priority == 0xff) {
+ tmp &= ~CMD_CFG_PFC_MODE;
+ priority = 0;
+ }
+ else
+ tmp |= CMD_CFG_PFC_MODE;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ tmp = ioread32be(&regs->pause_quanta[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));
+ iowrite32be(tmp, &regs->pause_quanta[priority / 2]);
+
+ tmp = ioread32be(&regs->pause_thresh[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2)));
+ iowrite32be(tmp, &regs->pause_thresh[priority / 2]);
+}
+
+void memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (enable)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void memac_set_loopback(struct memac_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ else
+ tmp &= ~CMD_CFG_LOOPBACK_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+
+#define GET_MEMAC_CNTR_64(bn) \
+ (ioread32be(&regs->bn ## _l) | \
+ ((uint64_t)ioread32be(&regs->bn ## _u) << 32))
+
+uint64_t memac_get_counter(struct memac_regs *regs,
+ enum memac_counters reg_name)
+{
+ uint64_t ret_val;
+
+ switch (reg_name) {
+ case E_MEMAC_COUNTER_R64:
+ ret_val = GET_MEMAC_CNTR_64(r64);
+ break;
+ case E_MEMAC_COUNTER_R127:
+ ret_val = GET_MEMAC_CNTR_64(r127);
+ break;
+ case E_MEMAC_COUNTER_R255:
+ ret_val = GET_MEMAC_CNTR_64(r255);
+ break;
+ case E_MEMAC_COUNTER_R511:
+ ret_val = GET_MEMAC_CNTR_64(r511);
+ break;
+ case E_MEMAC_COUNTER_R1023:
+ ret_val = GET_MEMAC_CNTR_64(r1023);
+ break;
+ case E_MEMAC_COUNTER_R1518:
+ ret_val = GET_MEMAC_CNTR_64(r1518);
+ break;
+ case E_MEMAC_COUNTER_R1519X:
+ ret_val = GET_MEMAC_CNTR_64(r1519x);
+ break;
+ case E_MEMAC_COUNTER_RFRG:
+ ret_val = GET_MEMAC_CNTR_64(rfrg);
+ break;
+ case E_MEMAC_COUNTER_RJBR:
+ ret_val = GET_MEMAC_CNTR_64(rjbr);
+ break;
+ case E_MEMAC_COUNTER_RDRP:
+ ret_val = GET_MEMAC_CNTR_64(rdrp);
+ break;
+ case E_MEMAC_COUNTER_RALN:
+ ret_val = GET_MEMAC_CNTR_64(raln);
+ break;
+ case E_MEMAC_COUNTER_TUND:
+ ret_val = GET_MEMAC_CNTR_64(tund);
+ break;
+ case E_MEMAC_COUNTER_ROVR:
+ ret_val = GET_MEMAC_CNTR_64(rovr);
+ break;
+ case E_MEMAC_COUNTER_RXPF:
+ ret_val = GET_MEMAC_CNTR_64(rxpf);
+ break;
+ case E_MEMAC_COUNTER_TXPF:
+ ret_val = GET_MEMAC_CNTR_64(txpf);
+ break;
+ case E_MEMAC_COUNTER_ROCT:
+ ret_val = GET_MEMAC_CNTR_64(roct);
+ break;
+ case E_MEMAC_COUNTER_RMCA:
+ ret_val = GET_MEMAC_CNTR_64(rmca);
+ break;
+ case E_MEMAC_COUNTER_RBCA:
+ ret_val = GET_MEMAC_CNTR_64(rbca);
+ break;
+ case E_MEMAC_COUNTER_RPKT:
+ ret_val = GET_MEMAC_CNTR_64(rpkt);
+ break;
+ case E_MEMAC_COUNTER_RUCA:
+ ret_val = GET_MEMAC_CNTR_64(ruca);
+ break;
+ case E_MEMAC_COUNTER_RERR:
+ ret_val = GET_MEMAC_CNTR_64(rerr);
+ break;
+ case E_MEMAC_COUNTER_TOCT:
+ ret_val = GET_MEMAC_CNTR_64(toct);
+ break;
+ case E_MEMAC_COUNTER_TMCA:
+ ret_val = GET_MEMAC_CNTR_64(tmca);
+ break;
+ case E_MEMAC_COUNTER_TBCA:
+ ret_val = GET_MEMAC_CNTR_64(tbca);
+ break;
+ case E_MEMAC_COUNTER_TUCA:
+ ret_val = GET_MEMAC_CNTR_64(tuca);
+ break;
+ case E_MEMAC_COUNTER_TERR:
+ ret_val = GET_MEMAC_CNTR_64(terr);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+
+void memac_defconfig(struct memac_cfg *cfg)
+{
+ cfg->reset_on_init = FALSE;
+ cfg->wan_mode_enable = FALSE;
+ cfg->promiscuous_mode_enable = FALSE;
+ cfg->pause_forward_enable = FALSE;
+ cfg->pause_ignore = FALSE;
+ cfg->tx_addr_ins_enable = FALSE;
+ cfg->loopback_enable = FALSE;
+ cfg->cmd_frame_enable = FALSE;
+ cfg->rx_error_discard = FALSE;
+ cfg->send_idle_enable = FALSE;
+ cfg->no_length_check_enable = TRUE;
+ cfg->lgth_check_nostdr = FALSE;
+ cfg->time_stamp_enable = FALSE;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_FRAME_LENGTH;
+ cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;
+ cfg->pad_enable = TRUE;
+ cfg->phy_tx_ena_on = FALSE;
+ cfg->rx_sfd_any = FALSE;
+ cfg->rx_pbl_fwd = FALSE;
+ cfg->tx_pbl_fwd = FALSE;
+ cfg->debug_mode = FALSE;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c
new file mode 100644
index 0000000..fa80a36
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "fsl_fman_tgec.h"
+
+
+void tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+ iowrite32be(tmp0, &regs->mac_addr_0);
+ iowrite32be(tmp1, &regs->mac_addr_1);
+}
+
+void tgec_reset_stat(struct tgec_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ tmp |= CMD_CFG_STAT_CLR;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ while (ioread32be(&regs->command_config) & CMD_CFG_STAT_CLR);
+}
+
+#define GET_TGEC_CNTR_64(bn) \
+ (((uint64_t)ioread32be(&regs->bn ## _u) << 32) | \
+ ioread32be(&regs->bn ## _l))
+
+uint64_t tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name)
+{
+ uint64_t ret_val;
+
+ switch (reg_name) {
+ case E_TGEC_COUNTER_R64:
+ ret_val = GET_TGEC_CNTR_64(r64);
+ break;
+ case E_TGEC_COUNTER_R127:
+ ret_val = GET_TGEC_CNTR_64(r127);
+ break;
+ case E_TGEC_COUNTER_R255:
+ ret_val = GET_TGEC_CNTR_64(r255);
+ break;
+ case E_TGEC_COUNTER_R511:
+ ret_val = GET_TGEC_CNTR_64(r511);
+ break;
+ case E_TGEC_COUNTER_R1023:
+ ret_val = GET_TGEC_CNTR_64(r1023);
+ break;
+ case E_TGEC_COUNTER_R1518:
+ ret_val = GET_TGEC_CNTR_64(r1518);
+ break;
+ case E_TGEC_COUNTER_R1519X:
+ ret_val = GET_TGEC_CNTR_64(r1519x);
+ break;
+ case E_TGEC_COUNTER_TRFRG:
+ ret_val = GET_TGEC_CNTR_64(trfrg);
+ break;
+ case E_TGEC_COUNTER_TRJBR:
+ ret_val = GET_TGEC_CNTR_64(trjbr);
+ break;
+ case E_TGEC_COUNTER_RDRP:
+ ret_val = GET_TGEC_CNTR_64(rdrp);
+ break;
+ case E_TGEC_COUNTER_RALN:
+ ret_val = GET_TGEC_CNTR_64(raln);
+ break;
+ case E_TGEC_COUNTER_TRUND:
+ ret_val = GET_TGEC_CNTR_64(trund);
+ break;
+ case E_TGEC_COUNTER_TROVR:
+ ret_val = GET_TGEC_CNTR_64(trovr);
+ break;
+ case E_TGEC_COUNTER_RXPF:
+ ret_val = GET_TGEC_CNTR_64(rxpf);
+ break;
+ case E_TGEC_COUNTER_TXPF:
+ ret_val = GET_TGEC_CNTR_64(txpf);
+ break;
+ case E_TGEC_COUNTER_ROCT:
+ ret_val = GET_TGEC_CNTR_64(roct);
+ break;
+ case E_TGEC_COUNTER_RMCA:
+ ret_val = GET_TGEC_CNTR_64(rmca);
+ break;
+ case E_TGEC_COUNTER_RBCA:
+ ret_val = GET_TGEC_CNTR_64(rbca);
+ break;
+ case E_TGEC_COUNTER_RPKT:
+ ret_val = GET_TGEC_CNTR_64(rpkt);
+ break;
+ case E_TGEC_COUNTER_RUCA:
+ ret_val = GET_TGEC_CNTR_64(ruca);
+ break;
+ case E_TGEC_COUNTER_RERR:
+ ret_val = GET_TGEC_CNTR_64(rerr);
+ break;
+ case E_TGEC_COUNTER_TOCT:
+ ret_val = GET_TGEC_CNTR_64(toct);
+ break;
+ case E_TGEC_COUNTER_TMCA:
+ ret_val = GET_TGEC_CNTR_64(tmca);
+ break;
+ case E_TGEC_COUNTER_TBCA:
+ ret_val = GET_TGEC_CNTR_64(tbca);
+ break;
+ case E_TGEC_COUNTER_TUCA:
+ ret_val = GET_TGEC_CNTR_64(tuca);
+ break;
+ case E_TGEC_COUNTER_TERR:
+ ret_val = GET_TGEC_CNTR_64(terr);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+
+void tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp_reg_32;
+
+ tmp_reg_32 = ioread32be(&regs->command_config);
+ if (apply_rx)
+ tmp_reg_32 &= ~CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp_reg_32 &= ~CMD_CFG_TX_EN;
+ iowrite32be(tmp_reg_32, &regs->command_config);
+}
+
+void tgec_set_promiscuous(struct tgec_regs *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void tgec_set_hash_table(struct tgec_regs *regs, uint32_t value)
+{
+ iowrite32be(value, &regs->hashtable_ctrl);
+}
+
+void tgec_tx_mac_pause(struct tgec_regs *regs, uint16_t pause_time)
+{
+ iowrite32be((uint32_t)pause_time, &regs->pause_quant);
+}
+
+void tgec_rx_ignore_mac_pause(struct tgec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (en)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (en)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ else
+ tmp &= ~CMD_CFG_EN_TIMESTAMP;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+uint32_t tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t tgec_get_interrupt_mask(struct tgec_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+void tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+ iowrite32be(tmp0, &regs->mac_addr_2);
+ iowrite32be(tmp1, &regs->mac_addr_3);
+}
+
+void tgec_clear_addr_in_paddr(struct tgec_regs *regs)
+{
+ iowrite32be(0, &regs->mac_addr_2);
+ iowrite32be(0, &regs->mac_addr_3);
+}
+
+uint32_t tgec_get_revision(struct tgec_regs *regs)
+{
+ return ioread32be(&regs->tgec_id);
+}
+
+void tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
+
+uint16_t tgec_get_max_frame_len(struct tgec_regs *regs)
+{
+ return (uint16_t) ioread32be(&regs->maxfrm);
+}
+
+void tgec_defconfig(struct tgec_cfg *cfg)
+{
+ cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE;
+ cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE;
+ cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE;
+ cfg->pause_ignore = DEFAULT_PAUSE_IGNORE;
+ cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE;
+ cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE;
+ cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE;
+ cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD;
+ cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE;
+ cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE;
+ cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR;
+ cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH;
+ cfg->pause_quant = DEFAULT_PAUSE_QUANT;
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ cfg->skip_fman11_workaround = FALSE;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+}
+
+int tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg,
+ uint32_t exception_mask)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0x40; /* CRC forward */
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CMD_FRM_EN;
+ if (cfg->rx_error_discard)
+ tmp |= CMD_CFG_RX_ER_DISC;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->time_stamp_enable)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ iowrite32be(tmp, &regs->command_config);
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+ /* Pause Time */
+ iowrite32be(cfg->pause_quant, &regs->pause_quant);
+
+ /* clear all pending events and set-up interrupts */
+ tgec_ack_event(regs, 0xffffffff);
+ tgec_enable_interrupt(regs, exception_mask);
+ return 0;
+}
+
+void tgec_fm_tx_fifo_corruption_errata_10gmac_a007(struct tgec_regs *regs)
+{
+ uint32_t tmp;
+
+ /* restore the default tx ipg Length */
+ tmp = (ioread32be(&regs->tx_ipg_len) & ~TX_IPG_LENGTH_MASK) | 12;
+
+ iowrite32be(tmp, &regs->tx_ipg_len);
+
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h
new file mode 100644
index 0000000..2d74b6a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fsl_fman_dtsec_mii_acc.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __FSL_FMAN_DTSEC_MII_ACC_H
+#define __FSL_FMAN_DTSEC_MII_ACC_H
+
+#include "common/general.h"
+
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT 0x80000000
+#define MIIMCFG_MGNTCLK_MASK 0x00000007
+#define MIIMCFG_MGNTCLK_SHIFT 0
+
+/* MII Management Command Register */
+#define MIIMCOM_SCAN_CYCLE 0x00000002
+#define MIIMCOM_READ_CYCLE 0x00000001
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT 8
+#define MIIMADD_PHY_ADDR_MASK 0x00001f00
+
+#define MIIMADD_REG_ADDR_SHIFT 0
+#define MIIMADD_REG_ADDR_MASK 0x0000001f
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+
+
+/* PHY Control Register */
+#define PHY_CR_LOOPBACK 0x4000
+#define PHY_CR_SPEED0 0x2000
+#define PHY_CR_ANE 0x1000
+#define PHY_CR_FULLDUPLEX 0x0100
+#define PHY_CR_SPEED1 0x0040
+
+#define PHY_TBICON_SRESET 0x8000
+#define PHY_TBICON_SPEED2 0x0020
+
+/* register map */
+
+/* MII Configuration Control Memory Map Registers */
+struct dtsec_mii_reg {
+ uint32_t reserved1[72];
+ uint32_t miimcfg; /* MII Mgmt:configuration */
+ uint32_t miimcom; /* MII Mgmt:command */
+ uint32_t miimadd; /* MII Mgmt:address */
+ uint32_t miimcon; /* MII Mgmt:control 3 */
+ uint32_t miimstat; /* MII Mgmt:status */
+ uint32_t miimind; /* MII Mgmt:indicators */
+};
+
+/* dTSEC MII API */
+
+/* functions to access the mii registers for phy configuration.
+ * this functionality may not be available for all dtsecs in the system.
+ * consult the reference manual for details */
+void dtsec_mii_reset(struct dtsec_mii_reg *regs);
+/* frequency is in MHz.
+ * note that dtsec clock is 1/2 of fman clock */
+void dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq);
+int dtsec_mii_write_reg(struct dtsec_mii_reg *regs,
+ uint8_t addr,
+ uint8_t reg,
+ uint16_t data);
+
+int dtsec_mii_read_reg(struct dtsec_mii_reg *regs,
+ uint8_t addr,
+ uint8_t reg,
+ uint16_t *data);
+
+#endif /* __FSL_FMAN_DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c
new file mode 100644
index 0000000..6e5440d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c
@@ -0,0 +1,1036 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 memac.c
+
+ @Description FM mEMAC driver
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "string_ext.h"
+#include "error_ext.h"
+#include "xx_ext.h"
+#include "endian_ext.h"
+#include "debug_ext.h"
+
+#include "fm_common.h"
+#include "memac.h"
+
+
+/*****************************************************************************/
+/* Internal routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint64_t mask1, mask2;
+ uint32_t xor = 0;
+ uint8_t i, j;
+
+ for (i=0; i < 6; i++)
+ {
+ mask1 = ethAddr & (uint64_t)0x01;
+ ethAddr >>= 1;
+
+ for (j=0; j < 7; j++)
+ {
+ mask2 = ethAddr & (uint64_t)0x01;
+ mask1 ^= mask2;
+ ethAddr >>= 1;
+ }
+ xor |= (mask1 << (5-i));
+ }
+
+ return xor;
+}
+
+
+/* ......................................................................... */
+
+static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr)
+{
+ uint16_t tmpReg16;
+
+ /* SGMII mode + AN enable */
+ tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
+
+ /* Device ability according to SGMII specification */
+ tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
+
+ /* Adjust link timer for SGMII -
+ According to Cisco SGMII specification the timer should be 1.6 ms.
+ The link_timer register is configured in units of the clock.
+ - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ unit = 1 / (125*10^6 Hz) = 8 ns.
+ 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40
+ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120.
+ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ we always set up here a value of 2.5 SGMII. */
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007);
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120);
+
+ /* Restart AN */
+ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
+}
+
+/* ......................................................................... */
+
+static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr)
+{
+ uint16_t tmpReg16;
+
+ /* 1000BaseX mode */
+ tmpReg16 = PHY_SGMII_IF_MODE_1000X;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
+
+ /* AN Device capability */
+ tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
+
+ /* Adjust link timer for SGMII -
+ For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
+ The link_timer register is configured in units of the clock.
+ - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ unit = 1 / (125*10^6 Hz) = 8 ns.
+ 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
+ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
+ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ we always set up here a value of 2.5 SGMII. */
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f);
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08);
+
+ /* Restart AN */
+ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
+}
+
+/* ......................................................................... */
+
+static t_Error CheckInitParameters(t_Memac *p_Memac)
+{
+ e_FmMacType portType;
+
+ portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+#if (FM_MAX_NUM_OF_10G_MACS > 0)
+ if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS));
+#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */
+
+ if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS));
+ if (p_Memac->addr == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address"));
+ if (!p_Memac->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception"));
+ if (!p_Memac->f_Event)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event"));
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_Memac->p_MemacDriverParam->no_length_check_enable)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return E_OK;
+}
+
+/* ........................................................................... */
+
+static void MemacErrException(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ struct memac_regs *regs = p_Memac->p_MemMap;
+ uint32_t event, imsk;
+
+ event = memac_get_event(regs, 0xffffffff);
+
+ /*
+ * Apparently the imask bits are shifted by 16 bits offset from
+ * their corresponding bits in the ievent - hence the >> 16
+ */
+ imsk = memac_get_interrupt_mask(regs) >> 16;;
+
+ /*
+ * Extract all event bits plus the pending interrupts according to
+ * their imask
+ */
+ event = (event & ~(MEMAC_ALL_IMASKS >> 16)) | (event & imsk);
+
+ /* Ignoring the status bits */
+ event = event & ~(MEMAC_IEVNT_RX_EMPTY |
+ MEMAC_IEVNT_TX_EMPTY |
+ MEMAC_IEVNT_RX_LOWP |
+ MEMAC_IEVNT_PHY_LOS);
+
+ memac_ack_event(regs, event);
+
+ if (event & MEMAC_IEVNT_RX_FIFO_OVFL)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL);
+ if (event & MEMAC_IEVNT_TX_FIFO_UNFL)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL);
+ if (event & MEMAC_IEVNT_TX_FIFO_OVFL)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL);
+ if (event & MEMAC_IEVNT_TX_ECC_ER)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & MEMAC_IEVNT_RX_ECC_ER)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
+ if (event & MEMAC_IEVNT_REM_FAULT)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_REM_FAULT);
+ if (event & MEMAC_IEVNT_LOC_FAULT)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_LOC_FAULT);
+}
+
+
+/* ......................................................................... */
+
+static void FreeInitResources(t_Memac *p_Memac)
+{
+ e_FmMacType portType;
+
+ portType =
+ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+ if (portType == e_FM_MAC_10G)
+ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
+ else
+ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ FreeHashTable(p_Memac->p_MulticastAddrHash);
+ p_Memac->p_MulticastAddrHash = NULL;
+
+ /* release the driver's individual hash table */
+ FreeHashTable(p_Memac->p_UnicastAddrHash);
+ p_Memac->p_UnicastAddrHash = NULL;
+}
+
+
+/*****************************************************************************/
+/* mEMAC API routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacEnable(t_Handle h_Memac, e_CommMode mode)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_set_promiscuous(p_Memac->p_MemMap, newVal);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+UNUSED(p_Memac);
+DBG(WARNING, ("mEMAC works in automatic-mode; therefore, adjust-link is not needed!"));
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Memac Configs modification functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->loopback_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->wan_mode_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->max_frame_length = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->pad_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Memac->exceptions |= bitMask;
+ else
+ p_Memac->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->reset_on_init = enable;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Memac Run Time API functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacSetTxPauseFrames(t_Handle h_Memac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac,
+ uint16_t pauseTime)
+{
+ return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+UNUSED(p_Memac);
+DBG(WARNING, ("mEMAC has 1588 always enabled!"));
+
+ return E_OK;
+}
+
+/* Counters handling */
+/* ......................................................................... */
+
+static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_Statistics->eStatPkts64 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64);
+ p_Statistics->eStatPkts65to127 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127);
+ p_Statistics->eStatPkts128to255 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255);
+ p_Statistics->eStatPkts256to511 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511);
+ p_Statistics->eStatPkts512to1023 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023);
+ p_Statistics->eStatPkts1024to1518 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518);
+ p_Statistics->eStatPkts1519to1522 = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X);
+/* */
+ p_Statistics->eStatFragments = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG);
+ p_Statistics->eStatJabbers = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR);
+
+ p_Statistics->eStatsDropEvents = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP);
+ p_Statistics->eStatCRCAlignErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN);
+
+ p_Statistics->eStatUndersizePkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND);
+ p_Statistics->eStatOversizePkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR);
+/* Pause */
+ p_Statistics->reStatPause = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF);
+ p_Statistics->teStatPause = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF);
+
+/* MIB II */
+ p_Statistics->ifInOctets = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT);
+ p_Statistics->ifInUcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA);
+ p_Statistics->ifInMcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA);
+ p_Statistics->ifInBcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA);
+ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts
+ + p_Statistics->ifInMcastPkts
+ + p_Statistics->ifInBcastPkts;
+ p_Statistics->ifInDiscards = 0;
+ p_Statistics->ifInErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR);
+
+ p_Statistics->ifOutOctets = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT);
+ p_Statistics->ifOutUcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA);
+ p_Statistics->ifOutMcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA);
+ p_Statistics->ifOutBcastPkts = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA);
+ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts
+ + p_Statistics->ifOutMcastPkts
+ + p_Statistics->ifOutBcastPkts;
+ p_Statistics->ifOutDiscards = 0;
+ p_Statistics->ifOutErrors = memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TERR);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacResetCounters (t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ memac_reset_counter(p_Memac->p_MemMap);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *) h_Memac;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ 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 < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ if (p_Memac->indAddrRegUsed[paddrNum])
+ if (p_Memac->paddr[paddrNum] == ethAddr)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+
+ /* Find first unused PADDR */
+ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ if (!(p_Memac->indAddrRegUsed[paddrNum]))
+ {
+ /* mark this PADDR as used */
+ p_Memac->indAddrRegUsed[paddrNum] = TRUE;
+ /* store address */
+ p_Memac->paddr[paddrNum] = ethAddr;
+
+ /* put in hardware */
+ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum);
+ p_Memac->numOfIndAddrInRegs++;
+
+ return E_OK;
+ }
+
+ /* No free PADDR */
+ RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *) h_Memac;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* Find used PADDR containing this address */
+ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if ((p_Memac->indAddrRegUsed[paddrNum]) &&
+ (p_Memac->paddr[paddrNum] == ethAddr))
+ {
+ /* mark this PADDR as not used */
+ p_Memac->indAddrRegUsed[paddrNum] = FALSE;
+ /* clear in hardware */
+ memac_hardware_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum);
+ p_Memac->numOfIndAddrInRegs--;
+
+ return E_OK;
+ }
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ t_EthHashEntry *p_HashEntry;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (!(ethAddr & GROUP_ADDRESS))
+ /* Unicast addresses not supported in hash */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
+
+ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
+
+ /* 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_Memac->p_MulticastAddrHash->p_Lsts[hash]));
+ memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ t_EthHashEntry *p_HashEntry = NULL;
+ t_List *p_Pos;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
+
+ LIST_FOR_EACH(p_Pos, &(p_Memac->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_Memac->p_MulticastAddrHash->p_Lsts[hash]))
+ memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN));
+
+ return E_OK;
+}
+
+
+/* ......................................................................... */
+
+static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Memac->exceptions |= bitMask;
+ else
+ p_Memac->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ memac_set_exception(p_Memac->p_MemMap, bitMask, enable);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0);
+
+ return memac_get_max_frame_length(p_Memac->p_MemMap);
+}
+
+/* ......................................................................... */
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static t_Error MemacDumpRegs(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_Memac->p_MemMap)
+ {
+ DUMP_TITLE(p_Memac->p_MemMap, ("mEMAC %d: ", p_Memac->macId));
+ DUMP_VAR(p_Memac->p_MemMap, command_config);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_l);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_u);
+ DUMP_VAR(p_Memac->p_MemMap, maxfrm);
+ DUMP_VAR(p_Memac->p_MemMap, hashtable_ctrl);
+ DUMP_VAR(p_Memac->p_MemMap, ievent);
+ DUMP_VAR(p_Memac->p_MemMap, tx_ipg_length);
+ DUMP_VAR(p_Memac->p_MemMap, imask);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, pause_quanta[i]);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, pause_thresh[i]);
+ }
+
+ DUMP_VAR(p_Memac->p_MemMap, rx_pause_status);
+
+ DUMP_SUBSTRUCT_ARRAY(i, MEMAC_NUM_OF_PADDRS)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_l);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_u);
+ }
+
+ DUMP_VAR(p_Memac->p_MemMap, lpwake_timer);
+ DUMP_VAR(p_Memac->p_MemMap, sleep_timer);
+ DUMP_VAR(p_Memac->p_MemMap, statn_config);
+ DUMP_VAR(p_Memac->p_MemMap, if_mode);
+ DUMP_VAR(p_Memac->p_MemMap, if_status);
+ DUMP_VAR(p_Memac->p_MemMap, hg_config);
+ DUMP_VAR(p_Memac->p_MemMap, hg_pause_quanta);
+ DUMP_VAR(p_Memac->p_MemMap, hg_pause_thresh);
+ DUMP_VAR(p_Memac->p_MemMap, hgrx_pause_status);
+ DUMP_VAR(p_Memac->p_MemMap, hg_fifos_status);
+ DUMP_VAR(p_Memac->p_MemMap, rhm);
+ DUMP_VAR(p_Memac->p_MemMap, thm);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+/*****************************************************************************/
+/* mEMAC Init & Free API */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacInit(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ struct memac_cfg *p_MemacDriverParam;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ uint8_t i, phyAddr;
+ t_EnetAddr ethAddr;
+ e_FmMacType portType;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ /* not needed! */
+ /*FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);*/
+
+ CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters);
+
+ p_MemacDriverParam = p_Memac->p_MemacDriverParam;
+
+ portType =
+ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+ /* First, reset the MAC if desired. */
+ if (p_MemacDriverParam->reset_on_init)
+ memac_reset(p_Memac->p_MemMap);
+
+ /* MAC Address */
+ MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr);
+ memac_hardware_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0);
+
+ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode);
+ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode);
+
+ memac_init(p_Memac->p_MemMap,
+ p_Memac->p_MemacDriverParam,
+ enet_interface,
+ enet_speed,
+ p_Memac->exceptions);
+
+ if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII)
+ {
+ /* Configure internal SGMII PHY */
+ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
+ SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR);
+ else
+ SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR);
+ }
+ else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII)
+ {
+ /* Configure 4 internal SGMII PHYs */
+ for (i = 0; i < 4; i++)
+ {
+ /* QSGMII PHY address occupies 3 upper bits of 5-bit
+ phyAddress; the lower 2 bits are used to extend
+ register address space and access each one of 4
+ ports inside QSGMII. */
+ phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
+ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
+ SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr);
+ else
+ SetupSgmiiInternalPhy(p_Memac, phyAddr);
+ }
+ }
+
+ /* Max Frame Length */
+ err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm,
+ portType,
+ p_Memac->fmMacControllerDriver.macId,
+ p_MemacDriverParam->max_frame_length);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED"));
+
+ p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Memac->p_MulticastAddrHash)
+ {
+ FreeInitResources(p_Memac);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Memac->p_UnicastAddrHash)
+ {
+ FreeInitResources(p_Memac);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
+ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
+ p_Memac->macId,
+ e_FM_INTR_TYPE_ERR,
+ MemacErrException,
+ p_Memac);
+
+
+ XX_Free(p_MemacDriverParam);
+ p_Memac->p_MemacDriverParam = NULL;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacFree(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+
+ FreeInitResources(p_Memac);
+
+ if (p_Memac->p_MemacDriverParam)
+ {
+ XX_Free(p_Memac->p_MemacDriverParam);
+ p_Memac->p_MemacDriverParam = NULL;
+ }
+ XX_Free(p_Memac);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
+{
+ p_FmMacControllerDriver->f_FM_MAC_Init = MemacInit;
+ p_FmMacControllerDriver->f_FM_MAC_Free = MemacFree;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = MemacConfigLoopback;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = MemacConfigMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = MemacConfigWan;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = MemacConfigPad;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is detected automatically */
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = MemacConfigLengthCheck;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigException = MemacConfigException;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = MemacConfigResetOnInit;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetException = MemacSetException;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = MemacEnable1588TimeStamp; /* always enabled */
+ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = MemacSetPromiscuous;
+ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = MemacAdjustLink;
+ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable = MemacEnable;
+ p_FmMacControllerDriver->f_FM_MAC_Disable = MemacDisable;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = MemacSetTxAutoPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = MemacSetTxPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = MemacSetRxIgnorePauseFrames;
+
+ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = MemacResetCounters;
+ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = MemacGetStatistics;
+
+ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = MemacModifyMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = MemacAddHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = MemacDelHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = MemacAddExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = MemacDelExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_GetId = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_GetVersion = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = MemacGetMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = MEMAC_MII_WritePhyReg;
+ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = MEMAC_MII_ReadPhyReg;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = MemacDumpRegs;
+#endif /* (defined(DEBUG_ERRORS) && ... */
+}
+
+
+/*****************************************************************************/
+/* mEMAC Config Main Entry */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam)
+{
+ t_Memac *p_Memac;
+ struct memac_cfg *p_MemacDriverParam;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
+
+ baseAddr = p_FmMacParam->baseAddr;
+ /* Allocate memory for the mEMAC data structure */
+ p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac));
+ if (!p_Memac)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure"));
+ return NULL;
+ }
+ memset(p_Memac, 0, sizeof(t_Memac));
+ InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver);
+
+ /* Allocate memory for the mEMAC driver parameters data structure */
+ p_MemacDriverParam = (struct memac_cfg *) XX_Malloc(sizeof(struct memac_cfg));
+ if (!p_MemacDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters"));
+ MemacFree(p_Memac);
+ return NULL;
+ }
+ memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Memac->p_MemacDriverParam = p_MemacDriverParam;
+
+ memac_defconfig(p_MemacDriverParam);
+
+ p_Memac->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+
+ p_Memac->p_MemMap = (struct memac_regs *)UINT_TO_PTR(baseAddr);
+ p_Memac->p_MiiMemMap = (t_MemacMiiAccessMemMap *)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET);
+
+ p_Memac->enetMode = p_FmMacParam->enetMode;
+ p_Memac->macId = p_FmMacParam->macId;
+ p_Memac->exceptions = MEMAC_default_exceptions;
+ p_Memac->f_Exception = p_FmMacParam->f_Exception;
+ p_Memac->f_Event = p_FmMacParam->f_Event;
+ p_Memac->h_App = p_FmMacParam->h_App;
+
+ return p_Memac;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h
new file mode 100644
index 0000000..e1c4c53
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 memac.h
+
+ @Description FM Multirate Ethernet MAC (mEMAC)
+*//***************************************************************************/
+#ifndef __MEMAC_H
+#define __MEMAC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "memac_mii_acc.h"
+#include "fm_mac.h"
+#include "fsl_fman_memac.h"
+
+
+#define MEMAC_default_exceptions ((uint32_t)(MEMAC_IMASK_TECC_ER | MEMAC_IMASK_RECC_ER))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_10G_1TX_ECC_ER: \
+ bitMask = MEMAC_IMASK_TECC_ER; break; \
+ case e_FM_MAC_EX_10G_RX_ECC_ER: \
+ bitMask = MEMAC_IMASK_RECC_ER; break; \
+ default: bitMask = 0;break;}
+
+
+typedef struct
+{
+ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct memac_regs *p_MemMap; /**< Pointer to MAC memory mapped registers */
+ t_MemacMiiAccessMemMap *p_MiiMemMap; /**< Pointer to MII memory mapped registers */
+ uint64_t addr; /**< MAC address of device */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[MEMAC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[MEMAC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ t_EthHash *p_MulticastAddrHash; /**< Pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /**< Pointer to driver's individual address hash table */
+ bool debugMode;
+ uint8_t macId;
+ uint32_t exceptions;
+ struct memac_cfg *p_MemacDriverParam;
+} t_Memac;
+
+
+/* Internal PHY access */
+#define PHY_MDIO_ADDR 0
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET 0x8000
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+
+#define MEMAC_TO_MII_OFFSET 0x030 /* Offset from the MEM map to the MDIO mem map */
+
+t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+
+#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c
new file mode 100644
index 0000000..be5b867
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "memac.h"
+#include "xx_ext.h"
+
+#include "fm_common.h"
+
+
+static void WritePhyReg10G(t_MemacMiiAccessMemMap *p_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ uint32_t tmpReg;
+
+ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmpReg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ change of data signal */
+ tmpReg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmpReg |= MDIO_CFG_ENC45;
+ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg);
+
+ /* Wait for command completion */
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Specify phy and register to be accessed */
+ WRITE_UINT32(p_MiiAccess->mdio_ctrl, phyAddr);
+ WRITE_UINT32(p_MiiAccess->mdio_addr, reg);
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Write data */
+ WRITE_UINT32(p_MiiAccess->mdio_data, data);
+ CORE_MemoryBarrier();
+
+ /* Wait for write transaction end */
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY)
+ XX_UDelay(1);
+}
+
+static uint32_t ReadPhyReg10G(t_MemacMiiAccessMemMap *p_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ uint32_t tmpReg;
+
+ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmpReg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ change of data signal */
+ tmpReg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmpReg |= MDIO_CFG_ENC45;
+ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg);
+
+ /* Wait for command completion */
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Specify phy and register to be accessed */
+ WRITE_UINT32(p_MiiAccess->mdio_ctrl, phyAddr);
+ WRITE_UINT32(p_MiiAccess->mdio_addr, reg);
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Read cycle */
+ tmpReg = phyAddr;
+ tmpReg |= MDIO_CTL_READ;
+ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg);
+ CORE_MemoryBarrier();
+
+ /* Wait for data to be available */
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY)
+ XX_UDelay(1);
+
+ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data);
+
+ /* Check if there was an error */
+ return GET_UINT32(p_MiiAccess->mdio_cfg);
+}
+
+static void WritePhyReg1G(t_MemacMiiAccessMemMap *p_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ uint32_t tmpReg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg);
+ tmpReg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg);
+
+ /* Wait for command completion */
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Write transaction */
+ tmpReg = (phyAddr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmpReg |= reg;
+ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_data, data);
+
+ CORE_MemoryBarrier();
+
+ /* Wait for write transaction to end */
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY)
+ XX_UDelay(1);
+}
+
+static uint32_t ReadPhyReg1G(t_MemacMiiAccessMemMap *p_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ uint32_t tmpReg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmpReg = GET_UINT32(p_MiiAccess->mdio_cfg);
+ tmpReg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg, tmpReg);
+
+ /* Wait for command completion */
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Read transaction */
+ tmpReg = (phyAddr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmpReg |= reg;
+ tmpReg |= MDIO_CTL_READ;
+ WRITE_UINT32(p_MiiAccess->mdio_ctrl, tmpReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg)) & MDIO_CFG_BSY)
+ XX_UDelay(1);
+
+ /* Wait for data to be available */
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MDIO_DATA_BSY)
+ XX_UDelay(1);
+
+ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data);
+
+ /* Check error */
+ return GET_UINT32(p_MiiAccess->mdio_cfg);
+}
+
+/*****************************************************************************/
+t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE);
+
+ /* Figure out interface type - 10G vs 1G.
+ In 10G interface both phyAddr and devAddr present. */
+ if (ENET_SPEED_FROM_MODE(p_Memac->enetMode) == e_ENET_SPEED_10000)
+ WritePhyReg10G(p_Memac->p_MiiMemMap, phyAddr, reg, data);
+ else
+ WritePhyReg1G(p_Memac->p_MiiMemMap, phyAddr, reg, data);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t ans;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE);
+
+ /* Figure out interface type - 10G vs 1G.
+ In 10G interface both phyAddr and devAddr present. */
+ if (ENET_SPEED_FROM_MODE(p_Memac->enetMode) == e_ENET_SPEED_10000)
+ ans = ReadPhyReg10G(p_Memac->p_MiiMemMap, phyAddr, reg, p_Data);
+ else
+ ans = ReadPhyReg1G(p_Memac->p_MiiMemMap, phyAddr, reg, p_Data);
+
+ if (ans & MDIO_CFG_READ_ERR)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgReg 0x%x",
+ ((phyAddr & 0xe0) >> 5), (phyAddr & 0x1f), reg, ans));
+
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h
new file mode 100644
index 0000000..dab4360
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __MEMAC_MII_ACC_H
+#define __MEMAC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0000ff80
+#define MDIO_CFG_CLK_DIV_SHIFT 7
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+typedef _Packed struct t_MemacMiiAccessMemMap
+{
+ volatile uint32_t mdio_cfg; /* 0x030 */
+ volatile uint32_t mdio_ctrl; /* 0x034 */
+ volatile uint32_t mdio_data; /* 0x038 */
+ volatile uint32_t mdio_addr; /* 0x03c */
+} _PackedType t_MemacMiiAccessMemMap ;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+#endif /* __MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c
new file mode 100644
index 0000000..522d64b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 "debug_ext.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "fsl_fman_tgec.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 /* (FM_MAX_NUM_OF_10G_MACS > 0) */
+
+ 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"));
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_Tgec->p_TgecDriverParam->no_length_check_enable)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(ethAddr, crc);
+
+ crc = GetMirror32(crc);
+
+ return crc;
+}
+
+/* ......................................................................... */
+
+static void TgecErrException(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ uint32_t event;
+ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap;
+
+ /* do not handle MDIO events */
+ event = tgec_get_event(p_TgecMemMap, ~(TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= tgec_get_interrupt_mask(p_TgecMemMap);
+
+ tgec_ack_event(p_TgecMemMap, event);
+
+ if (event & TGEC_IMASK_REM_FAULT)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_REM_FAULT);
+ if (event & TGEC_IMASK_LOC_FAULT)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_LOC_FAULT);
+ if (event & TGEC_IMASK_TX_ECC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & TGEC_IMASK_TX_FIFO_UNFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL);
+ if (event & TGEC_IMASK_TX_FIFO_OVFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL);
+ if (event & TGEC_IMASK_TX_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_ER);
+ if (event & TGEC_IMASK_RX_FIFO_OVFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL);
+ if (event & TGEC_IMASK_RX_ECC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
+ if (event & TGEC_IMASK_RX_JAB_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_JAB_FRM);
+ if (event & TGEC_IMASK_RX_OVRSZ_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_OVRSZ_FRM);
+ if (event & TGEC_IMASK_RX_RUNT_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_RUNT_FRM);
+ if (event & TGEC_IMASK_RX_FRAG_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FRAG_FRM);
+ if (event & TGEC_IMASK_RX_LEN_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_LEN_ER);
+ if (event & TGEC_IMASK_RX_CRC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_CRC_ER);
+ if (event & TGEC_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;
+ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap;
+
+ /* handle only MDIO events */
+ event = tgec_get_event(p_TgecMemMap, (TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= tgec_get_interrupt_mask(p_TgecMemMap);
+
+ tgec_ack_event(p_TgecMemMap, event);
+
+ if (event & TGEC_IMASK_MDIO_SCAN_EVENT)
+ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO);
+ if (event & TGEC_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;
+}
+
+
+/*****************************************************************************/
+/* 10G MAC API routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error TgecEnable(t_Handle h_Tgec, e_CommMode mode)
+{
+ 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);
+
+ tgec_enable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDisable (t_Handle h_Tgec, e_CommMode mode)
+{
+ 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);
+
+ tgec_disable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecSetPromiscuous(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);
+
+ tgec_set_promiscuous(p_Tgec->p_MemMap, newVal);
+
+ 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);
+
+ p_Tgec->p_TgecDriverParam->loopback_enable = 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->wan_mode_enable = 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->max_frame_length = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecConfigLengthCheck(t_Handle h_Tgec, bool newVal)
+{
+ 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->no_length_check_enable = !newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+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);
+
+ 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->skip_fman11_workaround = TRUE;
+
+ return E_OK;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+
+/*****************************************************************************/
+/* Tgec Run Time API functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+/* backward compatibility. will be removed in the future. */
+static t_Error TgecTxMacPause(t_Handle h_Tgec, uint16_t pauseTime)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+ tgec_tx_mac_pause(p_Tgec->p_MemMap, pauseTime);
+
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecSetTxPauseFrames(t_Handle h_Tgec,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ UNUSED(priority); UNUSED(threshTime);
+
+ tgec_tx_mac_pause(p_Tgec->p_MemMap, pauseTime);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecRxIgnoreMacPause(t_Handle h_Tgec, bool en)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ tgec_rx_ignore_mac_pause(p_Tgec->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecGetStatistics(t_Handle h_Tgec, t_FmMacStatistics *p_Statistics)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ struct tgec_regs *p_TgecMemMap;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_TgecMemMap = p_Tgec->p_MemMap;
+
+ p_Statistics->eStatPkts64 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R64);
+ p_Statistics->eStatPkts65to127 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R127);
+ p_Statistics->eStatPkts128to255 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R255);
+ p_Statistics->eStatPkts256to511 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R511);
+ p_Statistics->eStatPkts512to1023 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1023);
+ p_Statistics->eStatPkts1024to1518 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1518);
+ p_Statistics->eStatPkts1519to1522 = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1519X);
+/* */
+ p_Statistics->eStatFragments = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRFRG);
+ p_Statistics->eStatJabbers = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRJBR);
+
+ p_Statistics->eStatsDropEvents = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RDRP);
+ p_Statistics->eStatCRCAlignErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RALN);
+
+ p_Statistics->eStatUndersizePkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRUND);
+ p_Statistics->eStatOversizePkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TROVR);
+/* Pause */
+ p_Statistics->reStatPause = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RXPF);
+ p_Statistics->teStatPause = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TXPF);
+
+/* MIB II */
+ p_Statistics->ifInOctets = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_ROCT);
+ p_Statistics->ifInUcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RUCA);
+ p_Statistics->ifInMcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RMCA);
+ p_Statistics->ifInBcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RBCA);
+ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts
+ + p_Statistics->ifInMcastPkts
+ + p_Statistics->ifInBcastPkts;
+ p_Statistics->ifInDiscards = 0;
+ p_Statistics->ifInErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RERR);
+
+ p_Statistics->ifOutOctets = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TOCT);
+ p_Statistics->ifOutUcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TUCA);
+ p_Statistics->ifOutMcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TMCA);
+ p_Statistics->ifOutBcastPkts = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TBCA);
+ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts
+ + p_Statistics->ifOutMcastPkts
+ + p_Statistics->ifOutBcastPkts;
+ p_Statistics->ifOutDiscards = 0;
+ p_Statistics->ifOutErrors = tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TERR);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecEnable1588TimeStamp(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);
+
+ tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 1);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDisable1588TimeStamp(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);
+
+ tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 0);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecModifyMacAddress (t_Handle h_Tgec, t_EnetAddr *p_EnetAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);
+ tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)(*p_EnetAddr));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecResetCounters (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);
+
+ tgec_reset_stat(p_Tgec->p_MemMap);
+
+ 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);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ 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 */
+ tgec_add_addr_in_paddr(p_Tgec->p_MemMap, (uint8_t*)(*p_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_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* 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 */
+ tgec_clear_addr_in_paddr(p_Tgec->p_MemMap /*, 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_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_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (!(ethAddr & GROUP_ADDRESS))
+ /* Unicast addresses not supported in hash */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
+
+ /* CRC calculation */
+ crc = GetMacAddrHashCode(ethAddr);
+
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* 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]));
+ tgec_set_hash_table(p_Tgec->p_MemMap, (hash | TGEC_HASH_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_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_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
+
+ /* CRC calculation */
+ crc = GetMacAddrHashCode(ethAddr);
+
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* 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]))
+ tgec_set_hash_table(p_Tgec->p_MemMap, (hash & ~TGEC_HASH_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_INVALID_STATE);
+
+ 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;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ *macVersion = tgec_get_revision(p_Tgec->p_MemMap);
+
+ 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;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ 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"));
+
+ if (enable)
+ tgec_enable_interrupt(p_Tgec->p_MemMap, bitMask);
+ else
+ tgec_disable_interrupt(p_Tgec->p_MemMap, bitMask);
+
+ 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);
+ SANITY_CHECK_RETURN_VALUE(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE, 0);
+
+ return tgec_get_max_frame_len(p_Tgec->p_MemMap);
+}
+
+/* ......................................................................... */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+static t_Error TgecTxEccWorkaround(t_Tgec *p_Tgec)
+{
+ t_Error err;
+
+#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)
+ XX_Print("Applying 10G TX ECC workaround (10GMAC-A004) ... ");
+#endif /* (DEBUG_ERRORS > 0) */
+ /* enable and set promiscuous */
+ tgec_enable(p_Tgec->p_MemMap, TRUE, TRUE);
+ tgec_set_promiscuous(p_Tgec->p_MemMap, TRUE);
+ err = Fm10GTxEccWorkaround(p_Tgec->fmMacControllerDriver.h_Fm, p_Tgec->macId);
+ /* disable */
+ tgec_set_promiscuous(p_Tgec->p_MemMap, FALSE);
+ tgec_enable(p_Tgec->p_MemMap, FALSE, FALSE);
+#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)
+ if (err)
+ XX_Print("FAILED!\n");
+ else
+ XX_Print("done.\n");
+#endif /* (DEBUG_ERRORS > 0) */
+ tgec_reset_stat(p_Tgec->p_MemMap);
+
+ 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, command_config);
+ 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);
+ }
+
+ 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;
+ struct tgec_cfg *p_TgecDriverParam;
+ t_EnetAddr ethAddr;
+ 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->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &p_Tgec->fmMacControllerDriver.fmRevInfo);
+ CHECK_INIT_PARAMETERS(p_Tgec, CheckInitParameters);
+
+ p_TgecDriverParam = p_Tgec->p_TgecDriverParam;
+
+ MAKE_ENET_ADDR_FROM_UINT64(p_Tgec->addr, ethAddr);
+ tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)ethAddr);
+
+ /* interrupts */
+#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+ {
+ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <=2)
+ p_Tgec->exceptions &= ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT);
+ }
+#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <= 6 /*fixed for rev3 */)
+ {
+ if (!p_Tgec->p_TgecDriverParam->skip_fman11_workaround &&
+ ((err = TgecTxEccWorkaround(p_Tgec)) != E_OK))
+ {
+ FreeInitResources(p_Tgec);
+ REPORT_ERROR(MINOR, err, ("TgecTxEccWorkaround FAILED"));
+ }
+ }
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ err = tgec_init(p_Tgec->p_MemMap, p_TgecDriverParam, p_Tgec->exceptions);
+ if (err)
+ {
+ FreeInitResources(p_Tgec);
+ RETURN_ERROR(MAJOR, err, ("This TGEC version does not support the required i/f mode"));
+ }
+
+ /* Max Frame Length */
+ err = FmSetMacMaxFrame(p_Tgec->fmMacControllerDriver.h_Fm,
+ e_FM_MAC_10G,
+ p_Tgec->fmMacControllerDriver.macId,
+ p_TgecDriverParam->max_frame_length);
+ /* we consider having no IPC a non crasher... */
+
+#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ tgec_fm_tx_fifo_corruption_errata_10gmac_a007(p_Tgec->p_MemMap);
+#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
+
+ 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"));
+ }
+
+ 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_SetStatistics = NULL;
+ 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;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL;
+
+#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_RestartAutoneg = 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_SetTxPauseFrames = TgecSetTxPauseFrames;
+ 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;
+ struct tgec_cfg *p_TgecDriverParam;
+ uintptr_t baseAddr;
+
+ 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;
+ }
+ memset(p_Tgec, 0, sizeof(t_Tgec));
+ InitFmMacControllerDriver(&p_Tgec->fmMacControllerDriver);
+
+ /* allocate memory for the 10G MAC driver parameters data structure. */
+ p_TgecDriverParam = (struct tgec_cfg *) XX_Malloc(sizeof(struct tgec_cfg));
+ if (!p_TgecDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver parameters"));
+ TgecFree(p_Tgec);
+ return NULL;
+ }
+ memset(p_TgecDriverParam, 0, sizeof(struct tgec_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Tgec->p_TgecDriverParam = p_TgecDriverParam;
+
+ tgec_defconfig(p_TgecDriverParam);
+
+ p_Tgec->p_MemMap = (struct tgec_regs *)UINT_TO_PTR(baseAddr);
+ p_Tgec->p_MiiMemMap = (t_TgecMiiAccessMemMap *)UINT_TO_PTR(baseAddr + TGEC_TO_MII_OFFSET);
+ p_Tgec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+ 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;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h
new file mode 100644
index 0000000..2aa3923
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.h
+
+ @Description FM 10G MAC ...
+*//***************************************************************************/
+#ifndef __TGEC_H
+#define __TGEC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "enet_ext.h"
+
+#include "tgec_mii_acc.h"
+#include "fm_mac.h"
+
+
+#define DEFAULT_exceptions \
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \
+ TGEC_IMASK_REM_FAULT | \
+ TGEC_IMASK_LOC_FAULT | \
+ TGEC_IMASK_TX_ECC_ER | \
+ TGEC_IMASK_TX_FIFO_UNFL | \
+ TGEC_IMASK_TX_FIFO_OVFL | \
+ TGEC_IMASK_TX_ER | \
+ TGEC_IMASK_RX_FIFO_OVFL | \
+ TGEC_IMASK_RX_ECC_ER | \
+ TGEC_IMASK_RX_JAB_FRM | \
+ TGEC_IMASK_RX_OVRSZ_FRM | \
+ TGEC_IMASK_RX_RUNT_FRM | \
+ TGEC_IMASK_RX_FRAG_FRM | \
+ TGEC_IMASK_RX_CRC_ER | \
+ TGEC_IMASK_RX_ALIGN_ER))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO: \
+ bitMask = TGEC_IMASK_MDIO_SCAN_EVENT ; break; \
+ case e_FM_MAC_EX_10G_MDIO_CMD_CMPL: \
+ bitMask = TGEC_IMASK_MDIO_CMD_CMPL ; break; \
+ case e_FM_MAC_EX_10G_REM_FAULT: \
+ bitMask = TGEC_IMASK_REM_FAULT ; break; \
+ case e_FM_MAC_EX_10G_LOC_FAULT: \
+ bitMask = TGEC_IMASK_LOC_FAULT ; break; \
+ case e_FM_MAC_EX_10G_1TX_ECC_ER: \
+ bitMask = TGEC_IMASK_TX_ECC_ER ; break; \
+ case e_FM_MAC_EX_10G_TX_FIFO_UNFL: \
+ bitMask = TGEC_IMASK_TX_FIFO_UNFL ; break; \
+ case e_FM_MAC_EX_10G_TX_FIFO_OVFL: \
+ bitMask = TGEC_IMASK_TX_FIFO_OVFL ; break; \
+ case e_FM_MAC_EX_10G_TX_ER: \
+ bitMask = TGEC_IMASK_TX_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_FIFO_OVFL: \
+ bitMask = TGEC_IMASK_RX_FIFO_OVFL ; break; \
+ case e_FM_MAC_EX_10G_RX_ECC_ER: \
+ bitMask = TGEC_IMASK_RX_ECC_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_JAB_FRM: \
+ bitMask = TGEC_IMASK_RX_JAB_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_OVRSZ_FRM: \
+ bitMask = TGEC_IMASK_RX_OVRSZ_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_RUNT_FRM: \
+ bitMask = TGEC_IMASK_RX_RUNT_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_FRAG_FRM: \
+ bitMask = TGEC_IMASK_RX_FRAG_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_LEN_ER: \
+ bitMask = TGEC_IMASK_RX_LEN_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_CRC_ER: \
+ bitMask = TGEC_IMASK_RX_CRC_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_ALIGN_ER: \
+ bitMask = TGEC_IMASK_RX_ALIGN_ER ; break; \
+ default: bitMask = 0;break;}
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+#define TGEC_NUM_OF_PADDRS 1 /* number of pattern match registers (entries) */
+
+#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */
+
+#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits * 8 regs) */
+
+#define TGEC_TO_MII_OFFSET 0x1030 /* Offset from the MEM map to the MDIO mem map */
+
+/* 10-gigabit Ethernet MAC Controller ID (10GEC_ID) */
+#define TGEC_ID_ID 0xffff0000
+#define TGEC_ID_MAC_VERSION 0x0000FF00
+#define TGEC_ID_MAC_REV 0x000000ff
+
+
+typedef struct {
+ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct tgec_regs *p_MemMap; /**< pointer to 10G memory mapped registers. */
+ t_TgecMiiAccessMemMap *p_MiiMemMap; /**< pointer to MII memory mapped registers. */
+ uint64_t addr; /**< MAC address of device; */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[TGEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[TGEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ t_EthHash *p_MulticastAddrHash; /**< pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /**< pointer to driver's individual address hash table */
+ bool debugMode;
+ uint8_t macId;
+ uint32_t exceptions;
+ struct tgec_cfg *p_TgecDriverParam;
+} t_Tgec;
+
+
+t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+
+#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c
new file mode 100644
index 0000000..e0fafd1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "tgec.h"
+#include "xx_ext.h"
+
+#include "fm_common.h"
+
+
+/*****************************************************************************/
+t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_TgecMiiAccessMemMap *p_MiiAccess;
+ uint32_t cfgStatusReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ p_MiiAccess = p_Tgec->p_MiiMemMap;
+
+ /* Configure MII */
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+ cfgStatusReg &= ~MIIMCOM_DIV_MASK;
+ /* (one half of fm clock => 2.5Mhz) */
+ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr);
+
+ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_data, data);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY)
+ XX_UDelay (1);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_TgecMiiAccessMemMap *p_MiiAccess;
+ uint32_t cfgStatusReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ p_MiiAccess = p_Tgec->p_MiiMemMap;
+
+ /* Configure MII */
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+ cfgStatusReg &= ~MIIMCOM_DIV_MASK;
+ /* (one half of fm clock => 2.5Mhz) */
+ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr);
+
+ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, (uint32_t)(phyAddr | MIIMCOM_READ_CYCLE));
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY)
+ XX_UDelay (1);
+
+ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data);
+
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+
+ if (cfgStatusReg & MIIMIND_READ_ERROR)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgStatusReg 0x%x",
+ ((phyAddr & 0xe0)>>5), (phyAddr & 0x1f), reg, cfgStatusReg));
+
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h
new file mode 100644
index 0000000..645cdde
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __TGEC_MII_ACC_H
+#define __TGEC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_POST_INCREMENT 0x00004000
+#define MIIMCOM_READ_CYCLE 0x00008000
+#define MIIMCOM_SCAN_CYCLE 0x00000800
+#define MIIMCOM_PREAMBLE_DISABLE 0x00000400
+
+#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0
+#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1
+#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2
+#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3
+
+#define MIIMCOM_DIV_MASK 0x0000ff00
+#define MIIMCOM_DIV_SHIFT 8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_READ_ERROR 0x00000002
+
+#define MIIDATA_BUSY 0x80000000
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+typedef _Packed struct t_TgecMiiAccessMemMap
+{
+ volatile uint32_t mdio_cfg_status; /* 0x030 */
+ volatile uint32_t mdio_command; /* 0x034 */
+ volatile uint32_t mdio_data; /* 0x038 */
+ volatile uint32_t mdio_regaddr; /* 0x03c */
+} _PackedType t_TgecMiiAccessMemMap ;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+#endif /* __TGEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile
new file mode 100644
index 0000000..e96de26
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+
+obj-y += fsl-ncsw-PFM1.o
+
+fsl-ncsw-PFM1-objs := fm.o fm_muram.o
+
+obj-y += MAC/
+obj-y += Pcd/
+obj-y += SP/
+obj-y += Port/
+obj-y += HC/
+obj-y += Rtc/
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile
new file mode 100644
index 0000000..70c7d7e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Pcd.o
+
+fsl-ncsw-Pcd-objs := fman_kg.o fman_prs.o fm_cc.o fm_kg.o fm_pcd.o fm_plcr.o fm_prs.o fm_manip.o
+
+ifeq ($(CONFIG_FMAN_T4240),y)
+fsl-ncsw-Pcd-objs += fm_replic.o
+endif
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h
new file mode 100644
index 0000000..335ee68
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 crc64.h
+
+ @Description brief This file contains the CRC64 Table, and __inline__
+ functions used for calculating crc.
+*//***************************************************************************/
+#ifndef __CRC64_H
+#define __CRC64_H
+
+#include "std_ext.h"
+
+
+#define BITS_PER_BYTE 8
+
+#define CRC64_EXPON_ECMA_182 0xC96C5795D7870F42ULL
+#define CRC64_DEFAULT_INITVAL 0xFFFFFFFFFFFFFFFFULL
+
+#define CRC64_BYTE_MASK 0xFF
+#define CRC64_TABLE_ENTRIES ( 1 << BITS_PER_BYTE )
+#define CRC64_ODD_MASK 1
+
+
+/**
+ \brief '64 bit crc' Table
+ */
+struct crc64_t {
+ uint64_t initial; /**< Initial seed */
+ uint64_t table[CRC64_TABLE_ENTRIES]; /**< CRC table entries */
+};
+
+
+static struct crc64_t CRC64_ECMA_182 = {
+ CRC64_DEFAULT_INITVAL,
+ {
+ 0x0000000000000000ULL,
+ 0xb32e4cbe03a75f6fULL,
+ 0xf4843657a840a05bULL,
+ 0x47aa7ae9abe7ff34ULL,
+ 0x7bd0c384ff8f5e33ULL,
+ 0xc8fe8f3afc28015cULL,
+ 0x8f54f5d357cffe68ULL,
+ 0x3c7ab96d5468a107ULL,
+ 0xf7a18709ff1ebc66ULL,
+ 0x448fcbb7fcb9e309ULL,
+ 0x0325b15e575e1c3dULL,
+ 0xb00bfde054f94352ULL,
+ 0x8c71448d0091e255ULL,
+ 0x3f5f08330336bd3aULL,
+ 0x78f572daa8d1420eULL,
+ 0xcbdb3e64ab761d61ULL,
+ 0x7d9ba13851336649ULL,
+ 0xceb5ed8652943926ULL,
+ 0x891f976ff973c612ULL,
+ 0x3a31dbd1fad4997dULL,
+ 0x064b62bcaebc387aULL,
+ 0xb5652e02ad1b6715ULL,
+ 0xf2cf54eb06fc9821ULL,
+ 0x41e11855055bc74eULL,
+ 0x8a3a2631ae2dda2fULL,
+ 0x39146a8fad8a8540ULL,
+ 0x7ebe1066066d7a74ULL,
+ 0xcd905cd805ca251bULL,
+ 0xf1eae5b551a2841cULL,
+ 0x42c4a90b5205db73ULL,
+ 0x056ed3e2f9e22447ULL,
+ 0xb6409f5cfa457b28ULL,
+ 0xfb374270a266cc92ULL,
+ 0x48190ecea1c193fdULL,
+ 0x0fb374270a266cc9ULL,
+ 0xbc9d3899098133a6ULL,
+ 0x80e781f45de992a1ULL,
+ 0x33c9cd4a5e4ecdceULL,
+ 0x7463b7a3f5a932faULL,
+ 0xc74dfb1df60e6d95ULL,
+ 0x0c96c5795d7870f4ULL,
+ 0xbfb889c75edf2f9bULL,
+ 0xf812f32ef538d0afULL,
+ 0x4b3cbf90f69f8fc0ULL,
+ 0x774606fda2f72ec7ULL,
+ 0xc4684a43a15071a8ULL,
+ 0x83c230aa0ab78e9cULL,
+ 0x30ec7c140910d1f3ULL,
+ 0x86ace348f355aadbULL,
+ 0x3582aff6f0f2f5b4ULL,
+ 0x7228d51f5b150a80ULL,
+ 0xc10699a158b255efULL,
+ 0xfd7c20cc0cdaf4e8ULL,
+ 0x4e526c720f7dab87ULL,
+ 0x09f8169ba49a54b3ULL,
+ 0xbad65a25a73d0bdcULL,
+ 0x710d64410c4b16bdULL,
+ 0xc22328ff0fec49d2ULL,
+ 0x85895216a40bb6e6ULL,
+ 0x36a71ea8a7ace989ULL,
+ 0x0adda7c5f3c4488eULL,
+ 0xb9f3eb7bf06317e1ULL,
+ 0xfe5991925b84e8d5ULL,
+ 0x4d77dd2c5823b7baULL,
+ 0x64b62bcaebc387a1ULL,
+ 0xd7986774e864d8ceULL,
+ 0x90321d9d438327faULL,
+ 0x231c512340247895ULL,
+ 0x1f66e84e144cd992ULL,
+ 0xac48a4f017eb86fdULL,
+ 0xebe2de19bc0c79c9ULL,
+ 0x58cc92a7bfab26a6ULL,
+ 0x9317acc314dd3bc7ULL,
+ 0x2039e07d177a64a8ULL,
+ 0x67939a94bc9d9b9cULL,
+ 0xd4bdd62abf3ac4f3ULL,
+ 0xe8c76f47eb5265f4ULL,
+ 0x5be923f9e8f53a9bULL,
+ 0x1c4359104312c5afULL,
+ 0xaf6d15ae40b59ac0ULL,
+ 0x192d8af2baf0e1e8ULL,
+ 0xaa03c64cb957be87ULL,
+ 0xeda9bca512b041b3ULL,
+ 0x5e87f01b11171edcULL,
+ 0x62fd4976457fbfdbULL,
+ 0xd1d305c846d8e0b4ULL,
+ 0x96797f21ed3f1f80ULL,
+ 0x2557339fee9840efULL,
+ 0xee8c0dfb45ee5d8eULL,
+ 0x5da24145464902e1ULL,
+ 0x1a083bacedaefdd5ULL,
+ 0xa9267712ee09a2baULL,
+ 0x955cce7fba6103bdULL,
+ 0x267282c1b9c65cd2ULL,
+ 0x61d8f8281221a3e6ULL,
+ 0xd2f6b4961186fc89ULL,
+ 0x9f8169ba49a54b33ULL,
+ 0x2caf25044a02145cULL,
+ 0x6b055fede1e5eb68ULL,
+ 0xd82b1353e242b407ULL,
+ 0xe451aa3eb62a1500ULL,
+ 0x577fe680b58d4a6fULL,
+ 0x10d59c691e6ab55bULL,
+ 0xa3fbd0d71dcdea34ULL,
+ 0x6820eeb3b6bbf755ULL,
+ 0xdb0ea20db51ca83aULL,
+ 0x9ca4d8e41efb570eULL,
+ 0x2f8a945a1d5c0861ULL,
+ 0x13f02d374934a966ULL,
+ 0xa0de61894a93f609ULL,
+ 0xe7741b60e174093dULL,
+ 0x545a57dee2d35652ULL,
+ 0xe21ac88218962d7aULL,
+ 0x5134843c1b317215ULL,
+ 0x169efed5b0d68d21ULL,
+ 0xa5b0b26bb371d24eULL,
+ 0x99ca0b06e7197349ULL,
+ 0x2ae447b8e4be2c26ULL,
+ 0x6d4e3d514f59d312ULL,
+ 0xde6071ef4cfe8c7dULL,
+ 0x15bb4f8be788911cULL,
+ 0xa6950335e42fce73ULL,
+ 0xe13f79dc4fc83147ULL,
+ 0x521135624c6f6e28ULL,
+ 0x6e6b8c0f1807cf2fULL,
+ 0xdd45c0b11ba09040ULL,
+ 0x9aefba58b0476f74ULL,
+ 0x29c1f6e6b3e0301bULL,
+ 0xc96c5795d7870f42ULL,
+ 0x7a421b2bd420502dULL,
+ 0x3de861c27fc7af19ULL,
+ 0x8ec62d7c7c60f076ULL,
+ 0xb2bc941128085171ULL,
+ 0x0192d8af2baf0e1eULL,
+ 0x4638a2468048f12aULL,
+ 0xf516eef883efae45ULL,
+ 0x3ecdd09c2899b324ULL,
+ 0x8de39c222b3eec4bULL,
+ 0xca49e6cb80d9137fULL,
+ 0x7967aa75837e4c10ULL,
+ 0x451d1318d716ed17ULL,
+ 0xf6335fa6d4b1b278ULL,
+ 0xb199254f7f564d4cULL,
+ 0x02b769f17cf11223ULL,
+ 0xb4f7f6ad86b4690bULL,
+ 0x07d9ba1385133664ULL,
+ 0x4073c0fa2ef4c950ULL,
+ 0xf35d8c442d53963fULL,
+ 0xcf273529793b3738ULL,
+ 0x7c0979977a9c6857ULL,
+ 0x3ba3037ed17b9763ULL,
+ 0x888d4fc0d2dcc80cULL,
+ 0x435671a479aad56dULL,
+ 0xf0783d1a7a0d8a02ULL,
+ 0xb7d247f3d1ea7536ULL,
+ 0x04fc0b4dd24d2a59ULL,
+ 0x3886b22086258b5eULL,
+ 0x8ba8fe9e8582d431ULL,
+ 0xcc0284772e652b05ULL,
+ 0x7f2cc8c92dc2746aULL,
+ 0x325b15e575e1c3d0ULL,
+ 0x8175595b76469cbfULL,
+ 0xc6df23b2dda1638bULL,
+ 0x75f16f0cde063ce4ULL,
+ 0x498bd6618a6e9de3ULL,
+ 0xfaa59adf89c9c28cULL,
+ 0xbd0fe036222e3db8ULL,
+ 0x0e21ac88218962d7ULL,
+ 0xc5fa92ec8aff7fb6ULL,
+ 0x76d4de52895820d9ULL,
+ 0x317ea4bb22bfdfedULL,
+ 0x8250e80521188082ULL,
+ 0xbe2a516875702185ULL,
+ 0x0d041dd676d77eeaULL,
+ 0x4aae673fdd3081deULL,
+ 0xf9802b81de97deb1ULL,
+ 0x4fc0b4dd24d2a599ULL,
+ 0xfceef8632775faf6ULL,
+ 0xbb44828a8c9205c2ULL,
+ 0x086ace348f355aadULL,
+ 0x34107759db5dfbaaULL,
+ 0x873e3be7d8faa4c5ULL,
+ 0xc094410e731d5bf1ULL,
+ 0x73ba0db070ba049eULL,
+ 0xb86133d4dbcc19ffULL,
+ 0x0b4f7f6ad86b4690ULL,
+ 0x4ce50583738cb9a4ULL,
+ 0xffcb493d702be6cbULL,
+ 0xc3b1f050244347ccULL,
+ 0x709fbcee27e418a3ULL,
+ 0x3735c6078c03e797ULL,
+ 0x841b8ab98fa4b8f8ULL,
+ 0xadda7c5f3c4488e3ULL,
+ 0x1ef430e13fe3d78cULL,
+ 0x595e4a08940428b8ULL,
+ 0xea7006b697a377d7ULL,
+ 0xd60abfdbc3cbd6d0ULL,
+ 0x6524f365c06c89bfULL,
+ 0x228e898c6b8b768bULL,
+ 0x91a0c532682c29e4ULL,
+ 0x5a7bfb56c35a3485ULL,
+ 0xe955b7e8c0fd6beaULL,
+ 0xaeffcd016b1a94deULL,
+ 0x1dd181bf68bdcbb1ULL,
+ 0x21ab38d23cd56ab6ULL,
+ 0x9285746c3f7235d9ULL,
+ 0xd52f0e859495caedULL,
+ 0x6601423b97329582ULL,
+ 0xd041dd676d77eeaaULL,
+ 0x636f91d96ed0b1c5ULL,
+ 0x24c5eb30c5374ef1ULL,
+ 0x97eba78ec690119eULL,
+ 0xab911ee392f8b099ULL,
+ 0x18bf525d915feff6ULL,
+ 0x5f1528b43ab810c2ULL,
+ 0xec3b640a391f4fadULL,
+ 0x27e05a6e926952ccULL,
+ 0x94ce16d091ce0da3ULL,
+ 0xd3646c393a29f297ULL,
+ 0x604a2087398eadf8ULL,
+ 0x5c3099ea6de60cffULL,
+ 0xef1ed5546e415390ULL,
+ 0xa8b4afbdc5a6aca4ULL,
+ 0x1b9ae303c601f3cbULL,
+ 0x56ed3e2f9e224471ULL,
+ 0xe5c372919d851b1eULL,
+ 0xa26908783662e42aULL,
+ 0x114744c635c5bb45ULL,
+ 0x2d3dfdab61ad1a42ULL,
+ 0x9e13b115620a452dULL,
+ 0xd9b9cbfcc9edba19ULL,
+ 0x6a978742ca4ae576ULL,
+ 0xa14cb926613cf817ULL,
+ 0x1262f598629ba778ULL,
+ 0x55c88f71c97c584cULL,
+ 0xe6e6c3cfcadb0723ULL,
+ 0xda9c7aa29eb3a624ULL,
+ 0x69b2361c9d14f94bULL,
+ 0x2e184cf536f3067fULL,
+ 0x9d36004b35545910ULL,
+ 0x2b769f17cf112238ULL,
+ 0x9858d3a9ccb67d57ULL,
+ 0xdff2a94067518263ULL,
+ 0x6cdce5fe64f6dd0cULL,
+ 0x50a65c93309e7c0bULL,
+ 0xe388102d33392364ULL,
+ 0xa4226ac498dedc50ULL,
+ 0x170c267a9b79833fULL,
+ 0xdcd7181e300f9e5eULL,
+ 0x6ff954a033a8c131ULL,
+ 0x28532e49984f3e05ULL,
+ 0x9b7d62f79be8616aULL,
+ 0xa707db9acf80c06dULL,
+ 0x14299724cc279f02ULL,
+ 0x5383edcd67c06036ULL,
+ 0xe0ada17364673f59ULL
+ }
+};
+
+
+/**
+ \brief Initializes the crc seed
+ */
+static __inline__ uint64_t crc64_init(void)
+{
+ return CRC64_ECMA_182.initial;
+}
+
+/**
+ \brief Computes 64 bit the crc
+ \param[in] data Pointer to the Data in the frame
+ \param[in] len Length of the Data
+ \param[in] crc seed
+ \return calculated crc
+ */
+static __inline__ uint64_t crc64_compute(void const *data,
+ uint32_t len,
+ uint64_t seed)
+{
+ uint32_t i;
+ uint64_t crc = seed;
+ uint8_t *bdata = (uint8_t *) data;
+
+ for (i = 0; i < len; i++)
+ crc =
+ CRC64_ECMA_182.
+ table[(crc ^ *bdata++) & CRC64_BYTE_MASK] ^ (crc >> 8);
+
+ return crc;
+}
+
+
+#endif /* __CRC64_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c
new file mode 100644
index 0000000..85810a9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c
@@ -0,0 +1,6940 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_cc.c
+
+ @Description FM Coarse Classifier implementation
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_cc.h"
+#include "crc64.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+
+static t_Error CcRootTryLock(t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ ASSERT_COND(h_FmPcdCcTree);
+
+ if (FmPcdLockTryLock(p_FmPcdCcTree->p_Lock))
+ return E_OK;
+
+ return ERROR_CODE(E_BUSY);
+}
+
+static void CcRootReleaseLock(t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ ASSERT_COND(h_FmPcdCcTree);
+
+ FmPcdLockUnlock(p_FmPcdCcTree->p_Lock);
+}
+
+static void UpdateNodeOwner(t_FmPcdCcNode *p_CcNode, bool add)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_CcNode);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (add)
+ p_CcNode->owners++;
+ else
+ {
+ ASSERT_COND(p_CcNode->owners);
+ p_CcNode->owners--;
+ }
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+}
+
+static __inline__ t_FmPcdStatsObj* DequeueStatsObj(t_List *p_List)
+{
+ t_FmPcdStatsObj *p_StatsObj = NULL;
+ t_List *p_Next;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_Next = LIST_FIRST(p_List);
+ p_StatsObj = LIST_OBJECT(p_Next, t_FmPcdStatsObj, node);
+ ASSERT_COND(p_StatsObj);
+ LIST_DelAndInit(p_Next);
+ }
+
+ return p_StatsObj;
+}
+
+static __inline__ void EnqueueStatsObj(t_List *p_List,
+ t_FmPcdStatsObj *p_StatsObj)
+{
+ LIST_AddToTail(&p_StatsObj->node, p_List);
+}
+
+static void FreeStatObjects(t_List *p_List,
+ t_Handle h_FmMuram)
+{
+ t_FmPcdStatsObj *p_StatsObj;
+
+ while (!LIST_IsEmpty(p_List))
+ {
+ p_StatsObj = DequeueStatsObj(p_List);
+ ASSERT_COND(p_StatsObj);
+
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
+
+ XX_Free(p_StatsObj);
+ }
+}
+
+static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode)
+{
+ t_FmPcdStatsObj* p_StatsObj;
+ t_Handle h_FmMuram;
+
+ ASSERT_COND(p_CcNode);
+
+ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
+ upon node initialization */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ p_StatsObj = DequeueStatsObj(&p_CcNode->availableStatsLst);
+ }
+ else
+ {
+ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
+ ASSERT_COND(h_FmMuram);
+
+ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
+ if (!p_StatsObj)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("statistics object"));
+ return NULL;
+ }
+
+ p_StatsObj->h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_StatsObj->h_StatsAd)
+ {
+ XX_Free(p_StatsObj);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs"));
+ return NULL;
+ }
+ IOMemSet32(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ p_CcNode->countersArraySize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_StatsObj->h_StatsCounters)
+ {
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ XX_Free(p_StatsObj);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters"));
+ return NULL;
+ }
+ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
+ }
+
+ return p_StatsObj;
+}
+
+static void PutStatsObj(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdStatsObj *p_StatsObj)
+{
+ t_Handle h_FmMuram;
+
+ ASSERT_COND(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
+ upon node initialization and now will be enqueued back to the list */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ /* Nullify counters */
+ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
+
+ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
+ }
+ else
+ {
+ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
+ ASSERT_COND(h_FmMuram);
+
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
+
+ XX_Free(p_StatsObj);
+ }
+}
+
+static void SetStatsCounters(t_AdOfTypeStats *p_StatsAd,
+ uint32_t statsCountersAddr)
+{
+ uint32_t tmp = (statsCountersAddr & FM_PCD_AD_STATS_COUNTERS_ADDR_MASK);
+
+ WRITE_UINT32(p_StatsAd->statsTableAddr, tmp);
+}
+
+
+static void UpdateStatsAd(t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_Handle h_Ad,
+ uint64_t physicalMuramBase)
+{
+ t_AdOfTypeStats *p_StatsAd;
+ uint32_t statsCountersAddr, nextActionAddr, tmp;
+#if (DPAA_VERSION >= 11)
+ uint32_t frameLengthRangesAddr;
+#endif /* (DPAA_VERSION >= 11) */
+
+ p_StatsAd = (t_AdOfTypeStats *)p_FmPcdCcStatsParams->h_StatsAd;
+
+ tmp = FM_PCD_AD_STATS_TYPE;
+
+#if (DPAA_VERSION >= 11)
+ if (p_FmPcdCcStatsParams->h_StatsFLRs)
+ {
+ frameLengthRangesAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsFLRs) - physicalMuramBase));
+ tmp |= (frameLengthRangesAddr & FM_PCD_AD_STATS_FLR_ADDR_MASK);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_StatsAd->profileTableAddr, tmp);
+
+ nextActionAddr = (uint32_t)((XX_VirtToPhys(h_Ad) - physicalMuramBase));
+ tmp = 0;
+ tmp |= (uint32_t)((nextActionAddr << FM_PCD_AD_STATS_NEXT_ACTION_SHIFT) & FM_PCD_AD_STATS_NEXT_ACTION_MASK);
+ tmp |= (FM_PCD_AD_STATS_NAD_EN | FM_PCD_AD_STATS_OP_CODE);
+
+#if (DPAA_VERSION >= 11)
+ if (p_FmPcdCcStatsParams->h_StatsFLRs)
+ tmp |= FM_PCD_AD_STATS_FLR_EN;
+#endif /* (DPAA_VERSION >= 11) */
+
+ WRITE_UINT32(p_StatsAd->nextActionIndx, tmp);
+
+ statsCountersAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsCounters) - physicalMuramBase));
+ SetStatsCounters(p_StatsAd, statsCountersAddr);
+}
+
+static void FillAdOfTypeContLookup(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_Handle h_FmPcd,
+ t_Handle p_CcNode,
+ t_Handle h_Manip,
+ t_Handle h_FrmReplic)
+{
+ t_FmPcdCcNode *p_Node = (t_FmPcdCcNode *)p_CcNode;
+ t_AdOfTypeContLookup *p_AdContLookup = (t_AdOfTypeContLookup *)h_Ad;
+ t_Handle h_TmpAd;
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t tmpReg32;
+ t_Handle p_AdNewPtr = NULL;
+
+ UNUSED(h_Manip);
+ UNUSED(h_FrmReplic);
+
+ /* there are 3 cases handled in this routine of building a "Continue lookup" type AD.
+ * Case 1: No Manip. The action descriptor is built within the match table.
+ * p_AdResult = p_AdNewPtr;
+ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
+ * either in the FmPcdManipUpdateAdResultForCc routine or it was already
+ * initialized and returned here.
+ * p_AdResult (within the match table) will be initialized after
+ * this routine returns and point to the existing AD.
+ * Case 3: Manip exists. The action descriptor is built within the match table.
+ * FmPcdManipUpdateAdContLookupForCc returns a NULL p_AdNewPtr.
+ */
+
+ /* As default, the "new" ptr is the current one. i.e. the content of the result
+ * AD will be written into the match table itself (case (1))*/
+ p_AdNewPtr = p_AdContLookup;
+
+ /* Initialize an action descriptor, if current statistics mode requires an Ad */
+ if (p_FmPcdCcStatsParams)
+ {
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
+
+ /* Swapping addresses between statistics Ad and the current lookup AD */
+ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
+ p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
+ h_Ad = h_TmpAd;
+
+ p_AdNewPtr = h_Ad;
+ p_AdContLookup = h_Ad;
+
+ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
+ UpdateStatsAd(p_FmPcdCcStatsParams,
+ h_Ad,
+ p_FmPcd->physicalMuramBase);
+ }
+
+#if DPAA_VERSION >= 11
+ if (h_Manip && h_FrmReplic)
+ FmPcdManipUpdateAdContLookupForCc(h_Manip,
+ h_Ad,
+ &p_AdNewPtr,
+ (uint32_t)((XX_VirtToPhys(FrmReplicGroupGetSourceTableDescriptor(h_FrmReplic)) - p_FmPcd->physicalMuramBase)));
+ else if (h_FrmReplic)
+ FrmReplicGroupUpdateAd(h_FrmReplic, h_Ad, &p_AdNewPtr);
+ else
+#endif /* (DPAA_VERSION >= 11) */
+ if (h_Manip)
+ FmPcdManipUpdateAdContLookupForCc(h_Manip,
+ h_Ad,
+ &p_AdNewPtr,
+
+#ifdef FM_CAPWAP_SUPPORT
+ /*no check for opcode of manip - this step can be reached only with capwap_applic_specific*/
+ (uint32_t)((XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase))
+#else /* not FM_CAPWAP_SUPPORT */
+ (uint32_t)((XX_VirtToPhys(p_Node->h_Ad) - p_FmPcd->physicalMuramBase))
+#endif /* not FM_CAPWAP_SUPPORT */
+ );
+
+ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
+ if (p_AdNewPtr)
+ {
+ /* cases (1) & (2) */
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= p_Node->sizeOfExtraction ? ((p_Node->sizeOfExtraction - 1) << 24) : 0;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_AdContLookup->ccAdBase, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= p_Node->numOfKeys << 24;
+ tmpReg32 |= (p_Node->lclMask ? FM_PCD_AD_CONT_LOOKUP_LCL_MASK : 0);
+ tmpReg32 |= p_Node->h_KeysMatchTable ?
+ (uint32_t)(XX_VirtToPhys(p_Node->h_KeysMatchTable) - p_FmPcd->physicalMuramBase) : 0;
+ WRITE_UINT32(p_AdContLookup->matchTblPtr, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= p_Node->prsArrayOffset << 24;
+ tmpReg32 |= p_Node->offset << 16;
+ tmpReg32 |= p_Node->parseCode;
+ WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32);
+
+ Mem2IOCpy32((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, CC_GLBL_MASK_SIZE);
+ }
+}
+
+static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_CcNode);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (!p_CcNode->h_Ad)
+ {
+ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (!p_CcNode->h_Ad)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor"));
+
+ IOMemSet32(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ FillAdOfTypeContLookup(p_CcNode->h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_CcNode,
+ NULL,
+ NULL);
+ }
+ else
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ return E_OK;
+}
+
+static t_Error SetRequiredAction(t_Handle h_FmPcd,
+ uint32_t requiredAction,
+ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp,
+ t_Handle h_AdTmp,
+ uint16_t numOfEntries,
+ t_Handle h_Tree)
+{
+ t_AdOfTypeResult *p_AdTmp = (t_AdOfTypeResult *)h_AdTmp;
+ uint32_t tmpReg32;
+ t_Error err;
+ t_FmPcdCcNode *p_CcNode;
+ int i = 0;
+ uint16_t tmp = 0;
+ uint16_t profileId;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ t_CcNodeInformation ccNodeInfo;
+
+ for (i = 0; i < numOfEntries; i++)
+ {
+ if (i == 0)
+ h_AdTmp = PTR_MOVE(h_AdTmp, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ else
+ h_AdTmp = PTR_MOVE(h_AdTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ switch (p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.nextEngine)
+ {
+ case (e_FM_PCD_CC):
+ if (requiredAction)
+ {
+ p_CcNode = p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.ccParams.h_CcNode;
+ ASSERT_COND(p_CcNode);
+ if (p_CcNode->shadowAction == requiredAction)
+ break;
+ if ((requiredAction & UPDATE_CC_WITH_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_TREE))
+ {
+
+ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 0);
+ if (p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE)
+ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_DELETE_TREE;
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = h_Tree;
+ EnqueueNodeInfoToRelevantLst(&p_CcNode->ccTreesLst, &ccNodeInfo, NULL);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_TREE;
+ }
+ if ((requiredAction & UPDATE_CC_WITH_DELETE_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE))
+ {
+ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 1);
+ if (p_CcNode->shadowAction & UPDATE_CC_WITH_TREE)
+ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_TREE;
+ DequeueNodeInfoFromRelevantLst(&p_CcNode->ccTreesLst, h_Tree, NULL);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_DELETE_TREE;
+ }
+ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID)
+ tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ tmp = p_CcNode->numOfKeys;
+ err = SetRequiredAction(h_FmPcd,
+ requiredAction,
+ p_CcNode->keyAndNextEngineParams,
+ p_CcNode->h_AdTable,
+ tmp,
+ h_Tree);
+ if (err != E_OK)
+ return err;
+ p_CcNode->shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_KG):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd, physicalSchemeId);
+ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme."));
+ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this action scheme has to be direct."));
+ err = FmPcdKgCcGetSetParams(h_FmPcd, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme, requiredAction, 0);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_PLCR):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.overrideParams)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized"));
+ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.sharedProfile)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized"));
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, e_FM_PCD_PLCR_SHARED, NULL, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.newRelativeProfileId, &profileId);
+ if (err!= E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = FmPcdPlcrCcGetSetParams(h_FmPcd, profileId, requiredAction);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_DONE):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ tmpReg32 = GET_UINT32(p_AdTmp->nia);
+ if ((tmpReg32 & GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) != GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine was previously assigned not as PCD_DONE"));
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_AdTmp->nia, tmpReg32);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error ReleaseModifiedDataStructure(t_Handle h_FmPcd,
+ t_List *h_FmPcdOldPointersLst,
+ t_List *h_FmPcdNewPointersLst,
+ uint16_t numOfGoodChanges,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_List *p_Pos;
+ t_Error err = E_OK;
+ t_CcNodeInformation ccNodeInfo, *p_CcNodeInformation;
+ t_Handle h_Muram;
+ t_FmPcdCcNode *p_FmPcdCcNextNode;
+ t_List *p_UpdateLst;
+ uint32_t intFlags;
+
+ UNUSED(numOfGoodChanges);
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_AdditionalParams->h_CurrentNode,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdOldPointersLst,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdNewPointersLst,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((numOfGoodChanges == LIST_NumOfObjs(h_FmPcdOldPointersLst)),E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((1 == LIST_NumOfObjs(h_FmPcdNewPointersLst)),E_INVALID_STATE);
+
+ /* We don't update subtree of the new node with new tree because it was done in the previous stage */
+ if (p_AdditionalParams->h_NodeForAdd)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForAdd;
+
+ if (!p_AdditionalParams->tree)
+ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
+ else
+ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
+
+ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ if (p_CcNodeInformation)
+ p_CcNodeInformation->index++;
+ else
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(p_UpdateLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ if (p_AdditionalParams->h_ManipForAdd)
+ {
+ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd));
+
+ if (p_CcNodeInformation)
+ p_CcNodeInformation->index++;
+ else
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd),
+ &ccNodeInfo,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd));
+ }
+ }
+ }
+
+ if (p_AdditionalParams->h_NodeForRmv)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForRmv;
+
+ if (!p_AdditionalParams->tree)
+ {
+ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
+
+ while (!LIST_IsEmpty(&p_FmPcdCcNextNode->ccTreesLst))
+ {
+ p_Pos = LIST_NEXT(&p_FmPcdCcNextNode->ccTreesLst);
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+
+ err = SetRequiredAction(h_FmPcd,
+ UPDATE_CC_WITH_DELETE_TREE,
+ &((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
+ PTR_MOVE(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable, p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ }
+ }
+ else
+ {
+ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
+
+ err = SetRequiredAction(h_FmPcd,
+ UPDATE_CC_WITH_DELETE_TREE,
+ &((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
+ UINT_TO_PTR(((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->ccTreeBaseAddr + p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_AdditionalParams->h_CurrentNode);
+ }
+ if (err)
+ return err;
+
+ /* We remove from the subtree of the removed node tree because it wasn't done in the previous stage
+ Update ccPrevNodesLst or ccTreeIdLst of the removed node
+ Update of the node owner */
+ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ ASSERT_COND(p_CcNodeInformation);
+ ASSERT_COND(p_CcNodeInformation->index);
+
+ p_CcNodeInformation->index--;
+
+ if (p_CcNodeInformation->index == 0)
+ DequeueNodeInfoFromRelevantLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ UpdateNodeOwner(p_FmPcdCcNextNode, FALSE);
+
+ if (p_AdditionalParams->h_ManipForRmv)
+ {
+ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv));
+
+ ASSERT_COND(p_CcNodeInformation);
+ ASSERT_COND(p_CcNodeInformation->index);
+
+ p_CcNodeInformation->index--;
+
+ if (p_CcNodeInformation->index == 0)
+ DequeueNodeInfoFromRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv));
+ }
+ }
+
+ if (p_AdditionalParams->h_ManipForRmv)
+ FmPcdManipUpdateOwner(p_AdditionalParams->h_ManipForRmv, FALSE);
+
+ if (p_AdditionalParams->p_StatsObjForRmv)
+ PutStatsObj((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode),
+ p_AdditionalParams->p_StatsObjForRmv);
+
+#if (DPAA_VERSION >= 11)
+ if (p_AdditionalParams->h_FrmReplicForRmv)
+ FrmReplicGroupUpdateOwner(p_AdditionalParams->h_FrmReplicForRmv,
+ FALSE/* remove */);
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (!useShadowStructs)
+ {
+ h_Muram = FmPcdGetMuramHandle(h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ if ((p_AdditionalParams->tree &&
+ !((t_FmPcd *)h_FmPcd)->p_CcShadow) ||
+ (!p_AdditionalParams->tree &&
+ !((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->maxNumOfKeys))
+ {
+ /* We release new AD which was allocated and updated for copy from to actual AD */
+ p_Pos = LIST_FIRST(h_FmPcdNewPointersLst);
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ FM_MURAM_FreeMem(h_Muram, p_CcNodeInformation->h_CcNode);
+ }
+
+ /* Free Old data structure if it has to be freed - new data structure was allocated*/
+ if (p_AdditionalParams->p_AdTableOld)
+ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_AdTableOld);
+
+ if (p_AdditionalParams->p_KeysMatchTableOld)
+ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_KeysMatchTableOld);
+ }
+
+ /* Update current modified node with changed fields if it's required*/
+ if (!p_AdditionalParams->tree)
+ {
+ if (p_AdditionalParams->p_AdTableNew)
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable = p_AdditionalParams->p_AdTableNew;
+
+ if (p_AdditionalParams->p_KeysMatchTableNew)
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_KeysMatchTable = p_AdditionalParams->p_KeysMatchTableNew;
+
+ /* Locking node's spinlock before updating 'keys and next engine' structure,
+ as it maybe used to retrieve keys statistics */
+ intFlags = XX_LockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock);
+
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->numOfKeys = p_AdditionalParams->numOfKeys;
+
+ memcpy(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
+ &p_AdditionalParams->keyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams) * (CC_MAX_NUM_OF_KEYS));
+
+ XX_UnlockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock, intFlags);
+ }
+ else
+ {
+ uint8_t numEntries = ((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->numOfEntries;
+ ASSERT_COND(numEntries < FM_PCD_MAX_NUM_OF_CC_GROUPS);
+ memcpy(&((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
+ &p_AdditionalParams->keyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams) * numEntries);
+ }
+
+ ReleaseLst(h_FmPcdOldPointersLst);
+ ReleaseLst(h_FmPcdNewPointersLst);
+
+ XX_Free(p_AdditionalParams);
+
+ return E_OK;
+}
+
+static t_Handle BuildNewAd(t_Handle h_Ad,
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
+ t_FmPcdCcNode *p_CcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_FmPcdCcNodeTmp;
+
+ p_FmPcdCcNodeTmp = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
+ if (!p_FmPcdCcNodeTmp)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcNodeTmp"));
+ return NULL;
+ }
+ memset(p_FmPcdCcNodeTmp, 0, sizeof(t_FmPcdCcNode));
+
+ p_FmPcdCcNodeTmp->numOfKeys = p_FmPcdModifyCcKeyAdditionalParams->numOfKeys;
+ p_FmPcdCcNodeTmp->h_KeysMatchTable = p_FmPcdModifyCcKeyAdditionalParams->p_KeysMatchTableNew;
+ p_FmPcdCcNodeTmp->h_AdTable = p_FmPcdModifyCcKeyAdditionalParams->p_AdTableNew;
+
+ p_FmPcdCcNodeTmp->lclMask = p_CcNode->lclMask;
+ p_FmPcdCcNodeTmp->parseCode = p_CcNode->parseCode;
+ p_FmPcdCcNodeTmp->offset = p_CcNode->offset;
+ p_FmPcdCcNodeTmp->prsArrayOffset = p_CcNode->prsArrayOffset;
+ p_FmPcdCcNodeTmp->ctrlFlow = p_CcNode->ctrlFlow;
+ p_FmPcdCcNodeTmp->ccKeySizeAccExtraction = p_CcNode->ccKeySizeAccExtraction;
+ p_FmPcdCcNodeTmp->sizeOfExtraction = p_CcNode->sizeOfExtraction;
+ p_FmPcdCcNodeTmp->glblMaskSize = p_CcNode->glblMaskSize;
+ p_FmPcdCcNodeTmp->p_GlblMask = p_CcNode->p_GlblMask;
+
+ if (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ {
+ if (p_FmPcdCcNextEngineParams->h_Manip)
+ {
+ if (AllocAndFillAdForContLookupManip(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)!= E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+ FillAdOfTypeContLookup(h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_FmPcdCcNodeTmp,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ NULL);
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic))
+ {
+ FillAdOfTypeContLookup(h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_FmPcdCcNodeTmp,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ XX_Free(p_FmPcdCcNodeTmp);
+
+ return E_OK;
+}
+
+static t_Error DynamicChangeHc(t_Handle h_FmPcd,
+ t_List *h_OldPointersLst,
+ t_List *h_NewPointersLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_List *p_PosOld, *p_PosNew;
+ uint32_t oldAdAddrOffset, newAdAddrOffset;
+ uint16_t i = 0;
+ t_Error err = E_OK;
+ uint8_t numOfModifiedPtr;
+
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(h_OldPointersLst);
+ ASSERT_COND(h_NewPointersLst);
+
+ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst);
+
+ p_PosNew = LIST_FIRST(h_NewPointersLst);
+ p_PosOld = LIST_FIRST(h_OldPointersLst);
+
+ /* Retrieve address of new AD */
+ newAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, p_PosNew);
+ if (newAdAddrOffset == (uint32_t)ILLEGAL_BASE)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ 0,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("New AD address"));
+ }
+
+ for (i=0; i<numOfModifiedPtr; i++)
+ {
+ /* Retrieve address of current AD */
+ oldAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, p_PosOld);
+ if (oldAdAddrOffset == (uint32_t)ILLEGAL_BASE)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ i,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old AD address"));
+ }
+
+ /* Invoke host command to copy from new AD to old AD */
+ err = FmHcPcdCcDoDynamicChange(((t_FmPcd *)h_FmPcd)->h_Hc, oldAdAddrOffset, newAdAddrOffset);
+ if (err)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ i,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, err, ("For part of nodes changes are done - situation is danger"));
+ }
+
+ p_PosOld = LIST_NEXT(p_PosOld);
+ }
+
+ return E_OK;
+}
+
+static t_Error DoDynamicChange(t_Handle h_FmPcd,
+ t_List *h_OldPointersLst,
+ t_List *h_NewPointersLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode);
+ t_List *p_PosNew;
+ t_CcNodeInformation *p_CcNodeInfo;
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ t_Handle h_Ad;
+ uint32_t keySize;
+ t_Error err = E_OK;
+ uint8_t numOfModifiedPtr;
+
+ ASSERT_COND(h_FmPcd);
+
+ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_OldPointersLst) >= 1),E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_NewPointersLst) == 1),E_INVALID_STATE);
+
+ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
+
+ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst);
+
+ p_PosNew = LIST_FIRST(h_NewPointersLst);
+
+ /* Invoke host-command to copy from the new Ad to existing Ads */
+ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (useShadowStructs)
+ {
+ /* When the host-command above has ended, the old structures are 'free'and we can update
+ them by copying from the new shadow structures. */
+ if (p_CcNode->lclMask)
+ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
+ else
+ keySize = p_CcNode->ccKeySizeAccExtraction;
+
+ IO2IOCpy32(p_AdditionalParams->p_KeysMatchTableOld,
+ p_AdditionalParams->p_KeysMatchTableNew,
+ p_CcNode->maxNumOfKeys * keySize * sizeof (uint8_t));
+
+ IO2IOCpy32(p_AdditionalParams->p_AdTableOld,
+ p_AdditionalParams->p_AdTableNew,
+ (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE));
+
+ /* Retrieve the address of the allocated Ad */
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_PosNew);
+ h_Ad = p_CcNodeInfo->h_CcNode;
+
+ /* Build a new Ad that holds the old (now updated) structures */
+ p_AdditionalParams->p_KeysMatchTableNew = p_AdditionalParams->p_KeysMatchTableOld;
+ p_AdditionalParams->p_AdTableNew = p_AdditionalParams->p_AdTableOld;
+
+ nextEngineParams.nextEngine = e_FM_PCD_CC;
+ nextEngineParams.params.ccParams.h_CcNode = (t_Handle)p_CcNode;
+
+ BuildNewAd(h_Ad, p_AdditionalParams, p_CcNode, &nextEngineParams);
+
+ /* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */
+ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ numOfModifiedPtr,
+ p_AdditionalParams,
+ useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static bool IsCapwapApplSpecific(t_Handle h_Node)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_Node;
+ bool isManipForCapwapApplSpecificBuild = FALSE;
+ int i = 0;
+
+ ASSERT_COND(h_Node);
+ /* assumption that this function called only for INDEXED_FLOW_ID - so no miss*/
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ {
+ if ( p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip &&
+ FmPcdManipIsCapwapApplSpecific(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip))
+ {
+ isManipForCapwapApplSpecificBuild = TRUE;
+ break;
+ }
+ }
+ return isManipForCapwapApplSpecificBuild;
+
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error CcUpdateParam(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParams,
+ uint16_t numOfEntries,
+ t_Handle h_Ad,
+ bool validate,
+ uint16_t level,
+ t_Handle h_FmTree,
+ bool modify)
+{
+ t_FmPcdCcNode *p_CcNode;
+ t_Error err;
+ uint16_t tmp = 0;
+ int i = 0;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree;
+
+ level++;
+
+ if (p_CcTree->h_IpReassemblyManip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcTree->h_IpReassemblyManip,
+ NULL,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (numOfEntries)
+ {
+ for (i=0; i<numOfEntries; i++)
+ {
+ if (i == 0)
+ h_Ad = PTR_MOVE(h_Ad, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ else
+ h_Ad = PTR_MOVE(h_Ad, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ p_CcNode = p_CcKeyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+ ASSERT_COND(p_CcNode);
+
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ NULL,
+ h_FmPort,
+ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ h_Ad,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID)
+ tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ tmp = p_CcNode->numOfKeys;
+
+ err = CcUpdateParam(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcNode->keyAndNextEngineParams,
+ tmp,
+ p_CcNode->h_AdTable,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else
+ {
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ NULL,
+ h_FmPort,
+ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ h_Ad,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ }
+ }
+
+ return E_OK;
+}
+
+static ccPrivateInfo_t IcDefineCode(t_FmPcdCcNodeParams *p_CcNodeParam)
+{
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.action)
+ {
+ case (e_FM_PCD_ACTION_EXACT_MATCH):
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_KEY):
+ return CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH;
+ case (e_FM_PCD_EXTRACT_FROM_HASH):
+ return CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH;
+ default:
+ return CC_PRIVATE_INFO_NONE;
+ }
+
+ case (e_FM_PCD_ACTION_INDEXED_LOOKUP):
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HASH):
+ return CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP;
+ case (e_FM_PCD_EXTRACT_FROM_FLOW_ID):
+ return CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP;
+ default:
+ return CC_PRIVATE_INFO_NONE;
+ }
+
+ default:
+ break;
+ }
+
+ return CC_PRIVATE_INFO_NONE;
+}
+
+static t_CcNodeInformation * DequeueAdditionalInfoFromRelevantLst(t_List *p_List)
+{
+ t_CcNodeInformation *p_CcNodeInfo = NULL;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_List->p_Next);
+ LIST_DelAndInit(&p_CcNodeInfo->node);
+ }
+
+ return p_CcNodeInfo;
+}
+
+void ReleaseLst(t_List *p_List)
+{
+ t_CcNodeInformation *p_CcNodeInfo = NULL;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
+ while (p_CcNodeInfo)
+ {
+ XX_Free(p_CcNodeInfo);
+ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
+ }
+ }
+
+ LIST_Del(p_List);
+}
+
+static void DeleteNode(t_FmPcdCcNode *p_CcNode)
+{
+ uint32_t i;
+
+ if (!p_CcNode)
+ return;
+
+ if (p_CcNode->p_GlblMask)
+ {
+ XX_Free(p_CcNode->p_GlblMask);
+ p_CcNode->p_GlblMask = NULL;
+ }
+
+ if (p_CcNode->h_KeysMatchTable)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_KeysMatchTable);
+ p_CcNode->h_KeysMatchTable = NULL;
+ }
+
+ if (p_CcNode->h_AdTable)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_AdTable);
+ p_CcNode->h_AdTable = NULL;
+ }
+
+ if (p_CcNode->h_Ad)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_Ad);
+ p_CcNode->h_Ad = NULL;
+ }
+
+ if (p_CcNode->h_StatsFLRs)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_StatsFLRs);
+ p_CcNode->h_StatsFLRs = NULL;
+ }
+
+ if (p_CcNode->h_Spinlock)
+ {
+ XX_FreeSpinlock(p_CcNode->h_Spinlock);
+ p_CcNode->h_Spinlock = NULL;
+ }
+
+ /* Releasing all currently used statistics objects, including 'miss' entry */
+ for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
+ if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj)
+ PutStatsObj(p_CcNode, p_CcNode->keyAndNextEngineParams[i].p_StatsObj);
+
+ if (!LIST_IsEmpty(&p_CcNode->availableStatsLst))
+ {
+ t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
+
+ ASSERT_COND(h_FmMuram);
+
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ }
+
+ LIST_Del(&p_CcNode->availableStatsLst);
+
+ ReleaseLst(&p_CcNode->ccPrevNodesLst);
+ ReleaseLst(&p_CcNode->ccTreeIdLst);
+ ReleaseLst(&p_CcNode->ccTreesLst);
+
+ XX_Free(p_CcNode);
+}
+
+static void DeleteTree(t_FmPcdCcTree *p_FmPcdTree, t_FmPcd *p_FmPcd)
+{
+ if (p_FmPcdTree)
+ {
+ if (p_FmPcdTree->ccTreeBaseAddr)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), UINT_TO_PTR(p_FmPcdTree->ccTreeBaseAddr));
+ p_FmPcdTree->ccTreeBaseAddr = 0;
+ }
+
+ ReleaseLst(&p_FmPcdTree->fmPortsLst);
+
+ XX_Free(p_FmPcdTree);
+ }
+}
+
+static void GetCcExtractKeySize(uint8_t parseCodeRealSize, uint8_t *parseCodeCcSize)
+{
+ if ((parseCodeRealSize > 0) && (parseCodeRealSize < 2))
+ *parseCodeCcSize = 1;
+ else if (parseCodeRealSize == 2)
+ *parseCodeCcSize = 2;
+ else if ((parseCodeRealSize > 2) && (parseCodeRealSize <= 4))
+ *parseCodeCcSize = 4;
+ else if ((parseCodeRealSize > 4) && (parseCodeRealSize <= 8))
+ *parseCodeCcSize = 8;
+ else if ((parseCodeRealSize > 8) && (parseCodeRealSize <= 16))
+ *parseCodeCcSize = 16;
+ else if ((parseCodeRealSize > 16) && (parseCodeRealSize <= 24))
+ *parseCodeCcSize = 24;
+ else if ((parseCodeRealSize > 24) && (parseCodeRealSize <= 32))
+ *parseCodeCcSize = 32;
+ else if ((parseCodeRealSize > 32) && (parseCodeRealSize <= 40))
+ *parseCodeCcSize = 40;
+ else if ((parseCodeRealSize > 40) && (parseCodeRealSize <= 48))
+ *parseCodeCcSize = 48;
+ else if ((parseCodeRealSize > 48) && (parseCodeRealSize <= 56))
+ *parseCodeCcSize = 56;
+ else
+ *parseCodeCcSize = 0;
+}
+
+static void GetSizeHeaderField(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex index,
+ t_FmPcdFields field,
+ uint8_t *parseCodeRealSize)
+{
+ UNUSED(index);
+ switch (hdr)
+ {
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ *parseCodeRealSize = 6;
+ break;
+
+ case (NET_HEADER_FIELD_ETH_SA):
+ *parseCodeRealSize = 6;
+ break;
+
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported2"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported3"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_DST_IP | NET_HEADER_FIELD_IPv4_SRC_IP):
+ *parseCodeRealSize = 8;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_TTL):
+ *parseCodeRealSize = 1;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported4"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ *parseCodeRealSize = 16;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IP):
+ switch (field.ip)
+ {
+ case (NET_HEADER_FIELD_IP_DSCP):
+ case (NET_HEADER_FIELD_IP_PROTO):
+ *parseCodeRealSize = 1;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case ( NET_HEADER_FIELD_GRE_TYPE):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported6"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP):
+ *parseCodeRealSize = 8;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported7"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ *parseCodeRealSize = 2;
+ break;
+
+ case (NET_HEADER_FIELD_TCP_PORT_SRC | NET_HEADER_FIELD_TCP_PORT_DST):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported8"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ *parseCodeRealSize = 2;
+ break;
+
+ case (NET_HEADER_FIELD_UDP_PORT_SRC | NET_HEADER_FIELD_UDP_PORT_DST):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported9"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported10"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+}
+
+t_Error ValidateNextEngineParams(t_Handle h_FmPcd,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ e_FmPcdCcStatsMode statsMode)
+{
+ uint16_t absoluteProfileId;
+ t_Error err = E_OK;
+ uint8_t relativeSchemeId;
+
+ if ((statsMode == e_FM_PCD_CC_STATS_MODE_NONE) &&
+ (p_FmPcdCcNextEngineParams->statisticsEn))
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Statistics are requested for a key, but statistics mode was set"
+ "to 'NONE' upon initialization of this match table"));
+
+ switch (p_FmPcdCcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_INVALID):
+ err = E_NOT_SUPPORTED;
+ break;
+
+ case (e_FM_PCD_DONE):
+ if ((p_FmPcdCcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME) &&
+ p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ {
+ if (!p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("When overrideFqid is set, newFqid must not be zero"));
+ if (p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidForCtrlFlow must be between 1 and 2^24-1"));
+ }
+ break;
+
+ case (e_FM_PCD_KG):
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd,
+ FmPcdKgGetSchemeId(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme));
+ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("not valid schemeIndex in KG next engine param"));
+ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("CC Node may point only to a scheme that is always direct."));
+ break;
+
+ case (e_FM_PCD_PLCR):
+ if (p_FmPcdCcNextEngineParams->params.plcrParams.overrideParams)
+ {
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (p_FmPcdCcNextEngineParams->params.plcrParams.sharedProfile)
+ {
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd,
+ e_FM_PCD_PLCR_SHARED,
+ NULL,
+ p_FmPcdCcNextEngineParams->params.plcrParams.newRelativeProfileId,
+ &absoluteProfileId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Shared profile offset is out of range"));
+ if (!FmPcdPlcrIsProfileValid(h_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile"));
+ }
+ }
+ break;
+
+ case (e_FM_PCD_HASH):
+ p_FmPcdCcNextEngineParams->nextEngine = e_FM_PCD_CC;
+ case (e_FM_PCD_CC):
+ if (!p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER, ("handler to next Node is NULL"));
+ break;
+
+#if (DPAA_VERSION >= 11)
+ case (e_FM_PCD_FR):
+ if (!p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
+ err = E_NOT_SUPPORTED;
+ break;
+#endif /* (DPAA_VERSION >= 11) */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine is not correct"));
+ }
+
+
+ return err;
+}
+
+static uint8_t GetGenParseCode(t_Handle h_FmPcd,
+ e_FmPcdExtractFrom src,
+ uint32_t offset,
+ bool glblMask,
+ uint8_t *parseArrayOffset,
+ bool fromIc,
+ ccPrivateInfo_t icCode)
+{
+ UNUSED(h_FmPcd);
+
+ if (!fromIc)
+ {
+ switch (src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
+ if (glblMask)
+ return CC_PC_GENERIC_WITH_MASK ;
+ else
+ return CC_PC_GENERIC_WITHOUT_MASK;
+
+ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
+ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
+ if (offset)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ return CC_PC_ILLEGAL;
+ }
+ }
+ else
+ {
+ switch (icCode)
+ {
+ case (CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH):
+ *parseArrayOffset = 0x50;
+ return CC_PC_GENERIC_IC_GMASK;
+
+ case (CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH):
+ *parseArrayOffset = 0x48;
+ return CC_PC_GENERIC_IC_GMASK;
+
+ case (CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP):
+ *parseArrayOffset = 0x48;
+ return CC_PC_GENERIC_IC_HASH_INDEXED;
+
+ case (CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP):
+ *parseArrayOffset = 0x16;
+ return CC_PC_GENERIC_IC_HASH_INDEXED;
+
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ break;
+ }
+ }
+
+ return CC_PC_ILLEGAL;
+}
+
+static uint8_t GetFullFieldParseCode(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex index,
+ t_FmPcdFields field)
+{
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ return CC_PC_ILLEGAL;
+
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ return CC_PC_FF_MACDST;
+ case (NET_HEADER_FIELD_ETH_SA):
+ return CC_PC_FF_MACSRC;
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return CC_PC_FF_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_TCI1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_TCI2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_MPLS1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
+ return CC_PC_ILLEGAL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4IPTOS_TC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4IPTOS_TC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4PTYPE1;
+ if(index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4PTYPE2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4SRC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4SRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_SRC_IP | NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4SRC1_IPV4DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4SRC2_IPV4DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_TTL):
+ return CC_PC_FF_IPV4TTL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6PTYPE1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6PTYPE2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6SRC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6SRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
+ return CC_PC_FF_IPV6HOP_LIMIT;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IP):
+ switch (field.ip)
+ {
+ case (NET_HEADER_FIELD_IP_DSCP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPDSCP;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IP_PROTO):
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
+ return CC_PC_ILLEGAL;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case (NET_HEADER_FIELD_GRE_TYPE):
+ return CC_PC_FF_GREPTYPE;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ return CC_PC_FF_MINENCAP_PTYPE;
+
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return CC_PC_FF_MINENCAP_IPDST;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ return CC_PC_FF_MINENCAP_IPSRC;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return CC_PC_FF_MINENCAP_IPSRC_IPDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ return CC_PC_FF_L4PSRC;
+
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ return CC_PC_FF_L4PDST;
+
+ case (NET_HEADER_FIELD_TCP_PORT_DST | NET_HEADER_FIELD_TCP_PORT_SRC):
+ return CC_PC_FF_L4PSRC_L4PDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ return CC_PC_FF_PPPPID;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ return CC_PC_FF_L4PSRC;
+
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ return CC_PC_FF_L4PDST;
+
+ case (NET_HEADER_FIELD_UDP_PORT_DST | NET_HEADER_FIELD_UDP_PORT_SRC):
+ return CC_PC_FF_L4PSRC_L4PDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+}
+
+static uint8_t GetPrParseCode(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex hdrIndex,
+ uint32_t offset,
+ bool glblMask,
+ uint8_t *parseArrayOffset)
+{
+ bool offsetRelevant = FALSE;
+
+ if (offset)
+ offsetRelevant = TRUE;
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ return CC_PC_ILLEGAL;
+
+ case (HEADER_TYPE_ETH):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET;
+ break;
+
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ if (offset || glblMask)
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET;
+ else
+ return CC_PC_PR_SHIM1;
+ break;
+
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ if (offset || glblMask)
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET;
+ else
+ return CC_PC_PR_SHIM2;
+ break;
+
+ case (HEADER_TYPE_LLC_SNAP):
+ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET;
+ break;
+
+ case (HEADER_TYPE_PPPoE):
+ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET;
+ break;
+
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_IP1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_MINENCAP):
+ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET;
+ break;
+
+ case (HEADER_TYPE_GRE):
+ *parseArrayOffset = CC_PC_PR_GRE_OFFSET;
+ break;
+
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_SCTP):
+ *parseArrayOffset = CC_PC_PR_L4_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header for this type of operation"));
+ return CC_PC_ILLEGAL;
+ }
+
+ if (offsetRelevant)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+}
+
+static uint8_t GetFieldParseCode(e_NetHeaderType hdr,
+ t_FmPcdFields field,
+ uint32_t offset,
+ uint8_t *parseArrayOffset,
+ e_FmPcdHdrIndex hdrIndex)
+{
+ bool offsetRelevant = FALSE;
+
+ if (offset)
+ offsetRelevant = TRUE;
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal header "));
+ return CC_PC_ILLEGAL;
+ }
+
+ if (offsetRelevant)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+}
+
+static void FillAdOfTypeResult(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcd *p_FmPcd,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams)
+{
+ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult *)h_Ad;
+ t_Handle h_TmpAd;
+ uint32_t tmp = 0, tmpNia = 0;
+ uint16_t profileId;
+ t_Handle p_AdNewPtr = NULL;
+
+ /* There are 3 cases handled in this routine of building a "result" type AD.
+ * Case 1: No Manip. The action descriptor is built within the match table.
+ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
+ * either in the FmPcdManipUpdateAdResultForCc routine or it was already
+ * initialized and returned here.
+ * p_AdResult (within the match table) will be initialized after
+ * this routine returns and point to the existing AD.
+ * Case 3: Manip exists. The action descriptor is built within the match table.
+ * FmPcdManipUpdateAdResultForCc returns a NULL p_AdNewPtr.
+ *
+ * If statistics were enabled and the statistics mode of this node requires
+ * a statistics Ad, it will be placed after the result Ad and before the
+ * manip Ad, if manip Ad exists here.
+ */
+
+ /* As default, the "new" ptr is the current one. i.e. the content of the result
+ * AD will be written into the match table itself (case (1))*/
+ p_AdNewPtr = p_AdResult;
+
+ /* Initialize an action descriptor, if current statistics mode requires an Ad */
+ if (p_FmPcdCcStatsParams)
+ {
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
+
+ /* Swapping addresses between statistics Ad and the current lookup AD addresses */
+ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
+ p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
+ h_Ad = h_TmpAd;
+
+ p_AdNewPtr = h_Ad;
+ p_AdResult = h_Ad;
+
+ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
+ UpdateStatsAd(p_FmPcdCcStatsParams,
+ h_Ad,
+ p_FmPcd->physicalMuramBase);
+ }
+
+ /* Create manip and return p_AdNewPtr to either a new descriptor or NULL */
+ if (p_CcNextEngineParams->h_Manip)
+ FmPcdManipUpdateAdResultForCc(p_CcNextEngineParams->h_Manip,
+ p_CcNextEngineParams,
+ h_Ad,
+ &p_AdNewPtr);
+
+ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
+ if (p_AdNewPtr)
+ {
+ /* case (1) and (2) */
+ switch (p_CcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_DONE):
+ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME)
+ {
+ if (p_CcNextEngineParams->params.enqueueParams.overrideFqid)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+ tmp |= p_CcNextEngineParams->params.enqueueParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.enqueueParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+ tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
+ }
+ }
+
+ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_DROP_FRAME)
+ tmpNia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ else
+ tmpNia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+
+ case (e_FM_PCD_KG):
+ if (p_CcNextEngineParams->params.kgParams.overrideFqid)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+ tmp |= p_CcNextEngineParams->params.kgParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.kgParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+ tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
+ }
+ tmpNia = NIA_KG_DIRECT;
+ tmpNia |= NIA_ENG_KG;
+ tmpNia |= NIA_KG_CC_EN;
+ tmpNia |= FmPcdKgGetSchemeId(p_CcNextEngineParams->params.kgParams.h_DirectScheme);
+ break;
+
+ case (e_FM_PCD_PLCR):
+ tmp = 0;
+ if (p_CcNextEngineParams->params.plcrParams.overrideParams)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (p_CcNextEngineParams->params.plcrParams.sharedProfile)
+ {
+ tmpNia |= NIA_PLCR_ABSOLUTE;
+ FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,
+ e_FM_PCD_PLCR_SHARED,
+ NULL,
+ p_CcNextEngineParams->params.plcrParams.newRelativeProfileId,
+ &profileId);
+ }
+ else
+ profileId = p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
+
+ tmp |= p_CcNextEngineParams->params.plcrParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.plcrParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK)<< FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_AdResult->plcrProfile,(uint32_t)((uint32_t)profileId << FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT));
+ }
+ else
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+
+ tmpNia |= NIA_ENG_PLCR | p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
+ break;
+
+ default:
+ return;
+ }
+ WRITE_UINT32(p_AdResult->fqid, tmp);
+
+ if (p_CcNextEngineParams->h_Manip)
+ {
+ tmp = GET_UINT32(p_AdResult->plcrProfile);
+ tmp |= (uint32_t)(XX_VirtToPhys(p_AdNewPtr) - (p_FmPcd->physicalMuramBase)) >> 4;
+ WRITE_UINT32(p_AdResult->plcrProfile, tmp);
+
+ tmpNia |= FM_PCD_AD_RESULT_EXTENDED_MODE;
+ tmpNia |= FM_PCD_AD_RESULT_NADEN;
+ }
+
+#if (DPAA_VERSION >= 11)
+ tmpNia |= FM_PCD_AD_RESULT_NO_OM_VSPE;
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_AdResult->nia, tmpNia);
+ }
+}
+
+static t_Error CcUpdateParams(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_FmTree,
+ bool validate)
+{
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree;
+
+ return CcUpdateParam(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcTree->keyAndNextEngineParams,
+ p_CcTree->numOfEntries,
+ UINT_TO_PTR(p_CcTree->ccTreeBaseAddr),
+ validate,
+ 0,
+ h_FmTree,
+ FALSE);
+}
+
+
+static void ReleaseNewNodeCommonPart(t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ if (p_AdditionalInfo->p_AdTableNew)
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
+ p_AdditionalInfo->p_AdTableNew);
+
+ if (p_AdditionalInfo->p_KeysMatchTableNew)
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
+ p_AdditionalInfo->p_KeysMatchTableNew);
+}
+
+static t_Error UpdateGblMask(t_FmPcdCcNode *p_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Mask)
+{
+ uint8_t prvGlblMaskSize = p_CcNode->glblMaskSize;
+
+ if (p_Mask &&
+ !p_CcNode->glblMaskUpdated &&
+ (keySize <= 4) &&
+ !p_CcNode->lclMask)
+ {
+ memcpy(p_CcNode->p_GlblMask, p_Mask, (sizeof(uint8_t))*keySize);
+ p_CcNode->glblMaskUpdated = TRUE;
+ p_CcNode->glblMaskSize = 4;
+ }
+ else if (p_Mask &&
+ (keySize <= 4) &&
+ !p_CcNode->lclMask)
+ {
+ if (memcmp(p_CcNode->p_GlblMask, p_Mask, keySize) != 0)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+ }
+ else if (!p_Mask && p_CcNode->glblMaskUpdated && (keySize <= 4))
+ {
+ uint32_t tmpMask = 0xffffffff;
+ if (memcmp(p_CcNode->p_GlblMask, &tmpMask, 4) != 0)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+ }
+ else if (p_Mask)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+
+ /* In static mode (maxNumOfKeys > 0), local mask is supported
+ only is mask support was enabled at initialization */
+ if (p_CcNode->maxNumOfKeys && (!p_CcNode->maskSupport) && p_CcNode->lclMask)
+ {
+ p_CcNode->lclMask = FALSE;
+ p_CcNode->glblMaskSize = prvGlblMaskSize;
+ return ERROR_CODE(E_NOT_SUPPORTED);
+ }
+
+ return E_OK;
+}
+
+static __inline__ t_Handle GetNewAd(t_Handle h_FmPcdCcNodeOrTree, bool isTree)
+{
+ t_FmPcd *p_FmPcd;
+ t_Handle h_Ad;
+
+ if (isTree)
+ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcTree *)h_FmPcdCcNodeOrTree)->h_FmPcd);
+ else
+ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_FmPcd);
+
+ if ((isTree && p_FmPcd->p_CcShadow) ||
+ (!isTree && ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->maxNumOfKeys))
+ {
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ ---------------------------------------------------
+ | Shadow | Shadow Keys | Shadow Next |
+ | Ad | Match Table | Engine Table |
+ | (16 bytes) | (maximal size) | (maximal size) |
+ ---------------------------------------------------
+ */
+ if (!p_FmPcd->p_CcShadow)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+ return NULL;
+ }
+
+ h_Ad = p_FmPcd->p_CcShadow;
+ }
+ else
+ {
+ h_Ad = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor"));
+ return NULL;
+ }
+ }
+
+ return h_Ad;
+}
+
+static t_Error BuildNewNodeCommonPart(t_FmPcdCcNode *p_CcNode,
+ int *size,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ if (p_CcNode->lclMask)
+ *size = 2 * p_CcNode->ccKeySizeAccExtraction;
+ else
+ *size = p_CcNode->ccKeySizeAccExtraction;
+
+ if (p_CcNode->maxNumOfKeys == 0)
+ {
+ p_AdditionalInfo->p_AdTableNew =
+ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ (uint32_t)( (p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE),
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_AdditionalInfo->p_AdTableNew)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table"));
+
+ p_AdditionalInfo->p_KeysMatchTableNew =
+ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ (uint32_t)(*size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)),
+ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
+ if (!p_AdditionalInfo->p_KeysMatchTableNew)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_AdditionalInfo->p_AdTableNew);
+ p_AdditionalInfo->p_AdTableNew = NULL;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table"));
+ }
+
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE));
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1));
+ }
+ else
+ {
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ ---------------------------------------------------
+ | Shadow | Shadow Keys | Shadow Next |
+ | Ad | Match Table | Engine Table |
+ | (16 bytes) | (maximal size) | (maximal size) |
+ ---------------------------------------------------
+ */
+
+ if (!p_FmPcd->p_CcShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+
+ p_AdditionalInfo->p_KeysMatchTableNew = PTR_MOVE(p_FmPcd->p_CcShadow, FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdditionalInfo->p_AdTableNew = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize);
+
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE));
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys));
+ }
+
+ p_AdditionalInfo->p_AdTableOld = p_CcNode->h_AdTable;
+ p_AdditionalInfo->p_KeysMatchTableOld = p_CcNode->h_KeysMatchTable;
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine(t_Handle h_FmPcd,
+ t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyParams *p_KeyParams,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo,
+ bool add)
+{
+ t_Error err = E_OK;
+ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ int i = 0, j = 0;
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t requiredAction = 0;
+ bool prvLclMask;
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcStatsParams statsParams = {0};
+ t_List *p_Pos;
+ t_FmPcdStatsObj *p_StatsObj;
+
+ /* Check that new NIA is legal */
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ prvLclMask = p_CcNode->lclMask;
+
+ /* Check that new key is not require update of localMask */
+ err = UpdateGblMask(p_CcNode,
+ p_CcNode->ccKeySizeAccExtraction,
+ p_KeyParams->p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ /* Update internal data structure with new next engine for the given index */
+ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key,
+ p_KeyParams->p_Key,
+ p_CcNode->userSizeOfExtraction);
+
+ if ((p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (p_KeyParams->p_Mask)
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ p_KeyParams->p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else
+ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ 0xFF,
+ p_CcNode->userSizeOfExtraction);
+
+ /* Update numOfKeys */
+ if (add)
+ p_AdditionalInfo->numOfKeys = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ p_AdditionalInfo->numOfKeys = (uint8_t)p_CcNode->numOfKeys;
+
+ /* Allocate new tables in MURAM: keys match table and action descriptors table */
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Check that manip is legal and what requiredAction is necessary for this manip */
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams,&requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction;
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE;
+
+ /* Update new Ad and new Key Table according to new requirement */
+ i = 0;
+ for (j = 0; j < p_AdditionalInfo->numOfKeys; j++)
+ {
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (j == keyIndex)
+ {
+ if (p_KeyParams->ccNextEngineParams.statisticsEn)
+ {
+ /* Allocate a statistics object that holds statistics AD and counters.
+ - For added key - New statistics AD and counters pointer need to be allocated
+ new statistics object. If statistics were enabled, we need to replace the
+ existing descriptor with a new descriptor with nullified counters.
+ */
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ /* Store allocated statistics object */
+ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Building action descriptor for the received new key */
+ NextStepAd(p_AdTableNewTmp,
+ &statsParams,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+ }
+ else
+ {
+ /* Building action descriptor for the received new key */
+ NextStepAd(p_AdTableNewTmp,
+ NULL,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+ }
+
+ /* Copy the received new key into keys match table */
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t));
+
+ Mem2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, p_CcNode->userSizeOfExtraction);
+
+ /* Update mask for the received new key */
+ if (p_CcNode->lclMask)
+ {
+ if (p_KeyParams->p_Mask)
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_KeyParams->p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else if (p_CcNode->ccKeySizeAccExtraction > 4)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+
+ /* If key modification requested, the old entry is omitted and replaced by the new parameters */
+ if (!add)
+ i++;
+ }
+ else
+ {
+ /* Copy existing action descriptors to the newly allocated Ad table */
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Copy existing keys and their masks to the newly allocated keys match table */
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, i * size * sizeof(uint8_t));
+
+ if (p_CcNode->lclMask)
+ {
+ if (prvLclMask)
+ {
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->ccKeySizeAccExtraction);
+ }
+ else
+ {
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable,
+ i * p_CcNode->ccKeySizeAccExtraction*sizeof(uint8_t));
+
+ if (p_CcNode->ccKeySizeAccExtraction > 4)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else
+ {
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ }
+
+ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction);
+
+ i++;
+ }
+ }
+
+ /* Miss action descriptor */
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (!LIST_IsEmpty(&p_CcNode->ccTreesLst))
+ {
+ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ /* Update the manipulation which has to be updated from parameters of the port */
+ /* It's has to be updated with restrictions defined in the function */
+ err = SetRequiredAction(p_CcNode->h_FmPcd,
+ p_CcNode->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(p_CcNode->h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ TRUE,
+ p_CcNodeInformation->index,
+ p_CcNodeInformation->h_CcNode,
+ TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+
+ if (p_CcNode->lclMask)
+ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ if (p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForAdd = p_KeyParams->ccNextEngineParams.params.ccParams.h_CcNode;
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForAdd = p_KeyParams->ccNextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForAdd = p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (!add)
+ {
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+ /* If statistics were previously enabled, store the old statistics object to be released */
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeRemoveKey(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ int i = 0, j = 0;
+ t_Handle p_AdTableNewTmp,p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ t_Error err = E_OK;
+
+ /*save new numOfKeys*/
+ p_AdditionalInfo->numOfKeys = (uint16_t)(p_CcNode->numOfKeys - 1);
+
+ /*function which allocates in the memory new KeyTbl, AdTbl*/
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*update new Ad and new Key Table according to new requirement*/
+ for (i=0, j=0; j<p_CcNode->numOfKeys; i++, j++)
+ {
+ if (j == keyIndex)
+ {
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ j++;
+ }
+ if (j == p_CcNode->numOfKeys)
+ break;
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t));
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t));
+ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, size * sizeof(uint8_t));
+ }
+
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+ /* If statistics were previously enabled, store the old statistics object to be released */
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeModifyKey(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ t_Error err = E_OK;
+ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ int i = 0, j = 0;
+ bool prvLclMask;
+ t_FmPcdStatsObj *p_StatsObj, tmpStatsObj;
+ p_AdditionalInfo->numOfKeys = p_CcNode->numOfKeys;
+
+ prvLclMask = p_CcNode->lclMask;
+
+ /* Check that new key is not require update of localMask */
+ err = UpdateGblMask(p_CcNode,
+ p_CcNode->ccKeySizeAccExtraction,
+ p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ /* Update internal data structure with new next engine for the given index */
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key,
+ p_Key,
+ p_CcNode->userSizeOfExtraction);
+
+ if (p_Mask)
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else
+ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ 0xFF,
+ p_CcNode->userSizeOfExtraction);
+
+ /*function which build in the memory new KeyTbl, AdTbl*/
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*fill the New AdTable and New KeyTable*/
+ for (j=0, i=0; j<p_AdditionalInfo->numOfKeys; j++, i++)
+ {
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (j == keyIndex)
+ {
+ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ /* As statistics were enabled, we need to update the existing
+ statistics descriptor with a new nullified counters. */
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ SetStatsCounters(p_AdTableNewTmp,
+ (uint32_t)((XX_VirtToPhys(p_StatsObj->h_StatsCounters) - p_FmPcd->physicalMuramBase)));
+
+ tmpStatsObj.h_StatsAd = p_StatsObj->h_StatsAd;
+ tmpStatsObj.h_StatsCounters = p_StatsObj->h_StatsCounters;
+
+ /* As we need to replace only the counters, we build a new statistics
+ object that holds the old AD and the new counters - this will be the
+ currently used statistics object.
+ The newly allocated AD is not required and may be released back to
+ the available objects with the previous counters pointer. */
+ p_StatsObj->h_StatsAd = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
+
+ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd = tmpStatsObj.h_StatsAd;
+
+ /* Store allocated statistics object */
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ /* As statistics were previously enabled, store the old statistics object to be released */
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+
+ Mem2IOCpy32(p_KeysMatchTableNewTmp, p_Key, p_CcNode->userSizeOfExtraction);
+
+ if (p_CcNode->lclMask)
+ {
+ if (p_Mask)
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else if (p_CcNode->ccKeySizeAccExtraction > 4)
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ else
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ else
+ {
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * size * sizeof(uint8_t));
+
+ if (p_CcNode->lclMask)
+ {
+ if (prvLclMask)
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->userSizeOfExtraction);
+ else
+ {
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t));
+
+ if (p_CcNode->ccKeySizeAccExtraction > 4)
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ else
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ IO2IOCpy32((void*)p_KeysMatchTableNewTmp,
+ p_KeysMatchTableOldTmp,
+ p_CcNode->ccKeySizeAccExtraction);
+ }
+ }
+
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeModifyNextEngine(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNodeOrTree,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_List *h_OldLst,
+ t_List *h_NewLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_Error err = E_OK;
+ uint32_t requiredAction = 0;
+ t_List *p_Pos;
+ t_CcNodeInformation *p_CcNodeInformation, ccNodeInfo;
+ t_Handle p_Ad;
+ t_FmPcdCcNode *p_FmPcdCcNode1 = NULL;
+ t_FmPcdCcTree *p_FmPcdCcTree = NULL;
+ t_FmPcdStatsObj *p_StatsObj;
+ t_FmPcdCcStatsParams statsParams = {0};
+
+ ASSERT_COND(p_CcNextEngineParams);
+
+ /* check that new NIA is legal */
+ if (!p_AdditionalInfo->tree)
+ err = ValidateNextEngineParams(h_FmPcd,
+ p_CcNextEngineParams,
+ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->statisticsMode);
+ else
+ /* Statistics are not supported for CC root */
+ err = ValidateNextEngineParams(h_FmPcd,
+ p_CcNextEngineParams,
+ e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Update internal data structure for next engine per index (index - key) */
+ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ p_CcNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ /* Check that manip is legal and what requiredAction is necessary for this manip */
+ if (p_CcNextEngineParams->h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(p_CcNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (!p_AdditionalInfo->tree)
+ {
+ p_FmPcdCcNode1 = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
+ p_AdditionalInfo->numOfKeys = p_FmPcdCcNode1->numOfKeys;
+ p_Ad = p_FmPcdCcNode1->h_AdTable;
+
+ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
+ p_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ && p_CcNextEngineParams->h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNextEngineParams->params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ ASSERT_COND(p_Ad);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = PTR_MOVE(p_Ad, keyIndex * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* If statistics were enabled, this Ad is the statistics Ad. Need to follow its
+ nextAction to retrieve the actual Nia-Ad. If statistics should remain enabled,
+ only the actual Nia-Ad should be modified. */
+ if ((!p_AdditionalInfo->tree) &&
+ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (p_CcNextEngineParams->statisticsEn))
+ ccNodeInfo.h_CcNode = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
+
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ p_Ad = GetNewAd(h_FmPcdCcNodeOrTree, p_AdditionalInfo->tree);
+ if (!p_Ad)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor"));
+ IOMemSet32((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* If statistics were not enabled before, but requested now - Allocate a statistics
+ object that holds statistics AD and counters. */
+ if ((!p_AdditionalInfo->tree) &&
+ (!((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (p_CcNextEngineParams->statisticsEn))
+ {
+ p_StatsObj = GetStatsObj((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree);
+ ASSERT_COND(p_StatsObj);
+
+ /* Store allocated statistics object */
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ NextStepAd(p_Ad,
+ &statsParams,
+ p_CcNextEngineParams,
+ h_FmPcd);
+ }
+ else
+ NextStepAd(p_Ad,
+ NULL,
+ p_CcNextEngineParams,
+ h_FmPcd);
+
+ ccNodeInfo.h_CcNode = p_Ad;
+ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction;
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE;
+
+ if (!p_AdditionalInfo->tree)
+ {
+ ASSERT_COND(p_FmPcdCcNode1);
+ if (!LIST_IsEmpty(&p_FmPcdCcNode1->ccTreesLst))
+ {
+ LIST_FOR_EACH(p_Pos, &p_FmPcdCcNode1->ccTreesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ /* Update the manipulation which has to be updated from parameters of the port
+ it's has to be updated with restrictions defined in the function */
+
+ err = SetRequiredAction(p_FmPcdCcNode1->h_FmPcd,
+ p_FmPcdCcNode1->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ p_Ad,
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(p_FmPcdCcNode1->h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ p_Ad,
+ TRUE,
+ p_CcNodeInformation->index,
+ p_CcNodeInformation->h_CcNode,
+ TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+ }
+ else
+ {
+ ASSERT_COND(p_FmPcdCcTree);
+
+ err = SetRequiredAction(h_FmPcd,
+ p_FmPcdCcTree->requiredAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ p_Ad,
+ 1,
+ (t_Handle)p_FmPcdCcTree);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ p_Ad,
+ TRUE,
+ 0,
+ (t_Handle)p_FmPcdCcTree, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForAdd = p_CcNextEngineParams->params.ccParams.h_CcNode;
+ if (p_CcNextEngineParams->h_Manip)
+ p_AdditionalInfo->h_ManipForAdd = p_CcNextEngineParams->h_Manip;
+
+ /* If statistics were previously enabled, but now are disabled,
+ store the old statistics object to be released */
+ if ((!p_AdditionalInfo->tree) &&
+ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (!p_CcNextEngineParams->statisticsEn))
+ {
+ p_AdditionalInfo->p_StatsObjForRmv =
+ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj;
+
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = NULL;
+ }
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_FR) &&
+ (p_CcNextEngineParams->params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForAdd = p_CcNextEngineParams->params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode,
+ t_List *h_OldLst,
+ t_FmPcdCcNextEngineParams **p_NextEngineParams)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcNode *p_NodePtrOnCurrentMdfNode = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccPrevNodesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_NodePtrOnCurrentMdfNode = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_NodePtrOnCurrentMdfNode);
+
+ /* Search in the previous node which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_NodePtrOnCurrentMdfNode->numOfKeys + 1; i++)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ p_AdTablePtOnCrntCurrentMdfNode = p_CrntMdfNode->h_Ad;
+ else if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj)
+ p_AdTablePtOnCrntCurrentMdfNode =
+ p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd;
+ else
+ p_AdTablePtOnCrntCurrentMdfNode =
+ PTR_MOVE(p_NodePtrOnCurrentMdfNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode;
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ if (!(*p_NextEngineParams))
+ *p_NextEngineParams = &p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
+ }
+ }
+ }
+
+ ASSERT_COND(i != p_NodePtrOnCurrentMdfNode->numOfKeys);
+ }
+}
+
+static void UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode,
+ t_List *h_OldLst,
+ t_FmPcdCcNextEngineParams **p_NextEngineParams)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcTree *p_TreePtrOnCurrentMdfNode = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTableTmp;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccTreeIdLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_TreePtrOnCurrentMdfNode = (t_FmPcdCcTree *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_TreePtrOnCurrentMdfNode);
+
+ /*search in the trees which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_TreePtrOnCurrentMdfNode->numOfEntries; i++)
+ {
+ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode)
+ {
+ p_AdTableTmp = UINT_TO_PTR(p_TreePtrOnCurrentMdfNode->ccTreeBaseAddr + i*FM_PCD_CC_AD_ENTRY_SIZE);
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTableTmp;
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ if (!(*p_NextEngineParams))
+ *p_NextEngineParams = &p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
+ }
+ }
+ }
+
+ ASSERT_COND(i == p_TreePtrOnCurrentMdfNode->numOfEntries);
+ }
+}
+
+static t_FmPcdModifyCcKeyAdditionalParams* ModifyKeyCommonPart1(t_Handle h_FmPcdCcNodeOrTree,
+ uint16_t keyIndex,
+ e_ModifyState modifyState,
+ bool ttlCheck,
+ bool hashCheck,
+ bool tree)
+{
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams;
+ int i = 0, j = 0;
+ bool wasUpdate = FALSE;
+ t_FmPcdCcNode *p_CcNode = NULL;
+ t_FmPcdCcTree *p_FmPcdCcTree;
+ uint16_t numOfKeys;
+ t_FmPcdCcKeyAndNextEngineParams *p_KeyAndNextEngineParams;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcdCcNodeOrTree, E_INVALID_HANDLE, NULL);
+
+ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(sizeof(t_FmPcdCcKeyAndNextEngineParams)*CC_MAX_NUM_OF_KEYS);
+ if (!p_KeyAndNextEngineParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure"));
+ return NULL;
+ }
+ memset(p_KeyAndNextEngineParams, 0, sizeof(t_FmPcdCcKeyAndNextEngineParams)*CC_MAX_NUM_OF_KEYS);
+
+ if (!tree)
+ {
+ p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
+ numOfKeys = p_CcNode->numOfKeys;
+
+ /* node has to be pointed by another node or tree */
+ if (!LIST_NumOfObjs(&p_CcNode->ccPrevNodesLst) &&
+ !LIST_NumOfObjs(&p_CcNode->ccTreeIdLst))
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be pointed by node or tree"));
+ return NULL;
+ }
+
+ if (!LIST_NumOfObjs(&p_CcNode->ccTreesLst) ||
+ (LIST_NumOfObjs(&p_CcNode->ccTreesLst) != 1))
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be belonging to some tree and only to one tree"));
+ return NULL;
+ }
+
+ memcpy(p_KeyAndNextEngineParams,
+ p_CcNode->keyAndNextEngineParams,
+ CC_MAX_NUM_OF_KEYS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ if (ttlCheck)
+ {
+ if ((p_CcNode->parseCode == CC_PC_FF_IPV4TTL) ||
+ (p_CcNode->parseCode == CC_PC_FF_IPV6HOP_LIMIT))
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_FF_IPV4TTL or CC_PC_FF_IPV6HOP_LIMIT can not be used for this operation"));
+ return NULL;
+ }
+ }
+
+ if (hashCheck)
+ {
+ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_GENERIC_IC_HASH_INDEXED can not be used for this operation"));
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
+ numOfKeys = p_FmPcdCcTree->numOfEntries;
+ memcpy(p_KeyAndNextEngineParams,
+ p_FmPcdCcTree->keyAndNextEngineParams,
+ FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ }
+
+ p_FmPcdModifyCcKeyAdditionalParams =
+ (t_FmPcdModifyCcKeyAdditionalParams *)XX_Malloc(sizeof(t_FmPcdModifyCcKeyAdditionalParams));
+ if (!p_FmPcdModifyCcKeyAdditionalParams)
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of internal data structure FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdModifyCcKeyAdditionalParams, 0, sizeof(t_FmPcdModifyCcKeyAdditionalParams));
+
+ p_FmPcdModifyCcKeyAdditionalParams->h_CurrentNode = h_FmPcdCcNodeOrTree;
+ p_FmPcdModifyCcKeyAdditionalParams->savedKeyIndex = keyIndex;
+
+ while (i < numOfKeys)
+ {
+ if ((j == keyIndex) && !wasUpdate)
+ {
+ if (modifyState == e_MODIFY_STATE_ADD)
+ j++;
+ else if (modifyState == e_MODIFY_STATE_REMOVE)
+ i++;
+ wasUpdate = TRUE;
+ }
+ else
+ {
+ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
+ p_KeyAndNextEngineParams + i,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ i++;
+ j++;
+ }
+ }
+
+ if (keyIndex == numOfKeys)
+ {
+ if (modifyState == e_MODIFY_STATE_ADD)
+ j++;
+ else if (modifyState == e_MODIFY_STATE_REMOVE)
+ i++;
+ }
+
+ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
+ p_KeyAndNextEngineParams + numOfKeys,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ XX_Free(p_KeyAndNextEngineParams);
+
+ return p_FmPcdModifyCcKeyAdditionalParams;
+}
+
+static t_Error UpdatePtrWhichPointOnCrntMdfNode(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
+ t_List *h_OldLst,
+ t_List *h_NewLst)
+{
+ t_FmPcdCcNextEngineParams *p_NextEngineParams = NULL;
+ t_CcNodeInformation ccNodeInfo = {0};
+ t_Handle h_NewAd;
+
+ /* Building a list of all action descriptors that point to the previous node */
+ if (!LIST_IsEmpty(&p_CcNode->ccPrevNodesLst))
+ UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams);
+
+ if (!LIST_IsEmpty(&p_CcNode->ccTreeIdLst))
+ UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams);
+
+ /* This node must be found as next engine of one of its previous nodes or trees*/
+ ASSERT_COND(p_NextEngineParams);
+
+ /* Building a new action descriptor that points to the modified node */
+ h_NewAd = GetNewAd(p_CcNode, FALSE);
+ if (!h_NewAd)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ IOMemSet32(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ BuildNewAd(h_NewAd,
+ p_FmPcdModifyCcKeyAdditionalParams,
+ p_CcNode,
+ p_NextEngineParams);
+
+ ccNodeInfo.h_CcNode = h_NewAd;
+ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
+
+ return E_OK;
+}
+
+static void UpdateCcRootOwner(t_FmPcdCcTree *p_FmPcdCcTree, bool add)
+{
+ ASSERT_COND(p_FmPcdCcTree);
+
+ /* this routine must be protected by the calling routine! */
+
+ if (add)
+ p_FmPcdCcTree->owners++;
+ else
+ {
+ ASSERT_COND(p_FmPcdCcTree->owners);
+ p_FmPcdCcTree->owners--;
+ }
+}
+
+static t_Error CheckAndSetManipParamsWithCcNodeParams(t_FmPcdCcNode *p_CcNode)
+{
+ t_Error err = E_OK;
+ int i = 0;
+
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsWithCcNodeParams(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ (t_Handle)p_CcNode);
+ if (err)
+ return err;
+ }
+ }
+
+ return err;
+}
+static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ uint32_t *p_NumOfRanges,
+ uint32_t *p_CountersArraySize)
+{
+ e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode;
+
+ UNUSED(p_CcNodeParam);
+
+ switch (statisticsMode)
+ {
+ case e_FM_PCD_CC_STATS_MODE_NONE:
+ return E_OK;
+
+ case e_FM_PCD_CC_STATS_MODE_FRAME:
+ case e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME:
+ *p_NumOfRanges = 1;
+ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
+ return E_OK;
+
+#if (DPAA_VERSION >= 11)
+ case e_FM_PCD_CC_STATS_MODE_RMON:
+ {
+ uint16_t *p_FrameLengthRanges = p_CcNodeParam->keysParams.frameLengthRanges;
+ uint32_t i;
+
+ if (p_FrameLengthRanges[0] <= 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
+
+ if (p_FrameLengthRanges[0] == 0xFFFF)
+ {
+ *p_NumOfRanges = 1;
+ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
+ return E_OK;
+ }
+
+ for (i = 1; i < FM_PCD_CC_STATS_MAX_NUM_OF_FLR; i++)
+ {
+ if (p_FrameLengthRanges[i-1] >= p_FrameLengthRanges[i])
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Frame length range must be larger at least by 1 from preceding range"));
+
+ /* Stop when last range is reached */
+ if (p_FrameLengthRanges[i] == 0xFFFF)
+ break;
+ }
+
+ if ((i >= FM_PCD_CC_STATS_MAX_NUM_OF_FLR) ||
+ (p_FrameLengthRanges[i] != 0xFFFF))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Last Frame length range must be 0xFFFF"));
+
+ *p_NumOfRanges = i+1;
+
+ /* Allocate an extra counter for byte count, as counters
+ array always begins with byte count */
+ *p_CountersArraySize = (*p_NumOfRanges + 1) * FM_PCD_CC_STATS_COUNTER_SIZE;
+
+ }
+ return E_OK;
+#endif /* (DPAA_VERSION >= 11) */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
+ }
+}
+
+static t_Error CheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint32_t requiredAction = 0;
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ /* Validate next engine parameters on Miss */
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid"));
+
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (!p_KeyParams->p_Key)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_Key is not initialized"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = UpdateGblMask(p_CcNode,
+ p_CcNodeParam->keysParams.keySize,
+ p_KeyParams->p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ /* Store 'key' parameters - key, mask (if passed by the user) */
+ memcpy(p_CcNode->keyAndNextEngineParams[tmp].key, p_KeyParams->p_Key, p_CcNodeParam->keysParams.keySize);
+
+ if (p_KeyParams->p_Mask)
+ memcpy(p_CcNode->keyAndNextEngineParams[tmp].mask,
+ p_KeyParams->p_Mask,
+ p_CcNodeParam->keysParams.keySize);
+ else
+ memset((void *)(p_CcNode->keyAndNextEngineParams[tmp].mask),
+ 0xFF,
+ p_CcNodeParam->keysParams.keySize);
+
+ /* Store next engine parameters */
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (p_CcNode->maxNumOfKeys < p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Number of keys exceed the provided maximal number of keys"));
+ }
+
+ *isKeyTblAlloc = TRUE;
+
+ return E_OK;
+}
+
+static t_Error Ipv4TtlOrIpv6HopLimitCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint8_t key = 0x01;
+ uint32_t requiredAction = 0;
+
+ if (p_CcNode->numOfKeys != 1)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'numOfKeys' is 1"));
+
+ if ((p_CcNodeParam->keysParams.maxNumOfKeys) && (p_CcNodeParam->keysParams.maxNumOfKeys != 1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'maxNumOfKeys' is 1"));
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNodeParam->keysParams.statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid"));
+
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeyParams->p_Mask)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Mask can not be initialized"));
+
+ if (memcmp(p_KeyParams->p_Key, &key, 1) != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Key has to be 1"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ /* Store 'key' parameters - key (fixed to 0x01), key size of 1 byte and full mask */
+ p_CcNode->keyAndNextEngineParams[tmp].key[0] = key;
+ p_CcNode->keyAndNextEngineParams[tmp].mask[0] = 0xFF;
+
+ /* Store NextEngine parameters */
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+ }
+
+ *isKeyTblAlloc = FALSE;
+
+ return E_OK;
+}
+
+static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0, countOnes = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint16_t glblMask = p_CcNodeParam->extractCcParams.extractNonHdr.icIndxMask;
+ uint16_t countMask = (uint16_t)(glblMask >> 4);
+ uint32_t requiredAction = 0;
+
+ if (glblMask & 0x000f)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("icIndxMask has to be with last nibble 0"));
+
+ while (countMask)
+ {
+ countOnes++;
+ countMask = (uint16_t)(countMask >> 1);
+ }
+
+ if (!POWER_OF_2(p_CcNode->numOfKeys))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED numOfKeys has to be powerOfTwo"));
+
+ if (p_CcNode->numOfKeys != ((uint32_t)1 << countOnes))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED numOfKeys has to be powerOfTwo"));
+
+ if (p_CcNodeParam->keysParams.maxNumOfKeys &&
+ (p_CcNodeParam->keysParams.maxNumOfKeys != p_CcNode->numOfKeys))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED 'maxNumOfKeys' should be 0 or equal 'numOfKeys'"));
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNode->statisticsMode);
+ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED)
+ RETURN_ERROR(MAJOR, err, ("MissNextEngineParams for the node of the type IC_INDEX_HASH has to be UnInitialized"));
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeyParams->p_Mask || p_KeyParams->p_Key)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED p_Key or p_Mask has to be NULL"));
+
+ if ((glblMask & (tmp * 16)) == (tmp * 16))
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("This index has to be initialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask "));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+ else
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED)
+ RETURN_ERROR(MAJOR, err, ("This index has to be UnInitialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask"));
+ }
+ }
+
+ *isKeyTblAlloc = FALSE;
+ memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2);
+
+ return E_OK;
+}
+
+static t_Error ModifyNextEngineParamNode(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_HANDLE);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+ }
+
+ err = BuildNewNodeModifyNextEngine(h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+static t_Error FindKeyIndex(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ uint16_t *p_KeyIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint8_t tmpMask[FM_PCD_MAX_SIZE_OF_KEY];
+ uint16_t i;
+
+ ASSERT_COND(p_Key);
+ ASSERT_COND(p_KeyIndex);
+ ASSERT_COND(keySize < FM_PCD_MAX_SIZE_OF_KEY);
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Key size doesn't match the extraction size of the node"));
+
+ /* If user didn't pass a mask for this key, we'll look for full extraction mask */
+ if (!p_Mask)
+ memset(tmpMask, 0xFF, keySize);
+
+ for (i = 0 ; i < p_CcNode->numOfKeys; i++)
+ {
+ /* Comparing received key */
+ if (memcmp(p_Key, p_CcNode->keyAndNextEngineParams[i].key, keySize) == 0)
+ {
+ if (p_Mask)
+ {
+ /* If a user passed a mask for this key, it must match to the existing key's mask for a correct match */
+ if (memcmp(p_Mask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0)
+ {
+ *p_KeyIndex = i;
+ return E_OK;
+ }
+ }
+ else
+ {
+ /* If user didn't pass a mask for this key, check if the existing key mask is full extraction */
+ if (memcmp(tmpMask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0)
+ {
+ *p_KeyIndex = i;
+ return E_OK;
+ }
+ }
+ }
+ }
+
+ return ERROR_CODE(E_NOT_FOUND);
+}
+
+static t_Error CalcAndUpdateCcShadow(t_FmPcdCcNode *p_CcNode,
+ bool isKeyTblAlloc,
+ uint32_t *p_MatchTableSize,
+ uint32_t *p_AdTableSize)
+{
+ uint32_t shadowSize;
+ t_Error err;
+
+ /* Calculate keys table maximal size - each entry consists of a key and a mask,
+ (if local mask support is requested) */
+ *p_MatchTableSize = p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t) * p_CcNode->maxNumOfKeys;
+
+ if (p_CcNode->maskSupport)
+ *p_MatchTableSize *= 2;
+
+ /* Calculate next action descriptors table, including one more entry for miss */
+ *p_AdTableSize = (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Calculate maximal shadow size of this node.
+ All shadow structures will be used for runtime modifications host command. If
+ keys table was allocated for this node, the keys table and next engines table may
+ be modified in run time (entries added or removed), so shadow tables are requires.
+ Otherwise, the only supported runtime modification is a specific next engine update
+ and this requires shadow memory of a single AD */
+
+ /* Shadow size should be enough to hold the following 3 structures:
+ * 1 - an action descriptor */
+ shadowSize = FM_PCD_CC_AD_ENTRY_SIZE;
+
+ /* 2 - keys match table, if was allocated for the current node */
+ if (isKeyTblAlloc)
+ shadowSize += *p_MatchTableSize;
+
+ /* 3 - next action descriptors table */
+ shadowSize += *p_AdTableSize;
+
+ /* Update shadow to the calculated size */
+ err = FmPcdUpdateCcShadow (p_CcNode->h_FmPcd, (uint32_t)shadowSize, FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node shadow"));
+ }
+
+ return E_OK;
+}
+
+static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode)
+{
+ t_FmPcdStatsObj *p_StatsObj;
+ t_Handle h_FmMuram, h_StatsAd, h_StatsCounters;
+ uint32_t i;
+
+ h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
+ if (!h_FmMuram)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
+
+ /* Allocate statistics ADs and statistics counter. An extra pair (AD + counters)
+ will be allocated to support runtime modifications */
+ for (i = 0; i < p_CcNode->maxNumOfKeys + 2; i++)
+ {
+ /* Allocate list object structure */
+ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
+ if (!p_StatsObj)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Statistics object"));
+ }
+ memset(p_StatsObj, 0, sizeof(t_FmPcdStatsObj));
+
+ /* Allocate statistics AD from MURAM */
+ h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_StatsAd)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ XX_Free(p_StatsObj);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs"));
+ }
+ IOMemSet32(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Allocate statistics counters from MURAM */
+ h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ p_CcNode->countersArraySize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_StatsCounters)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ FM_MURAM_FreeMem(h_FmMuram, h_StatsAd);
+ XX_Free(p_StatsObj);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters"));
+ }
+ IOMemSet32(h_StatsCounters, 0, p_CcNode->countersArraySize);
+
+ p_StatsObj->h_StatsAd = h_StatsAd;
+ p_StatsObj->h_StatsCounters = h_StatsCounters;
+
+ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
+ }
+
+ return E_OK;
+}
+
+static t_Error MatchTableGetKeyStatistics(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ uint32_t *p_StatsCounters, i;
+
+ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table"));
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table"));
+
+ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key"));
+
+ memset(p_KeyStatistics, 0, sizeof (t_FmPcdCcKeyStatistics));
+
+ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
+ ASSERT_COND(p_StatsCounters);
+
+ p_KeyStatistics->byteCount = GET_UINT32(*p_StatsCounters);
+
+ for (i = 1; i <= p_CcNode->numOfStatsFLRs; i++)
+ {
+ p_StatsCounters = PTR_MOVE(p_StatsCounters, FM_PCD_CC_STATS_COUNTER_SIZE);
+
+ p_KeyStatistics->frameCount += GET_UINT32(*p_StatsCounters);
+
+#if (DPAA_VERSION >= 11)
+ p_KeyStatistics->frameLengthRangeCount[i-1] = GET_UINT32(*p_StatsCounters);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation;
+ t_List *p_Pos;
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos))
+ {
+ p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcInformation->h_CcNode);
+
+ if (p_CcInformation->h_CcNode == h_Info)
+ {
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ return p_CcInformation;
+ }
+ }
+
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+
+ return NULL;
+}
+
+void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation;
+ uint32_t intFlags = 0;
+
+ p_CcInformation = (t_CcNodeInformation *)XX_Malloc(sizeof(t_CcNodeInformation));
+
+ if (p_CcInformation)
+ {
+ memset(p_CcInformation, 0, sizeof(t_CcNodeInformation));
+ memcpy(p_CcInformation, p_CcInfo, sizeof(t_CcNodeInformation));
+ INIT_LIST(&p_CcInformation->node);
+
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ LIST_AddToTail(&p_CcInformation->node, p_List);
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ }
+ else
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Node Information"));
+}
+
+void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation = NULL;
+ uint32_t intFlags = 0;
+ t_List *p_Pos;
+
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ if (LIST_IsEmpty(p_List))
+ {
+ XX_RestoreAllIntr(intFlags);
+ return;
+ }
+
+ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos))
+ {
+ p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcInformation);
+ ASSERT_COND(p_CcInformation->h_CcNode);
+ if (p_CcInformation->h_CcNode == h_Info)
+ break;
+ }
+
+ if (p_CcInformation)
+ {
+ LIST_DelAndInit(&p_CcInformation->node);
+ XX_Free(p_CcInformation);
+ }
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+}
+
+void NextStepAd(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ t_FmPcd *p_FmPcd)
+{
+ switch (p_FmPcdCcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_KG):
+ case (e_FM_PCD_PLCR):
+ case (e_FM_PCD_DONE):
+ /* if NIA is not CC, create a "result" type AD */
+ FillAdOfTypeResult(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams);
+ break;
+#if (DPAA_VERSION >= 11)
+ case (e_FM_PCD_FR):
+ if (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
+ {
+ FillAdOfTypeContLookup(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
+ FrmReplicGroupUpdateOwner(p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic,
+ TRUE/* add */);
+ }
+ break;
+#endif /* (DPAA_VERSION >= 11) */
+
+ case (e_FM_PCD_CC):
+ /* if NIA is not CC, create a TD to continue the CC lookup */
+ FillAdOfTypeContLookup(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ NULL);
+
+ UpdateNodeOwner(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, TRUE);
+ break;
+
+ default:
+ return;
+ }
+}
+
+t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd,
+ t_Handle h_FmTree,
+ t_Handle h_NetEnv,
+ t_Handle h_IpReassemblyManip,
+ bool createSchemes)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ t_NetEnvParams netEnvParams;
+ t_Handle h_Ad;
+ bool isIpv6Present;
+ uint8_t ipv4GroupId, ipv6GroupId;
+ t_Error err;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ /* this routine must be protected by the calling routine! */
+
+ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
+ memset(&netEnvParams, 0, sizeof(t_NetEnvParams));
+
+ h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ isIpv6Present = FmPcdManipIpReassmIsIpv6Hdr(h_IpReassemblyManip);
+
+ if (isIpv6Present && (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-2)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
+
+ if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
+
+ nextEngineParams.nextEngine = e_FM_PCD_DONE;
+ nextEngineParams.h_Manip = h_IpReassemblyManip;
+
+ /* Lock tree */
+ err = CcRootTryLock(p_FmPcdCcTree);
+ if (err)
+ return ERROR_CODE(E_BUSY);
+
+ if (p_FmPcdCcTree->h_IpReassemblyManip == h_IpReassemblyManip)
+ {
+ CcRootReleaseLock(p_FmPcdCcTree);
+ return E_OK;
+ }
+
+ if ((p_FmPcdCcTree->h_IpReassemblyManip) &&
+ (p_FmPcdCcTree->h_IpReassemblyManip != h_IpReassemblyManip))
+ {
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This tree was previously updated with different IPR"));
+ }
+
+ /* Initialize IPR for the first time for this tree */
+ if (isIpv6Present)
+ {
+ ipv6GroupId = p_FmPcdCcTree->numOfGrps++;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv6GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-2);
+
+ if (createSchemes)
+ {
+ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, FALSE, ipv6GroupId);
+ if (err)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-2) * FM_PCD_CC_AD_ENTRY_SIZE),
+ NULL,
+ &nextEngineParams,
+ h_FmPcd);
+ }
+
+ ipv4GroupId = p_FmPcdCcTree->numOfGrps++;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].totalBitsMask = 0;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-1);
+
+ if (createSchemes)
+ {
+ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, TRUE, ipv4GroupId);
+ if (err)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ if (isIpv6Present)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ FmPcdManipDeleteIpReassmSchemes(h_IpReassemblyManip);
+ }
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE),
+ NULL,
+ &nextEngineParams,
+ h_FmPcd);
+
+ p_FmPcdCcTree->h_IpReassemblyManip = h_IpReassemblyManip;
+
+ CcRootReleaseLock(p_FmPcdCcTree);
+
+ return E_OK;
+}
+
+
+t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ return p_FmPcdCcTree->h_FmPcdCcSavedManipParams;
+}
+
+void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ p_FmPcdCcTree->h_FmPcdCcSavedManipParams = h_SavedManipParams;
+}
+
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->parseCode;
+}
+
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->offset;
+}
+
+uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->numOfKeys;
+}
+
+t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcTree,
+ uint8_t grpId,
+ uint8_t index,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ uint16_t keyIndex;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((grpId <= 7),E_INVALID_VALUE);
+
+ if (grpId >= p_FmPcdCcTree->numOfGrps)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree"));
+
+ if (index >= p_FmPcdCcTree->fmPcdGroupParam[grpId].numOfEntriesInGroup)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("index > numOfEntriesInGroup"));
+
+ p_FmPcd = (t_FmPcd *)h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ keyIndex = (uint16_t)(p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry + index);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_FmPcdCcTree, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, TRUE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ p_ModifyKeyParams->tree = TRUE;
+
+ if (p_FmPcd->p_CcShadow)
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = BuildNewNodeModifyNextEngine(p_FmPcd,
+ p_FmPcdCcTree,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_FmPcd->p_CcShadow)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+
+}
+
+t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex)
+{
+
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *) h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to remove key when numOfKeys <= keyIndex"));
+
+ if (!p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex you asked > numOfKeys of relevant node that was initialized"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_REMOVE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeRemoveKey(p_CcNode, keyIndex, p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ uint16_t tmpKeyIndex;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size for ModifyKey has to be the same as defined in SetNode"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_Key,
+ p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MINOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeModifyKey(p_CcNode,
+ keyIndex,
+ p_Key,
+ p_Mask,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ uint16_t keyIndex;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_VALUE);
+
+ keyIndex = p_CcNode->numOfKeys;
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+ }
+
+ err = BuildNewNodeModifyNextEngine(h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcAddKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ bool useShadowStructs = FALSE;
+ uint16_t tmpKeyIndex;
+ t_Error err = E_OK;
+
+ if (keyIndex > p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (p_CcNode->numOfKeys == p_CcNode->maxNumOfKeys)
+ RETURN_ERROR(MAJOR, E_FULL, ("number of keys exceeds the maximal number of keys provided at node initialization time"));
+ }
+ else if (p_CcNode->numOfKeys == FM_PCD_MAX_NUM_OF_KEYS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("number of keys can not be larger than %d", FM_PCD_MAX_NUM_OF_KEYS));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_FmPcdCcKeyParams->p_Key,
+ p_FmPcdCcKeyParams->p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MINOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode,
+ keyIndex,
+ e_MODIFY_STATE_ADD,
+ TRUE,
+ TRUE,
+ FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcKeyParams,
+ p_ModifyKeyParams,
+ TRUE);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ uint16_t tmpKeyIndex;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex > p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_FmPcdCcKeyParams->p_Key,
+ p_FmPcdCcKeyParams->p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MINOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyKeyCommonPart1(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcKeyParams,
+ p_ModifyKeyParams,
+ FALSE);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_CcNodeInformation *p_CcNodeInfo;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, (uint32_t)ILLEGAL_BASE);
+
+ p_CcNodeInfo = CC_NODE_F_OBJECT(h_Pointer);
+
+ return (uint32_t)(XX_VirtToPhys(p_CcNodeInfo->h_CcNode) - p_FmPcd->physicalMuramBase);
+}
+
+t_Error FmPcdCcGetGrpParams(t_Handle h_FmPcdCcTree, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *) h_FmPcdCcTree;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
+
+ if (grpId >= p_FmPcdCcTree->numOfGrps)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree"));
+
+ *p_GrpBits = p_FmPcdCcTree->fmPcdGroupParam[grpId].totalBitsMask;
+ *p_GrpBase = p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry;
+
+ return E_OK;
+}
+
+t_Error FmPcdCcBindTree(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPcdCcTree,
+ uint32_t *p_Offset,
+ t_Handle h_FmPort)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
+
+ /* this routine must be protected by the calling routine by locking all PCD modules! */
+
+ err = CcUpdateParams(h_FmPcd, h_PcdParams, h_FmPort, h_FmPcdCcTree, TRUE);
+
+ if (err == E_OK)
+ UpdateCcRootOwner(p_FmPcdCcTree, TRUE);
+
+ *p_Offset = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr)) -
+ p_FmPcd->physicalMuramBase);
+
+ return err;
+}
+
+t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ /* this routine must be protected by the calling routine by locking all PCD modules! */
+
+ UNUSED(h_FmPcd);
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE);
+
+ UpdateCcRootOwner(p_FmPcdCcTree, FALSE);
+
+ return E_OK;
+}
+
+t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_List *p_Pos, *p_Tmp;
+ t_CcNodeInformation *p_CcNodeInfo, nodeInfo;
+ uint32_t intFlags;
+ t_Error err = E_OK;
+
+ intFlags = FmPcdLock(h_FmPcd);
+
+ if (LIST_IsEmpty(&p_CcNode->ccTreesLst))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("asked for more nodes in CC than MAX"));
+
+ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInfo->h_CcNode);
+
+ err = CcRootTryLock(p_CcNodeInfo->h_CcNode);
+
+ if (err)
+ {
+ LIST_FOR_EACH(p_Tmp, &p_CcNode->ccTreesLst)
+ {
+ if (p_Tmp == p_Pos)
+ break;
+
+ CcRootReleaseLock(p_CcNodeInfo->h_CcNode);
+ }
+ break;
+ }
+
+ memset(&nodeInfo, 0, sizeof(t_CcNodeInformation));
+ nodeInfo.h_CcNode = p_CcNodeInfo->h_CcNode;
+ EnqueueNodeInfoToRelevantLst(p_List, &nodeInfo, NULL);
+ }
+
+ FmPcdUnlock(h_FmPcd, intFlags);
+ CORE_MemoryBarrier();
+
+ return err;
+}
+
+void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List)
+{
+ t_List *p_Pos;
+ t_CcNodeInformation *p_CcNodeInfo;
+ t_Handle h_FmPcdCcTree;
+ uint32_t intFlags;
+
+ intFlags = FmPcdLock(h_FmPcd);
+
+ LIST_FOR_EACH(p_Pos, p_List)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ h_FmPcdCcTree = p_CcNodeInfo->h_CcNode;
+ CcRootReleaseLock(h_FmPcdCcTree);
+ }
+
+ ReleaseLst(p_List);
+
+ FmPcdUnlock(h_FmPcd, intFlags);
+ CORE_MemoryBarrier();
+}
+
+
+t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align)
+{
+ uint32_t intFlags;
+ uint32_t newSize = 0, newAlign = 0;
+ bool allocFail = FALSE;
+
+ ASSERT_COND(p_FmPcd);
+
+ if (!size)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size must be larger then 0"));
+
+ if (!POWER_OF_2(align))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("alignment must be power of 2"));
+
+ newSize = p_FmPcd->ccShadowSize;
+ newAlign = p_FmPcd->ccShadowAlign;
+
+ /* Check if current shadow is large enough to hold the requested size */
+ if (size > p_FmPcd->ccShadowSize)
+ newSize = size;
+
+ /* Check if current shadow matches the requested alignment */
+ if (align > p_FmPcd->ccShadowAlign)
+ newAlign = align;
+
+ /* If a bigger shadow size or bigger shadow alignment are required,
+ a new shadow will be allocated */
+ if ((newSize != p_FmPcd->ccShadowSize) || (newAlign != p_FmPcd->ccShadowAlign))
+ {
+ intFlags = FmPcdLock(p_FmPcd);
+
+ if (p_FmPcd->p_CcShadow)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->p_CcShadow);
+ p_FmPcd->ccShadowSize = 0;
+ p_FmPcd->ccShadowAlign = 0;
+ }
+
+ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ newSize,
+ newAlign);
+ if (!p_FmPcd->p_CcShadow)
+ {
+ allocFail = TRUE;
+
+ /* If new shadow size allocation failed,
+ re-allocate with previous parameters */
+ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ p_FmPcd->ccShadowSize,
+ p_FmPcd->ccShadowAlign);
+ }
+
+ FmPcdUnlock(p_FmPcd, intFlags);
+
+ if (allocFail)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Shadow memory"));
+
+ p_FmPcd->ccShadowSize = newSize;
+ p_FmPcd->ccShadowAlign = newAlign;
+ }
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node,
+ t_Handle h_ReplicGroup,
+ t_List *p_AdTables,
+ uint32_t *p_NumOfAdTables)
+{
+ t_FmPcdCcNode *p_CurrentNode = (t_FmPcdCcNode *)h_Node;
+ int i = 0;
+ void * p_AdTable;
+ t_CcNodeInformation ccNodeInfo;
+
+ ASSERT_COND(h_Node);
+ *p_NumOfAdTables = 0;
+
+ /* search in the current node which exact index points on this current replicator group for getting AD */
+ for (i = 0; i < p_CurrentNode->numOfKeys + 1; i++)
+ {
+ if ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic == (t_Handle)h_ReplicGroup)))
+ {
+ /* save the current ad table in the list */
+ /* this entry uses the input replicator group */
+ p_AdTable = PTR_MOVE(p_CurrentNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTable;
+ EnqueueNodeInfoToRelevantLst(p_AdTables, &ccNodeInfo, NULL);
+ (*p_NumOfAdTables)++;
+ }
+ }
+
+ ASSERT_COND(i != p_CurrentNode->numOfKeys);
+}
+#endif /* (DPAA_VERSION >= 11) */
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_Error err = E_OK;
+ int i = 0, j = 0, k = 0;
+ t_FmPcdCcTree *p_FmPcdCcTree;
+ uint8_t numOfEntries;
+ t_Handle p_CcTreeTmp;
+ t_FmPcdCcGrpParams *p_FmPcdCcGroupParams;
+ t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams;
+ t_NetEnvParams netEnvParams;
+ uint8_t lastOne = 0;
+ uint32_t requiredAction = 0;
+ t_FmPcdCcNode *p_FmPcdCcNextNode;
+ t_CcNodeInformation ccNodeInfo, *p_CcInformation;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL);
+
+ if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
+ return NULL;
+ }
+
+ p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree));
+ if (!p_FmPcdCcTree)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure"));
+ return NULL;
+ }
+ memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree));
+ p_FmPcdCcTree->h_FmPcd = h_FmPcd;
+
+ p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ INIT_LIST(&p_FmPcdCcTree->fmPortsLst);
+
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_PcdGroupsParam->numOfGrps == 1) &&
+ (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) &&
+ (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) &&
+ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode &&
+ IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode))
+ {
+ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild();
+ if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ numOfEntries = 0;
+ p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv);
+
+ for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++)
+ {
+ p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i];
+
+ if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS));
+ return NULL;
+ }
+
+ p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries;
+ p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits);
+ numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
+ if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
+ return NULL;
+ }
+
+ if (lastOne)
+ {
+ if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order"));
+ return NULL;
+ }
+ }
+
+ lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
+
+ netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId;
+ netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits;
+
+ memcpy(netEnvParams.unitIds,
+ &p_FmPcdCcGroupParams->unitIds,
+ (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits);
+
+ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+
+ p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector;
+ for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++)
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
+ e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, err, (NO_MSG));
+ return NULL;
+ }
+
+ if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+ p_KeyAndNextEngineParams = p_Params+k;
+
+ memcpy(&p_KeyAndNextEngineParams->nextEngineParams,
+ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_KeyAndNextEngineParams->nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
+ return NULL;
+ }
+ }
+
+ requiredAction |= UPDATE_CC_WITH_TREE;
+ p_KeyAndNextEngineParams->requiredAction = requiredAction;
+
+ k++;
+ }
+ }
+
+ p_FmPcdCcTree->numOfEntries = (uint8_t)k;
+ p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps;
+
+ p_FmPcdCcTree->ccTreeBaseAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd),
+ (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE),
+ FM_PCD_CC_TREE_ADDR_ALIGN));
+ if (!p_FmPcdCcTree->ccTreeBaseAddr)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
+ return NULL;
+ }
+ IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE));
+
+ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ j = 0;
+ for (i = 0; i < numOfEntries; i++)
+ {
+ p_KeyAndNextEngineParams = p_Params + i;
+
+ NextStepAd(p_CcTreeTmp,
+ NULL,
+ &p_KeyAndNextEngineParams->nextEngineParams,
+ p_FmPcd);
+
+ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i],
+ p_KeyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst,
+ (t_Handle)p_FmPcdCcTree,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ else
+ p_CcInformation->index++;
+ }
+ }
+
+ FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId);
+ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return NULL;
+ }
+
+ for (i = 0; i < numOfEntries; i++)
+ {
+ if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction)
+ {
+ err = SetRequiredAction(h_FmPcd,
+ p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction,
+ &p_FmPcdCcTree->keyAndNextEngineParams[i],
+ p_CcTreeTmp,
+ 1,
+ p_FmPcdCcTree);
+ if (err)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ }
+
+ FmPcdLockUnlockAll(p_FmPcd);
+ p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_FmPcdCcTree->p_Lock)
+ {
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock"));
+ return NULL;
+ }
+
+ XX_Free(p_Params);
+
+ return p_FmPcdCcTree;
+}
+
+t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
+ int i= 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE);
+ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId);
+
+ if (p_CcTree->owners)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree"));
+
+ /* Delete reassembly schemes if exist */
+ if (p_CcTree->h_IpReassemblyManip)
+ {
+ FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip);
+ FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE);
+ }
+
+ for (i = 0; i <p_CcTree->numOfEntries; i++)
+ {
+ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE);
+
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_CcTree->numOfGrps == 1) &&
+ (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) &&
+ (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) &&
+ p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode &&
+ IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode))
+ {
+ if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK)
+ return E_INVALID_STATE;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
+ FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
+ FALSE);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ if (p_CcTree->p_Lock)
+ FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock);
+
+ DeleteTree(p_CcTree, p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree,
+ uint8_t grpId,
+ uint8_t index,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE);
+ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyNextEngineParamTree(p_FmPcd,
+ p_CcTree,
+ grpId,
+ index,
+ p_FmPcdCcNextEngineParams);
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd;
+ t_FmPcdCcNode *p_CcNode, *p_FmPcdCcNextNode;
+ t_Error err = E_OK;
+ uint32_t tmp, keySize;
+ bool glblMask = FALSE;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_StatsFLRs;
+#endif /* (DPAA_VERSION >= 11) */
+ bool fullField = FALSE;
+ ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE;
+ bool isKeyTblAlloc, fromIc = FALSE;
+ uint32_t matchTableSize, adTableSize;
+ t_CcNodeInformation ccNodeInfo, *p_CcInformation;
+ t_FmPcdStatsObj *p_StatsObj;
+ t_FmPcdCcStatsParams statsParams = {0};
+ t_Handle h_Manip;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL);
+
+ p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
+ if (!p_CcNode)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode));
+
+ p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+ memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ p_CcNode->h_FmPcd = h_FmPcd;
+ p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys;
+ p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys;
+ p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport;
+ p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode;
+
+ /* For backward compatibility - even if statistics mode is nullified,
+ we'll fix it to frame mode so we can support per-key request for
+ statistics using 'statisticsEn' in next engine parameters */
+ if (!p_CcNode->maxNumOfKeys &&
+ (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE))
+ p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME;
+
+ h_FmMuram = FmPcdGetMuramHandle(h_FmPcd);
+ if (!h_FmMuram)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
+ return NULL;
+ }
+
+ INIT_LIST(&p_CcNode->ccPrevNodesLst);
+ INIT_LIST(&p_CcNode->ccTreeIdLst);
+ INIT_LIST(&p_CcNode->ccTreesLst);
+ INIT_LIST(&p_CcNode->availableStatsLst);
+
+ p_CcNode->h_Spinlock = XX_InitSpinlock();
+ if (!p_CcNode->h_Spinlock)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock"));
+ return NULL;
+ }
+
+ if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) &&
+ ((p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv4) ||
+ (p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv6)) &&
+ (p_CcNodeParam->extractCcParams.extractByHdr.type == e_FM_PCD_EXTRACT_FULL_FIELD) &&
+ ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 == NET_HEADER_FIELD_IPv6_HOP_LIMIT) ||
+ (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 == NET_HEADER_FIELD_IPv4_TTL)))
+ {
+ err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ glblMask = FALSE;
+ }
+ else if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) &&
+ ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_KEY) ||
+ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_HASH) ||
+ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID)))
+ {
+ if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) &&
+ (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0"));
+ return NULL;
+ }
+
+ icCode = IcDefineCode(p_CcNodeParam);
+ fromIc = TRUE;
+ if (icCode == CC_PRIVATE_INFO_NONE)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way"));
+ return NULL;
+ }
+
+ if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) ||
+ (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP))
+ {
+ err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ glblMask = TRUE;
+ }
+ else
+ {
+ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ if (p_CcNode->glblMaskSize)
+ glblMask = TRUE;
+ }
+ }
+ else
+ {
+ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ if (p_CcNode->glblMaskSize)
+ glblMask = TRUE;
+ }
+
+ if (err)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+
+ switch (p_CcNodeParam->extractCcParams.type)
+ {
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ switch (p_CcNodeParam->extractCcParams.extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ p_CcNode->parseCode =
+ GetFullFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField);
+ GetSizeHeaderField(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField,
+ &p_CcNode->sizeOfExtraction);
+ fullField = TRUE;
+ if ((p_CcNode->parseCode != CC_PC_FF_TCI1) &&
+ (p_CcNode->parseCode != CC_PC_FF_TCI2) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS1) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPDSCP) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) &&
+ glblMask)
+ {
+ glblMask = FALSE;
+ p_CcNode->glblMaskSize = 4;
+ p_CcNode->lclMask = TRUE;
+ }
+ break;
+
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size;
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
+ p_CcNode->parseCode =
+ GetPrParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNode->offset,glblMask,
+ &p_CcNode->prsArrayOffset);
+ break;
+
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size;
+ p_CcNode->parseCode =
+ GetFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field,
+ p_CcNode->offset,
+ &p_CcNode->prsArrayOffset,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex);
+ break;
+
+ default:
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ return NULL;
+ }
+ break;
+
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* get the field code for the generic extract */
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractNonHdr.size;
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractNonHdr.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractNonHdr.offset;
+ p_CcNode->parseCode =
+ GetGenParseCode(h_FmPcd,
+ p_CcNodeParam->extractCcParams.extractNonHdr.src,
+ p_CcNode->offset,
+ glblMask,
+ &p_CcNode->prsArrayOffset,
+ fromIc,icCode);
+
+ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
+ {
+ if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION,("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)"));
+ return NULL;
+ }
+ }
+ if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) ||
+ (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED))
+ {
+ p_CcNode->offset += p_CcNode->prsArrayOffset;
+ p_CcNode->prsArrayOffset = 0;
+ }
+ break;
+
+ default:
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ return NULL;
+ }
+
+ if (p_CcNode->parseCode == CC_PC_ILLEGAL)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type"));
+ return NULL;
+ }
+
+ if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) ||
+ !p_CcNode->sizeOfExtraction)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0"));
+ return NULL;
+ }
+
+ if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction"));
+ return NULL;
+ }
+
+ p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction;
+
+ if (!glblMask)
+ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction"));
+ return NULL;
+ }
+
+ /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */
+ GetCcExtractKeySize(p_CcNode->sizeOfExtraction, &p_CcNode->ccKeySizeAccExtraction);
+
+ /* If local mask is used, it is stored next to each key in the keys match table */
+ if (p_CcNode->lclMask)
+ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
+ else
+ keySize = p_CcNode->ccKeySizeAccExtraction;
+
+ /* Update CC shadow with maximal size required by this node */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ err = CalcAndUpdateCcShadow(p_CcNode,
+ isKeyTblAlloc,
+ &matchTableSize,
+ &adTableSize);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+
+ p_CcNode->keysMatchTableMaxSize = matchTableSize;
+
+ if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)
+ {
+ err = AllocStatsObjs(p_CcNode);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+ }
+
+ /* If manipulation will be initialized before this node, it will use the table
+ descriptor in the AD table of previous node and this node will need an extra
+ AD as his table descriptor. */
+ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_CcNode->h_Ad)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor"));
+ return NULL;
+ }
+ }
+ else
+ {
+ matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) * (p_CcNode->numOfKeys + 1));
+ adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE * (p_CcNode->numOfKeys + 1));
+ }
+
+#if (DPAA_VERSION >= 11)
+ switch (p_CcNode->statisticsMode)
+ {
+
+ case e_FM_PCD_CC_STATS_MODE_RMON:
+ /* If RMON statistics or RMON conditional statistics modes are requested,
+ allocate frame length ranges array */
+ p_CcNode->h_StatsFLRs =
+ FM_MURAM_AllocMem(h_FmMuram,
+ (uint32_t)(p_CcNode->numOfStatsFLRs) * FM_PCD_CC_STATS_FLR_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ if (!p_CcNode->h_StatsFLRs)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array"));
+ return NULL;
+ }
+
+ /* Initialize using value received from the user */
+ for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++)
+ {
+ h_StatsFLRs = PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE);
+
+ Mem2IOCpy32(h_StatsFLRs,
+ &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]),
+ FM_PCD_CC_STATS_FLR_SIZE);
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+
+ /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL
+ identification, IPv6 hop count identification, etc. */
+ if (isKeyTblAlloc)
+ {
+ p_CcNode->h_KeysMatchTable =
+ (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ matchTableSize,
+ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
+ if (!p_CcNode->h_KeysMatchTable)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table"));
+ return NULL;
+ }
+ IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable,
+ 0,
+ matchTableSize);
+ }
+
+ /* Allocate action descriptors table */
+ p_CcNode->h_AdTable =
+ (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ adTableSize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_CcNode->h_AdTable)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table"));
+ return NULL;
+ }
+ IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize);
+
+ p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable;
+ p_AdTableTmp = p_CcNode->h_AdTable;
+
+ /* For each key, create the key and the next step AD */
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeysMatchTblTmp)
+ {
+ /* Copy the key */
+ Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, p_CcNode->sizeOfExtraction);
+
+ /* Copy the key mask or initialize it to 0xFF..F */
+ if (p_CcNode->lclMask && p_KeyParams->p_Mask)
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp,
+ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
+ p_KeyParams->p_Mask,
+ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
+ }
+ else if (p_CcNode->lclMask)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp,
+ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
+ 0xff,
+ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
+ }
+
+ p_KeysMatchTblTmp = PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t));
+ }
+
+ /* Create the next action descriptor in the match table */
+ if (p_KeyParams->ccNextEngineParams.statisticsEn)
+ {
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+ NextStepAd(p_AdTableTmp,
+ &statsParams,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
+ }
+ else
+ {
+ NextStepAd(p_AdTableTmp,
+ NULL,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
+ }
+
+ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+
+ /* Update next engine for the 'miss' entry */
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn)
+ {
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ NextStepAd(p_AdTableTmp,
+ &statsParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
+ }
+ else
+ {
+ NextStepAd(p_AdTableTmp,
+ NULL,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
+ }
+
+ /* This parameter will be used to initialize the "key length" field in the action descriptor
+ that points to this node and it should be 0 for full field extraction */
+ if (fullField == TRUE)
+ p_CcNode->sizeOfExtraction = 0;
+
+ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode;
+ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccPrevNodesLst,
+ (t_Handle)p_CcNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ else
+ p_CcInformation->index++;
+
+ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ h_Manip = p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip;
+ p_CcInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
+ (t_Handle)p_CcNode,
+ FmPcdManipGetSpinlock(h_Manip));
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
+ &ccNodeInfo,
+ FmPcdManipGetSpinlock(h_Manip));
+ }
+ else
+ p_CcInformation->index++;
+ }
+ }
+ }
+
+ p_AdTableTmp = p_CcNode->h_AdTable;
+
+ if (!FmPcdLockTryLockAll(h_FmPcd))
+ {
+ FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return NULL;
+ }
+
+ /* Required action for each next engine */
+ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction)
+ {
+ err = SetRequiredAction(h_FmPcd,
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction,
+ &p_CcNode->keyAndNextEngineParams[tmp],
+ p_AdTableTmp,
+ 1,
+ NULL);
+ if (err)
+ {
+ FmPcdLockUnlockAll(h_FmPcd);
+ FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ }
+
+ FmPcdLockUnlockAll(h_FmPcd);
+ return p_CcNode;
+}
+
+t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ int i = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (p_CcNode->owners)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This node cannot be removed because it is occupied; first unbind this node"));
+
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ /* Handle also Miss entry */
+ for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ FmPcdManipUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE);
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
+ {
+ FrmReplicGroupUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
+ FALSE);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ DeleteNode(p_CcNode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (keyIndex == FM_PCD_LAST_KEY_INDEX)
+ keyIndex = p_CcNode->numOfKeys;
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcAddKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_List h_List;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ INIT_LIST(&h_List);
+
+ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List);
+ if (err)
+ {
+ DBG(TRACE, ("Node's trees lock failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_Key,
+ p_Mask);
+
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = ModifyNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyMissNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+
+t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+
+t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = ModifyNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd,
+ h_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ uint8_t *p_NewKey,
+ uint8_t *p_NewMask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_List h_List;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_NewKey, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ INIT_LIST(&h_List);
+
+ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List);
+ if (err)
+ {
+ DBG(TRACE, ("Node's trees lock failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the "
+ "match table of the provided node"));
+ }
+
+ err = FmPcdCcModifyKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_NewKey,
+ p_NewMask);
+
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex exceeds current number of keys"));
+
+ if (keyIndex > (FM_PCD_MAX_NUM_OF_KEYS - 1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex can not be larger than %d", (FM_PCD_MAX_NUM_OF_KEYS - 1)));
+
+ memcpy(p_FmPcdCcNextEngineParams,
+ &p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ return E_OK;
+}
+
+
+uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t *p_StatsCounters, frameCount;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_VALUE(p_CcNode, E_INVALID_HANDLE, 0);
+
+ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table"));
+ return 0;
+ }
+
+ if ((p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_FRAME) &&
+ (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Frame count is not supported in the statistics mode of this match table"));
+ return 0;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table"));
+ return 0;
+ }
+
+ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key"));
+ return 0;
+ }
+
+ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
+ ASSERT_COND(p_StatsCounters);
+
+ /* The first counter is byte counter, so we need to advance to the next counter */
+ frameCount = GET_UINT32(*(uint32_t *)(PTR_MOVE(p_StatsCounters,
+ FM_PCD_CC_STATS_COUNTER_SIZE)));
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ return frameCount;
+}
+
+t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ err = MatchTableGetKeyStatistics(p_CcNode,
+ keyIndex,
+ p_KeyStatistics);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ uint32_t intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the "
+ "match table of the provided node"));
+ }
+
+ err = MatchTableGetKeyStatistics(p_CcNode,
+ keyIndex,
+ p_KeyStatistics);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t hashShift,
+ t_Handle *p_CcNodeBucketHandle,
+ uint8_t *p_BucketIndex,
+ uint16_t *p_LastIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t glblMask;
+ uint64_t crc64 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER);
+
+ memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2);
+
+ crc64 = crc64_init();
+ crc64 = crc64_compute(p_Key, keySize, crc64);
+ crc64 >>= hashShift;
+
+ *p_BucketIndex = (uint8_t)(((crc64 >> (8 * (6 - p_CcNode->userOffset))) & glblMask) >> 4);
+ if (*p_BucketIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MINOR, E_NOT_IN_RANGE, ("bucket index!"));
+
+ *p_CcNodeBucketHandle = p_CcNode->keyAndNextEngineParams[*p_BucketIndex].nextEngineParams.params.ccParams.h_CcNode;
+ if (!*p_CcNodeBucketHandle)
+ RETURN_ERROR(MINOR, E_NOT_FOUND, ("bucket!"));
+
+ *p_LastIndex = ((t_FmPcdCcNode *)*p_CcNodeBucketHandle)->numOfKeys;
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param)
+{
+ t_FmPcdCcNode *p_CcNodeHashTbl;
+ t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam;
+ t_Handle h_CcNode;
+ t_FmPcdCcKeyParams *p_HashKeyParams;
+ int i;
+ uint16_t numOfSets, numOfWays, countMask, onesCount = 0;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL);
+
+ if (p_Param->maxNumOfKeys == 0)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Max number of keys must be higher then 0"));
+ return NULL;
+ }
+
+ if (p_Param->hashResMask == 0)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Hash result mask must differ from 0"));
+ return NULL;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_RMON)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("RMON statistics mode is not supported for hash table"));
+ return NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ p_ExactMatchCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams));
+ if (!p_ExactMatchCcNodeParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_ExactMatchCcNodeParam"));
+ return NULL;
+ }
+ memset(p_ExactMatchCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
+
+ p_IndxHashCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams));
+ if (!p_IndxHashCcNodeParam)
+ {
+ XX_Free(p_ExactMatchCcNodeParam);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_IndxHashCcNodeParam"));
+ return NULL;
+ }
+ memset(p_IndxHashCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
+
+ /* Calculate number of sets and number of ways of the hash table */
+ countMask = (uint16_t)(p_Param->hashResMask >> 4);
+ while (countMask)
+ {
+ onesCount++;
+ countMask = (uint16_t)(countMask >> 1);
+ }
+
+ numOfSets = (uint16_t)(1 << onesCount);
+ numOfWays = (uint16_t)DIV_CEIL(p_Param->maxNumOfKeys, numOfSets);
+
+ if (p_Param->maxNumOfKeys % numOfSets)
+ DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up"));
+
+ /* Building exact-match node params, will be used to create the hash buckets */
+ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
+
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_KEY;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_EXACT_MATCH;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.offset = 0;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.size = p_Param->matchKeySize;
+
+ p_ExactMatchCcNodeParam->keysParams.maxNumOfKeys = numOfWays;
+ p_ExactMatchCcNodeParam->keysParams.maskSupport = FALSE;
+ p_ExactMatchCcNodeParam->keysParams.statisticsMode = p_Param->statisticsMode;
+ p_ExactMatchCcNodeParam->keysParams.numOfKeys = 0;
+ p_ExactMatchCcNodeParam->keysParams.keySize = p_Param->matchKeySize;
+ p_ExactMatchCcNodeParam->keysParams.ccNextEngineParamsForMiss = p_Param->ccNextEngineParamsForMiss;
+
+ p_HashKeyParams = p_IndxHashCcNodeParam->keysParams.keyParams;
+
+ for (i = 0; i < numOfSets; i++)
+ {
+ h_CcNode = FM_PCD_MatchTableSet(h_FmPcd, p_ExactMatchCcNodeParam);
+ if (!h_CcNode)
+ break;
+
+ p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC;
+ p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE;
+ p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = h_CcNode;
+ }
+
+ if (i < numOfSets)
+ {
+ for (i = i-1; i >=0; i--)
+ FM_PCD_MatchTableDelete(p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode);
+
+ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG);
+ XX_Free(p_IndxHashCcNodeParam);
+ XX_Free(p_ExactMatchCcNodeParam);
+ return NULL;
+ }
+
+ /* Creating indexed-hash CC node */
+ p_IndxHashCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_HASH;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_INDEXED_LOOKUP;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.icIndxMask = p_Param->hashResMask;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.offset = p_Param->hashShift;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.size = 2;
+
+ p_IndxHashCcNodeParam->keysParams.maxNumOfKeys = numOfSets;
+ p_IndxHashCcNodeParam->keysParams.maskSupport = FALSE;
+ p_IndxHashCcNodeParam->keysParams.statisticsMode = e_FM_PCD_CC_STATS_MODE_NONE;
+ p_IndxHashCcNodeParam->keysParams.numOfKeys = numOfSets; /* Number of keys of this node is number of sets of the hash */
+ p_IndxHashCcNodeParam->keysParams.keySize = 2;
+
+ p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam);
+
+ XX_Free(p_IndxHashCcNodeParam);
+ XX_Free(p_ExactMatchCcNodeParam);
+
+ return p_CcNodeHashTbl;
+}
+
+t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle *p_HashBuckets;
+ uint16_t i, numOfBuckets;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+
+ numOfBuckets = p_HashTbl->numOfKeys;
+
+ p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle));
+ if (!p_HashBuckets)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ for (i = 0; i < numOfBuckets; i++)
+ p_HashBuckets[i] = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+
+ err = FM_PCD_MatchTableDelete(p_HashTbl);
+
+ for (i = 0; i < numOfBuckets; i++)
+ err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]);
+
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ XX_Free(p_HashBuckets);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams->p_Key, E_NULL_POINTER);
+
+ if (p_KeyParams->p_Mask)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Keys masks not supported for hash table"));
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_KeyParams->p_Key,
+ p_HashTbl->userOffset,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableAddKey(h_HashBucket,
+ FM_PCD_LAST_KEY_INDEX,
+ keySize,
+ p_KeyParams);
+}
+
+t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->userOffset,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNRemoveKey(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL);
+}
+
+t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->userOffset,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNModifyNextEngine(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL,
+ p_FmPcdCcNextEngineParams);
+}
+
+t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t i;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ for (i = 0; i < p_HashTbl->numOfKeys; i++)
+ {
+ h_HashBucket = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+
+ err = FM_PCD_MatchTableModifyMissNextEngine(h_HashBucket,
+ p_FmPcdCcNextEngineParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+
+t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_FmPcdCcNode *p_HashBucket;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+
+ /* Miss next engine of each bucket was initialized with the next engine of the hash table */
+ p_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode;
+
+ memcpy(p_FmPcdCcNextEngineParams,
+ &p_HashBucket->keyAndNextEngineParams[p_HashBucket->numOfKeys].nextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->userOffset,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNGetKeyStatistics(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL,
+ p_KeyStatistics);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h
new file mode 100644
index 0000000..9efe721
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_cc.h
+
+ @Description FM PCD CC ...
+*//***************************************************************************/
+#ifndef __FM_CC_H
+#define __FM_CC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_pcd.h"
+
+
+/***********************************************************************/
+/* Coarse classification defines */
+/***********************************************************************/
+
+#define CC_MAX_NUM_OF_KEYS MAX(FM_PCD_MAX_NUM_OF_KEYS + 1, FM_PCD_MAX_NUM_OF_FLOWS)
+
+#define CC_PC_FF_MACDST 0x00
+#define CC_PC_FF_MACSRC 0x01
+#define CC_PC_FF_ETYPE 0x02
+
+#define CC_PC_FF_TCI1 0x03
+#define CC_PC_FF_TCI2 0x04
+
+#define CC_PC_FF_MPLS1 0x06
+#define CC_PC_FF_MPLS_LAST 0x07
+
+#define CC_PC_FF_IPV4DST1 0x08
+#define CC_PC_FF_IPV4DST2 0x16
+#define CC_PC_FF_IPV4IPTOS_TC1 0x09
+#define CC_PC_FF_IPV4IPTOS_TC2 0x17
+#define CC_PC_FF_IPV4PTYPE1 0x0A
+#define CC_PC_FF_IPV4PTYPE2 0x18
+#define CC_PC_FF_IPV4SRC1 0x0b
+#define CC_PC_FF_IPV4SRC2 0x19
+#define CC_PC_FF_IPV4SRC1_IPV4DST1 0x0c
+#define CC_PC_FF_IPV4SRC2_IPV4DST2 0x1a
+#define CC_PC_FF_IPV4TTL 0x29
+
+
+#define CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1 0x0d /*TODO - CLASS - what is it? TOS*/
+#define CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2 0x1b
+#define CC_PC_FF_IPV6PTYPE1 0x0e
+#define CC_PC_FF_IPV6PTYPE2 0x1c
+#define CC_PC_FF_IPV6DST1 0x0f
+#define CC_PC_FF_IPV6DST2 0x1d
+#define CC_PC_FF_IPV6SRC1 0x10
+#define CC_PC_FF_IPV6SRC2 0x1e
+#define CC_PC_FF_IPV6HOP_LIMIT 0x2a
+#define CC_PC_FF_IPPID 0x24
+#define CC_PC_FF_IPDSCP 0x76
+
+#define CC_PC_FF_GREPTYPE 0x11
+
+#define CC_PC_FF_MINENCAP_PTYPE 0x12
+#define CC_PC_FF_MINENCAP_IPDST 0x13
+#define CC_PC_FF_MINENCAP_IPSRC 0x14
+#define CC_PC_FF_MINENCAP_IPSRC_IPDST 0x15
+
+#define CC_PC_FF_L4PSRC 0x1f
+#define CC_PC_FF_L4PDST 0x20
+#define CC_PC_FF_L4PSRC_L4PDST 0x21
+
+#define CC_PC_FF_PPPPID 0x05
+
+#define CC_PC_PR_SHIM1 0x22
+#define CC_PC_PR_SHIM2 0x23
+
+#define CC_PC_GENERIC_WITHOUT_MASK 0x27
+#define CC_PC_GENERIC_WITH_MASK 0x28
+#define CC_PC_GENERIC_IC_GMASK 0x2B
+#define CC_PC_GENERIC_IC_HASH_INDEXED 0x2C
+
+#define CC_PR_OFFSET 0x25
+#define CC_PR_WITHOUT_OFFSET 0x26
+
+#define CC_PC_PR_ETH_OFFSET 19
+#define CC_PC_PR_USER_DEFINED_SHIM1_OFFSET 16
+#define CC_PC_PR_USER_DEFINED_SHIM2_OFFSET 17
+#define CC_PC_PR_USER_LLC_SNAP_OFFSET 20
+#define CC_PC_PR_VLAN1_OFFSET 21
+#define CC_PC_PR_VLAN2_OFFSET 22
+#define CC_PC_PR_PPPOE_OFFSET 24
+#define CC_PC_PR_MPLS1_OFFSET 25
+#define CC_PC_PR_MPLS_LAST_OFFSET 26
+#define CC_PC_PR_IP1_OFFSET 27
+#define CC_PC_PR_IP_LAST_OFFSET 28
+#define CC_PC_PR_MINENC_OFFSET 28
+#define CC_PC_PR_L4_OFFSET 30
+#define CC_PC_PR_GRE_OFFSET 29
+#define CC_PC_PR_ETYPE_LAST_OFFSET 23
+#define CC_PC_PR_NEXT_HEADER_OFFSET 31
+
+#define CC_PC_ILLEGAL 0xff
+#define CC_SIZE_ILLEGAL 0
+
+#define FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN 16
+#define FM_PCD_CC_AD_TABLE_ALIGN 16
+#define FM_PCD_CC_AD_ENTRY_SIZE 16
+#define FM_PCD_CC_NUM_OF_KEYS 255
+#define FM_PCD_CC_TREE_ADDR_ALIGN 256
+
+#define FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE 0x00000000
+#define FM_PCD_AD_RESULT_DATA_FLOW_TYPE 0x80000000
+#define FM_PCD_AD_RESULT_PLCR_DIS 0x20000000
+#define FM_PCD_AD_RESULT_EXTENDED_MODE 0x80000000
+#define FM_PCD_AD_RESULT_NADEN 0x20000000
+#define FM_PCD_AD_RESULT_STATISTICS_EN 0x40000000
+
+#define FM_PCD_AD_CONT_LOOKUP_TYPE 0x40000000
+#define FM_PCD_AD_CONT_LOOKUP_LCL_MASK 0x00800000
+
+#define FM_PCD_AD_STATS_TYPE 0x40000000
+#define FM_PCD_AD_STATS_FLR_ADDR_MASK 0x00FFFFFF
+#define FM_PCD_AD_STATS_COUNTERS_ADDR_MASK 0x00FFFFFF
+#define FM_PCD_AD_STATS_NEXT_ACTION_MASK 0xFFFF0000
+#define FM_PCD_AD_STATS_NEXT_ACTION_SHIFT 12
+#define FM_PCD_AD_STATS_NAD_EN 0x00008000
+#define FM_PCD_AD_STATS_OP_CODE 0x00000036
+#define FM_PCD_AD_STATS_FLR_EN 0x00004000
+#define FM_PCD_AD_STATS_COND_EN 0x00002000
+
+
+
+#define FM_PCD_AD_BYPASS_TYPE 0xc0000000
+
+#define FM_PCD_AD_TYPE_MASK 0xc0000000
+#define FM_PCD_AD_OPCODE_MASK 0x0000000f
+
+#define FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT 16
+#if (DPAA_VERSION >= 11)
+#define FM_PCD_AD_RESULT_VSP_SHIFT 24
+#define FM_PCD_AD_RESULT_NO_OM_VSPE 0x02000000
+#define FM_PCD_AD_RESULT_VSP_MASK 0x3f
+#define FM_PCD_AD_NCSPFQIDM_MASK 0x80000000
+#endif /* (DPAA_VERSION >= 11) */
+
+#define GLBL_MASK_FOR_HASH_INDEXED 0xfff00000
+#define CC_GLBL_MASK_SIZE 4
+
+typedef uint32_t ccPrivateInfo_t; /**< private info of CC: */
+
+#define CC_PRIVATE_INFO_NONE 0
+#define CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP 0x80000000
+#define CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH 0x40000000
+#define CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH 0x20000000
+#define CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP 0x10000000
+
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct
+{
+ volatile uint32_t fqid;
+ volatile uint32_t plcrProfile;
+ volatile uint32_t nia;
+ volatile uint32_t res;
+} _PackedType t_AdOfTypeResult;
+
+typedef _Packed struct
+{
+ volatile uint32_t ccAdBase;
+ volatile uint32_t matchTblPtr;
+ volatile uint32_t pcAndOffsets;
+ volatile uint32_t gmask;
+} _PackedType t_AdOfTypeContLookup;
+
+typedef _Packed struct
+{
+ volatile uint32_t profileTableAddr;
+ volatile uint32_t reserved;
+ volatile uint32_t nextActionIndx;
+ volatile uint32_t statsTableAddr;
+} _PackedType t_AdOfTypeStats;
+
+typedef _Packed union
+{
+ volatile t_AdOfTypeResult adResult;
+ volatile t_AdOfTypeContLookup adContLookup;
+} _PackedType t_Ad;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+
+typedef enum e_ModifyState
+{
+ e_MODIFY_STATE_ADD = 0,
+ e_MODIFY_STATE_REMOVE,
+ e_MODIFY_STATE_CHANGE
+} e_ModifyState;
+
+typedef struct t_FmPcdStatsObj
+{
+ t_Handle h_StatsAd;
+ t_Handle h_StatsCounters;
+ t_List node;
+} t_FmPcdStatsObj;
+
+typedef struct
+{
+ uint8_t key[FM_PCD_MAX_SIZE_OF_KEY];
+ uint8_t mask[FM_PCD_MAX_SIZE_OF_KEY];
+
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ uint32_t requiredAction;
+ uint32_t shadowAction;
+
+ t_FmPcdStatsObj *p_StatsObj;
+
+} t_FmPcdCcKeyAndNextEngineParams;
+
+typedef struct
+{
+ t_Handle p_Ad;
+ e_FmPcdEngine fmPcdEngine;
+ bool adAllocated;
+ bool isTree;
+
+ uint32_t myInfo;
+ t_List *h_CcNextNodesLst;
+ t_Handle h_AdditionalInfo;
+ t_Handle h_Node;
+} t_FmPcdModifyCcAdditionalParams;
+
+typedef struct
+{
+ t_Handle p_AdTableNew;
+ t_Handle p_KeysMatchTableNew;
+ t_Handle p_AdTableOld;
+ t_Handle p_KeysMatchTableOld;
+ uint16_t numOfKeys;
+ t_Handle h_CurrentNode;
+ uint16_t savedKeyIndex;
+ t_Handle h_NodeForAdd;
+ t_Handle h_NodeForRmv;
+ t_Handle h_ManipForRmv;
+ t_Handle h_ManipForAdd;
+ t_FmPcdStatsObj *p_StatsObjForRmv;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_FrmReplicForAdd;
+ t_Handle h_FrmReplicForRmv;
+#endif /* (DPAA_VERSION >= 11) */
+ bool tree;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS];
+} t_FmPcdModifyCcKeyAdditionalParams;
+
+typedef struct
+{
+ t_Handle h_Manip;
+ t_Handle h_CcNode;
+} t_CcNextEngineInfo;
+
+typedef struct
+{
+ uint16_t numOfKeys;
+ uint16_t maxNumOfKeys;
+
+ bool maskSupport;
+ uint32_t keysMatchTableMaxSize;
+
+ e_FmPcdCcStatsMode statisticsMode;
+ uint32_t numOfStatsFLRs;
+ uint32_t countersArraySize;
+
+ bool glblMaskUpdated;
+ t_Handle p_GlblMask;
+ bool lclMask;
+ uint8_t parseCode;
+ uint8_t offset;
+ uint8_t prsArrayOffset;
+ bool ctrlFlow;
+ uint8_t owners;
+
+ uint8_t ccKeySizeAccExtraction;
+ uint8_t sizeOfExtraction;
+ uint8_t glblMaskSize;
+
+ t_Handle h_KeysMatchTable;
+ t_Handle h_AdTable;
+ t_Handle h_StatsAds;
+ t_Handle h_Ad;
+ t_Handle h_StatsFLRs;
+
+ t_List availableStatsLst;
+
+ t_List ccPrevNodesLst;
+
+ t_List ccTreeIdLst;
+ t_List ccTreesLst;
+
+ t_Handle h_FmPcd;
+ uint32_t shadowAction;
+ uint8_t userSizeOfExtraction;
+ uint8_t userOffset;
+
+ t_Handle h_Spinlock;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS];
+} t_FmPcdCcNode;
+
+typedef struct
+{
+ t_FmPcdCcNode *p_FmPcdCcNode;
+ bool occupied;
+ uint8_t owners;
+ volatile bool lock;
+} t_FmPcdCcNodeArray;
+
+typedef struct
+{
+ uint8_t numOfEntriesInGroup;
+ uint32_t totalBitsMask;
+ uint8_t baseGroupEntry;
+} t_FmPcdCcGroupParam;
+
+typedef struct
+{
+ t_Handle h_FmPcd;
+ uint8_t netEnvId;
+ uintptr_t ccTreeBaseAddr;
+ uint8_t numOfGrps;
+ t_FmPcdCcGroupParam fmPcdGroupParam[FM_PCD_MAX_NUM_OF_CC_GROUPS];
+ t_List fmPortsLst;
+ t_FmPcdLock *p_Lock;
+ uint8_t numOfEntries;
+ uint8_t owners;
+ t_Handle h_FmPcdCcSavedManipParams;
+ bool modifiedState;
+ uint32_t requiredAction;
+ t_Handle h_IpReassemblyManip;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[FM_PCD_MAX_NUM_OF_CC_GROUPS];
+} t_FmPcdCcTree;
+
+
+bool FmPcdManipIsManipNode(t_Handle h_Ad);
+t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List);
+void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List);
+t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align);
+
+
+#endif /* __FM_CC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c
new file mode 100644
index 0000000..bdbc8ae
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c
@@ -0,0 +1,3263 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_kg.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_port_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_pcd_ipc.h"
+#include "fm_kg.h"
+#include "fsl_fman_kg.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static uint32_t KgHwLock(t_Handle h_FmPcdKg)
+{
+ ASSERT_COND(h_FmPcdKg);
+ return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock);
+}
+
+static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdKg);
+ XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags);
+}
+
+static uint32_t KgSchemeLock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags)
+{
+ ASSERT_COND(h_Scheme);
+ FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags);
+}
+
+static bool KgSchemeFlagTryLock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static void KgSchemeFlagUnlock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar)
+{
+
+ struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (fman_kg_write_ar_wait(regs, fmkg_ar))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation"));
+
+ return E_OK;
+}
+
+static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code)
+{
+ int i;
+
+ switch (code)
+ {
+ case (KG_SCH_GEN_PARSE_RESULT_N_FQID):
+ case (KG_SCH_GEN_DEFAULT):
+ case (KG_SCH_GEN_NEXTHDR):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_NOT_FROM_DATA)
+ return swDefaults[i].dfltSelect;
+ ASSERT_COND(FALSE);
+ case (KG_SCH_GEN_SHIM1):
+ case (KG_SCH_GEN_SHIM2):
+ case (KG_SCH_GEN_IP_PID_NO_V):
+ case (KG_SCH_GEN_ETH_NO_V):
+ case (KG_SCH_GEN_SNAP_NO_V):
+ case (KG_SCH_GEN_VLAN1_NO_V):
+ case (KG_SCH_GEN_VLAN2_NO_V):
+ case (KG_SCH_GEN_ETH_TYPE_NO_V):
+ case (KG_SCH_GEN_PPP_NO_V):
+ case (KG_SCH_GEN_MPLS1_NO_V):
+ case (KG_SCH_GEN_MPLS_LAST_NO_V):
+ case (KG_SCH_GEN_L3_NO_V):
+ case (KG_SCH_GEN_IP2_NO_V):
+ case (KG_SCH_GEN_GRE_NO_V):
+ case (KG_SCH_GEN_L4_NO_V):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V)
+ return swDefaults[i].dfltSelect;
+
+ case (KG_SCH_GEN_START_OF_FRM):
+ case (KG_SCH_GEN_ETH):
+ case (KG_SCH_GEN_SNAP):
+ case (KG_SCH_GEN_VLAN1):
+ case (KG_SCH_GEN_VLAN2):
+ case (KG_SCH_GEN_ETH_TYPE):
+ case (KG_SCH_GEN_PPP):
+ case (KG_SCH_GEN_MPLS1):
+ case (KG_SCH_GEN_MPLS2):
+ case (KG_SCH_GEN_MPLS3):
+ case (KG_SCH_GEN_MPLS_LAST):
+ case (KG_SCH_GEN_IPV4):
+ case (KG_SCH_GEN_IPV6):
+ case (KG_SCH_GEN_IPV4_TUNNELED):
+ case (KG_SCH_GEN_IPV6_TUNNELED):
+ case (KG_SCH_GEN_MIN_ENCAP):
+ case (KG_SCH_GEN_GRE):
+ case (KG_SCH_GEN_TCP):
+ case (KG_SCH_GEN_UDP):
+ case (KG_SCH_GEN_IPSEC_AH):
+ case (KG_SCH_GEN_SCTP):
+ case (KG_SCH_GEN_DCCP):
+ case (KG_SCH_GEN_IPSEC_ESP):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA)
+ return swDefaults[i].dfltSelect;
+ default:
+ return e_FM_PCD_KG_DFLT_ILLEGAL;
+ }
+}
+
+static uint8_t GetGenCode(e_FmPcdExtractFrom src, uint8_t *p_Offset)
+{
+ *p_Offset = 0;
+
+ switch (src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
+ return KG_SCH_GEN_START_OF_FRM;
+ case (e_FM_PCD_EXTRACT_FROM_DFLT_VALUE):
+ return KG_SCH_GEN_DEFAULT;
+ case (e_FM_PCD_EXTRACT_FROM_PARSE_RESULT):
+ return KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ case (e_FM_PCD_EXTRACT_FROM_ENQ_FQID):
+ *p_Offset = 32;
+ return KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
+ return KG_SCH_GEN_NEXTHDR;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ return 0;
+ }
+}
+
+static uint8_t GetGenHdrCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex, bool ignoreProtocolValidation)
+{
+ if (!ignoreProtocolValidation)
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ return KG_SCH_GEN_ETH;
+ case (HEADER_TYPE_LLC_SNAP):
+ return KG_SCH_GEN_SNAP;
+ case (HEADER_TYPE_PPPoE):
+ return KG_SCH_GEN_PPP;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_MPLS1;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_GEN_MPLS2;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_3)
+ return KG_SCH_GEN_MPLS3;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return 0;
+ case (HEADER_TYPE_IPv4):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_IPV4;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IPV4_TUNNELED;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 header index"));
+ return 0;
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_IPV6;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IPV6_TUNNELED;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 header index"));
+ return 0;
+ case (HEADER_TYPE_GRE):
+ return KG_SCH_GEN_GRE;
+ case (HEADER_TYPE_TCP):
+ return KG_SCH_GEN_TCP;
+ case (HEADER_TYPE_UDP):
+ return KG_SCH_GEN_UDP;
+ case (HEADER_TYPE_IPSEC_AH):
+ return KG_SCH_GEN_IPSEC_AH;
+ case (HEADER_TYPE_IPSEC_ESP):
+ return KG_SCH_GEN_IPSEC_ESP;
+ case (HEADER_TYPE_SCTP):
+ return KG_SCH_GEN_SCTP;
+ case (HEADER_TYPE_DCCP):
+ return KG_SCH_GEN_DCCP;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ else
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ return KG_SCH_GEN_ETH_NO_V;
+ case (HEADER_TYPE_LLC_SNAP):
+ return KG_SCH_GEN_SNAP_NO_V;
+ case (HEADER_TYPE_PPPoE):
+ return KG_SCH_GEN_PPP_NO_V;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_MPLS1_NO_V;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_MPLS_LAST_NO_V;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_3) )
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Indexed MPLS Extraction not supported"));
+ else
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return 0;
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_L3_NO_V;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IP2_NO_V;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
+ case (HEADER_TYPE_MINENCAP):
+ return KG_SCH_GEN_IP2_NO_V;
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ return KG_SCH_GEN_L3_NO_V;
+ case (HEADER_TYPE_GRE):
+ return KG_SCH_GEN_GRE_NO_V;
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ return KG_SCH_GEN_L4_NO_V;
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ return KG_SCH_GEN_SHIM1;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ return KG_SCH_GEN_SHIM2;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+}
+static t_GenericCodes GetGenFieldCode(e_NetHeaderType hdr, t_FmPcdFields field, bool ignoreProtocolValidation, e_FmPcdHdrIndex hdrIndex)
+{
+ if (!ignoreProtocolValidation)
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_GEN_ETH_TYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_VLAN1;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_VLAN2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_LLC_SNAP):
+ case (HEADER_TYPE_PPPoE):
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ case (HEADER_TYPE_GRE):
+ case (HEADER_TYPE_MINENCAP):
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_USER_DEFINED_L4):
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
+ return 0;
+ }
+ else
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_GEN_ETH_TYPE_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI) :
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_VLAN1_NO_V;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_VLAN2_NO_V;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ return KG_SCH_GEN_IP_PID_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ return KG_SCH_GEN_IP_PID_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ case (HEADER_TYPE_LLC_SNAP):
+ case (HEADER_TYPE_PPPoE):
+ case (HEADER_TYPE_GRE):
+ case (HEADER_TYPE_MINENCAP):
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_USER_DEFINED_L4):
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
+ return 0;
+ }
+}
+
+static t_KnownFieldsMasks GetKnownProtMask(t_FmPcd *p_FmPcd, e_NetHeaderType hdr, e_FmPcdHdrIndex index, t_FmPcdFields field)
+{
+ UNUSED(p_FmPcd);
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ return KG_SCH_KN_MACDST;
+ case (NET_HEADER_FIELD_ETH_SA):
+ return KG_SCH_KN_MACSRC;
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_KN_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_LLC_SNAP):
+ switch (field.llcSnap)
+ {
+ case (NET_HEADER_FIELD_LLC_SNAP_TYPE):
+ return KG_SCH_KN_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_TCI1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_KN_TCI2;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_MPLS1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_KN_MPLS2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_KN_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPSRC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPSRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPDST1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPDST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_PTYPE1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_PTYPE2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPTOS_TC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPTOS_TC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPSRC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPSRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPDST1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPDST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_PTYPE1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_KN_PTYPE2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+#ifdef FM_KG_NO_IPPID_SUPPORT
+ if (p_FmPcd->fmRevInfo.majorRev < 6)
+ return KG_SCH_KN_PTYPE2;
+#endif /* FM_KG_NO_IPPID_SUPPORT */
+ return KG_SCH_KN_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1);
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2);
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case (NET_HEADER_FIELD_GRE_TYPE):
+ return KG_SCH_KN_GREPTYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ return KG_SCH_KN_IPSRC2;
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return KG_SCH_KN_IPDST2;
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ return KG_SCH_KN_PTYPE2;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ case (NET_HEADER_FIELD_TCP_FLAGS):
+ return KG_SCH_KN_TFLG;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPSEC_AH):
+ switch (field.ipsecAh)
+ {
+ case (NET_HEADER_FIELD_IPSEC_AH_SPI):
+ return KG_SCH_KN_IPSEC_SPI;
+ case (NET_HEADER_FIELD_IPSEC_AH_NH):
+ return KG_SCH_KN_IPSEC_NH;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPSEC_ESP):
+ switch (field.ipsecEsp)
+ {
+ case (NET_HEADER_FIELD_IPSEC_ESP_SPI):
+ return KG_SCH_KN_IPSEC_SPI;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_SCTP):
+ switch (field.sctp)
+ {
+ case (NET_HEADER_FIELD_SCTP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_SCTP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_DCCP):
+ switch (field.dccp)
+ {
+ case (NET_HEADER_FIELD_DCCP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_DCCP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ return KG_SCH_KN_PPPID;
+ case (NET_HEADER_FIELD_PPPoE_SID):
+ return KG_SCH_KN_PPPSID;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+}
+
+
+static uint8_t GetKnownFieldId(uint32_t bitMask)
+{
+ uint8_t cnt = 0;
+
+ while (bitMask)
+ if (bitMask & 0x80000000)
+ break;
+ else
+ {
+ cnt++;
+ bitMask <<= 1;
+ }
+ return cnt;
+
+}
+
+static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid)
+{
+ uint8_t i, mask, numOfOnesToClear, walking1Mask = 1;
+
+ /* bitOffset 1-7 --> mask 0x1-0x7F */
+ if (bitOffset<8)
+ {
+ mask = 0;
+ for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1)
+ mask |= walking1Mask;
+ }
+ else
+ {
+ mask = 0xFF;
+ numOfOnesToClear = 0;
+ if (fqid && bitOffset>24)
+ /* bitOffset 25-31 --> mask 0xFE-0x80 */
+ numOfOnesToClear = (uint8_t)(bitOffset-24);
+ else
+ /* bitOffset 9-15 --> mask 0xFE-0x80 */
+ if (!fqid && bitOffset>8)
+ numOfOnesToClear = (uint8_t)(bitOffset-8);
+ for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1)
+ mask &= ~walking1Mask;
+ /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/
+ }
+ return mask;
+}
+
+static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
+{
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdKgScheme *p_Scheme;
+ uint32_t intFlags;
+ uint8_t relativeSchemeId;
+ int i;
+
+ p_FmPcdKg = p_FmPcd->p_FmPcdKg;
+
+ /* for each scheme - update owners counters */
+ for (i = 0; i < p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
+
+ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
+
+ /* increment owners number */
+ intFlags = KgSchemeLock(p_Scheme);
+ p_Scheme->owners++;
+ KgSchemeUnlock(p_Scheme, intFlags);
+ }
+}
+
+static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
+{
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdKgScheme *p_Scheme;
+ uint32_t intFlags;
+ uint8_t relativeSchemeId;
+ int i;
+
+ p_FmPcdKg = p_FmPcd->p_FmPcdKg;
+
+ /* for each scheme - update owners counters */
+ for (i = 0; i < p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
+
+ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
+
+ /* increment owners number */
+ ASSERT_COND(p_Scheme->owners);
+ intFlags = KgSchemeLock(p_Scheme);
+ p_Scheme->owners--;
+ KgSchemeUnlock(p_Scheme, intFlags);
+ }
+}
+
+static void UpateSchemePointedOwner(t_FmPcdKgScheme *p_Scheme, bool add)
+{
+ /* this routine is locked by the calling routine */
+ ASSERT_COND(p_Scheme);
+ ASSERT_COND(p_Scheme->valid);
+
+ if (add)
+ p_Scheme->pointedOwners++;
+ else
+ p_Scheme->pointedOwners--;
+}
+
+static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add)
+{
+ struct fman_kg_regs *p_KgRegs;
+
+ uint32_t tmpKgarReg = 0, intFlags;
+ t_Error err = E_OK;
+
+ /* The calling routine had locked the port, so for each port only one core can access
+ * (so we don't need a lock here) */
+
+ if (p_FmPcd->h_Hc)
+ return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add);
+
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+ /* lock a common KG reg */
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ {
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ fman_kg_write_sp(p_KgRegs, spReg, add);
+
+ tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
+
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ return err;
+}
+
+static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg)
+{
+ struct fman_kg_regs *p_KgRegs;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err;
+
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg);
+ return err;
+ }
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ fman_kg_write_cpp(p_KgRegs, cppReg);
+ tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return err;
+}
+
+static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId)
+{
+ uint32_t tmpKgpeCpp;
+
+ tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8);
+ tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT);
+
+ return tmpKgpeCpp;
+}
+
+static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
+{
+ uint32_t tmpKgpeCpp = 0;
+
+ tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId);
+ return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp);
+}
+
+static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
+{
+ KgWriteCpp(p_FmPcd, hardwarePortId, 0);
+}
+
+static uint32_t ReadClsPlanBlockActionReg(uint8_t grpId)
+{
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ DUMMY_PORT_ID |
+ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_PCD_KG_KGAR_WSEL_MASK);
+
+ /* if we ever want to write 1 by 1, use:
+ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
+ */
+}
+
+static void PcdKgErrorException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event,schemeIndexes = 0, index = 0;
+ struct fman_kg_regs *p_KgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+ fman_kg_get_event(p_KgRegs, &event, &schemeIndexes);
+
+ if (event & FM_EX_KG_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC);
+ if (event & FM_EX_KG_KEYSIZE_OVERFLOW)
+ {
+ if (schemeIndexes)
+ {
+ while (schemeIndexes)
+ {
+ if (schemeIndexes & 0x1)
+ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index));
+ schemeIndexes >>= 1;
+ index+=1;
+ }
+ }
+ else /* this should happen only when interrupt is forced. */
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW);
+ }
+}
+
+static t_Error KgInitGuest(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+ t_FmPcdIpcKgSchemesParams kgAlloc;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+ t_FmPcdIpcMsg msg;
+
+ ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID);
+
+ /* in GUEST_PARTITION, we use the IPC */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams));
+ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
+ kgAlloc.guestId = p_FmPcd->guestId;
+ msg.msgId = FM_PCD_ALLOC_KG_SCHEMES;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t));
+
+ return (t_Error)reply.error;
+}
+
+static t_Error KgInitMaster(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+
+ if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd));
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_KG,
+ 0,
+ e_FM_INTR_TYPE_ERR,
+ PcdKgErrorException,
+ p_FmPcd);
+
+ fman_kg_enable_scheme_interrupts(p_Regs);
+
+ if (p_FmPcd->p_FmPcdKg->numOfSchemes)
+ {
+ err = FmPcdKgAllocSchemes(p_FmPcd,
+ p_FmPcd->p_FmPcdKg->numOfSchemes,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->schemesIds);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+static void ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
+{
+ ASSERT_COND(!p_Scheme->valid);
+ if (p_Scheme->netEnvId != ILLEGAL_NETENV)
+ FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
+ p_Scheme->valid = TRUE;
+}
+
+static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
+{
+ if (p_Scheme->owners)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to"));
+
+ if (p_Scheme->netEnvId != ILLEGAL_NETENV)
+ FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
+ p_Scheme->valid = FALSE;
+
+ return E_OK;
+}
+
+static t_Error BuildSchemeRegs(t_FmPcdKgScheme *p_Scheme,
+ t_FmPcdKgSchemeParams *p_SchemeParams,
+ struct fman_kg_scheme_regs *p_SchemeRegs)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd);
+ uint32_t grpBits = 0;
+ uint8_t grpBase;
+ bool direct=TRUE, absolute=FALSE;
+ uint16_t profileId=0, numOfProfiles=0, relativeProfileId;
+ t_Error err = E_OK;
+ int i = 0;
+ t_NetEnvParams netEnvParams;
+ uint32_t tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp;
+ t_FmPcdKgKeyExtractAndHashParams *p_KeyAndHash = NULL;
+ uint8_t j, curr, idx;
+ uint8_t id, shift=0, code=0, offset=0, size=0;
+ t_FmPcdExtractEntry *p_Extract = NULL;
+ t_FmPcdKgExtractedOrParams *p_ExtractOr;
+ bool generic = FALSE;
+ t_KnownFieldsMasks bitMask;
+ e_FmPcdKgExtractDfltSelect swDefault = (e_FmPcdKgExtractDfltSelect)0;
+ t_FmPcdKgSchemesExtracts *p_LocalExtractsArray;
+ uint8_t numOfSwDefaults = 0;
+ t_FmPcdKgExtractDflt swDefaults[NUM_OF_SW_DEFAULTS];
+ uint8_t currGenId = 0;
+
+ memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt));
+ memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
+
+ if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS));
+
+ /* by netEnv parameters, get match vector */
+ if (!p_SchemeParams->alwaysDirect)
+ {
+ p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv);
+ netEnvParams.netEnvId = p_Scheme->netEnvId;
+ netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits;
+ memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits);
+ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ p_Scheme->matchVector = netEnvParams.vector;
+ }
+ else
+ {
+ p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT;
+ p_Scheme->netEnvId = ILLEGAL_NETENV;
+ }
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid"));
+
+ if (p_SchemeParams->bypassFqidGeneration)
+ {
+#ifdef FM_KG_NO_BYPASS_FQID_GEN
+ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration."));
+#endif /* FM_KG_NO_BYPASS_FQID_GEN */
+ if (p_SchemeParams->baseFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID"));
+ }
+ else
+ if (!p_SchemeParams->baseFqid)
+ DBG(WARNING, ("baseFqid is 0."));
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR)
+ {
+ direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct;
+ p_Scheme->directPlcr = direct;
+ absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE);
+ if (!direct && absolute)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared."));
+
+ if (direct)
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ }
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_CC)
+ {
+#ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN
+ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
+ {
+ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration."));
+ }
+#endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */
+
+ err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree,
+ p_SchemeParams->kgNextEngineParams.cc.grpId,
+ &grpBits,
+ &grpBase);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_Scheme->ccUnits = grpBits;
+
+ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
+ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
+ {
+ if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification."));
+ absolute = FALSE;
+ direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct;
+ if (direct)
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ }
+ }
+
+ /* if policer is used directly after KG, or after CC */
+ if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR) ||
+ ((p_SchemeParams->nextEngine == e_FM_PCD_CC) &&
+ (p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
+ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)))
+ {
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (absolute)
+ {
+ /* for absolute direct policy only, */
+ relativeProfileId = profileId;
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid."));
+ p_Scheme->relativeProfileId = profileId;
+ }
+ else
+ {
+ /* save relative profile id's for later check */
+ p_Scheme->nextRelativePlcrProfile = TRUE;
+ p_Scheme->relativeProfileId = profileId;
+ p_Scheme->numOfProfiles = numOfProfiles;
+ }
+ }
+ else
+ {
+ /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration
+ is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */
+ if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID"));
+ if (p_SchemeParams->bypassFqidGeneration &&
+ p_SchemeParams->useHash &&
+ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID"));
+ }
+
+ /* configure all 21 scheme registers */
+ tmpReg = KG_SCH_MODE_EN;
+ switch (p_SchemeParams->nextEngine)
+ {
+ case (e_FM_PCD_PLCR):
+ /* add to mode register - NIA */
+ tmpReg |= KG_SCH_MODE_NIA_PLCR;
+ tmpReg |= NIA_ENG_PLCR;
+ tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0);
+ /* initialize policer profile command - */
+ /* configure kgse_ppc */
+ if (direct)
+ /* use profileId as base, other fields are 0 */
+ p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
+ else
+ {
+ if (shift > MAX_PP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
+
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
+ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
+ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
+ ppcTmp |= (uint32_t)profileId;
+
+ p_SchemeRegs->kgse_ppc = ppcTmp;
+ }
+ break;
+ case (e_FM_PCD_CC):
+ /* mode reg - define NIA */
+ tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
+
+ p_SchemeRegs->kgse_ccbs = grpBits;
+ tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT);
+
+ if (p_SchemeParams->kgNextEngineParams.cc.plcrNext)
+ {
+ if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)
+ {
+ /* find out if absolute or relative */
+ if (absolute)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow"));
+ if (direct)
+ {
+ /* mask = 0, base = directProfileId */
+ p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
+ }
+ else
+ {
+ if (shift > MAX_PP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
+ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
+ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
+ ppcTmp |= (uint32_t)profileId;
+
+ p_SchemeRegs->kgse_ppc = ppcTmp;
+ }
+ }
+ else
+ ppcTmp = KG_SCH_PP_NO_GEN;
+ }
+ break;
+ case (e_FM_PCD_DONE):
+ if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME)
+ tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ else
+ tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported"));
+ }
+ p_SchemeRegs->kgse_mode = tmpReg;
+
+ p_SchemeRegs->kgse_mv = p_Scheme->matchVector;
+
+#if (DPAA_VERSION >= 11)
+ if (p_SchemeParams->overrideStorageProfile)
+ {
+ p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE;
+
+ tmpReg = 0;
+ if (p_SchemeParams->storageProfile.direct)
+ {
+ profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId;
+ shift = 0;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ if (shift > MAX_SP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT));
+
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT;
+ tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT);
+ tmpReg |= (uint32_t)profileId;
+
+
+ p_SchemeRegs->kgse_vsp = tmpReg;
+
+ p_Scheme->vspe = TRUE;
+
+ }
+ else
+ p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_SchemeParams->useHash)
+ {
+ p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams;
+
+ if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range"));
+
+ /* configure kgse_dv0 */
+ p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0;
+
+ /* configure kgse_dv1 */
+ p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1;
+
+ if (!p_SchemeParams->bypassFqidGeneration)
+ {
+ if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2"));
+ if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid)
+ DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues."));
+ }
+
+ /* configure kgse_ekdv */
+ tmpReg = 0;
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedDflts ; i++)
+ {
+ switch (p_KeyAndHash->dflts[i].type)
+ {
+ case (e_FM_PCD_KG_MAC_ADDR):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT);
+ break;
+ case (e_FM_PCD_KG_TCI):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT);
+ break;
+ case (e_FM_PCD_KG_ENET_TYPE):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PPP_SESSION_ID):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PPP_PROTOCOL_ID):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT);
+ break;
+ case (e_FM_PCD_KG_MPLS_LABEL):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IP_ADDR):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PROTOCOL_TYPE):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IP_TOS_TC):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IPV6_FLOW_LABEL):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IPSEC_SPI):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT);
+ break;
+ case (e_FM_PCD_KG_L4_PORT):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
+ break;
+ case (e_FM_PCD_KG_TCP_FLAG):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT);
+ break;
+ case (e_FM_PCD_KG_GENERIC_FROM_DATA):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ }
+ p_SchemeRegs->kgse_ekdv = tmpReg;
+
+ p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts));
+ if (!p_LocalExtractsArray)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+
+ /* configure kgse_ekfc and kgse_gec */
+ knownTmp = 0;
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedExtracts ; i++)
+ {
+ p_Extract = &p_KeyAndHash->extractArray[i];
+ switch (p_Extract->type)
+ {
+ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
+ knownTmp |= KG_SCH_KN_PORT_ID;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID);
+ p_LocalExtractsArray->extractsArray[i].known = TRUE;
+ break;
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ switch (p_Extract->extractByHdr.hdr)
+ {
+
+#ifdef FM_CAPWAP_SUPPORT
+ case (HEADER_TYPE_UDP_LITE):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+#endif
+ case (HEADER_TYPE_UDP_ENCAP_ESP):
+ switch (p_Extract->extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ /* case where extraction from ESP only */
+ if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE)
+ {
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ }
+ else
+ {
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ p_Extract->extractByHdr.ignoreProtocolValidation = FALSE;
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp)
+ {
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp)
+ {
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE;
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE;
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ switch (p_Extract->extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ generic = TRUE;
+ /* get the header code for the generic extract */
+ code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation);
+ /* set generic register fields */
+ offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset;
+ size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size;
+ break;
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ generic = TRUE;
+ /* get the field code for the generic extract */
+ code = GetGenFieldCode(p_Extract->extractByHdr.hdr,
+ p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex);
+ offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset;
+ size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ break;
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ if (!p_Extract->extractByHdr.ignoreProtocolValidation)
+ {
+ /* if we have a known field for it - use it, otherwise use generic */
+ bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex,
+ p_Extract->extractByHdr.extractByHdrType.fullField);
+ if (bitMask)
+ {
+ knownTmp |= bitMask;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask);
+ p_LocalExtractsArray->extractsArray[i].known = TRUE;
+ }
+ else
+ generic = TRUE;
+
+ }
+ else
+ generic = TRUE;
+ if (generic)
+ {
+ /* tmp - till we cover more headers under generic */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* use generic */
+ generic = TRUE;
+ offset = 0;
+ /* get the field code for the generic extract */
+ code = GetGenCode(p_Extract->extractNonHdr.src, &offset);
+ offset += p_Extract->extractNonHdr.offset;
+ size = p_Extract->extractNonHdr.size;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ if (generic)
+ {
+ /* set generic register fields */
+ if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS)
+ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
+ if (!code)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+
+ genTmp = KG_SCH_GEN_VALID;
+ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
+ genTmp |= offset;
+ if ((size > MAX_KG_SCH_SIZE) || (size < 1))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)"));
+ genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT);
+ swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code);
+ if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL)
+ DBG(WARNING, ("No sw default configured"));
+
+ genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT;
+ genTmp |= KG_SCH_GEN_MASK;
+ p_SchemeRegs->kgse_gec[currGenId] = genTmp;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = currGenId++;
+ p_LocalExtractsArray->extractsArray[i].known = FALSE;
+ generic = FALSE;
+ }
+ }
+ p_SchemeRegs->kgse_ekfc = knownTmp;
+
+ selectTmp = 0;
+ maskTmp = 0xFFFFFFFF;
+ /* configure kgse_bmch, kgse_bmcl and kgse_fqb */
+
+ if (p_KeyAndHash->numOfUsedMasks >= FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS));
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedMasks ; i++)
+ {
+ /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */
+ id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id;
+ /* Get the shift of the select field (depending on i) */
+ GET_MASK_SEL_SHIFT(shift,i);
+ if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known)
+ selectTmp |= id << shift;
+ else
+ selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift;
+
+ /* Get the shift of the offset field (depending on i) - may
+ be in kgse_bmch or in kgse_fqb (depending on i) */
+ GET_MASK_OFFSET_SHIFT(shift,i);
+ if (i<=1)
+ selectTmp |= p_KeyAndHash->masks[i].offset << shift;
+ else
+ fqbTmp |= p_KeyAndHash->masks[i].offset << shift;
+
+ /* Get the shift of the mask field (depending on i) */
+ GET_MASK_SHIFT(shift,i);
+ /* pass all bits */
+ maskTmp |= KG_SCH_BITMASK_MASK << shift;
+ /* clear bits that need masking */
+ maskTmp &= ~(0xFF << shift) ;
+ /* set mask bits */
+ maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ;
+ }
+ p_SchemeRegs->kgse_bmch = selectTmp;
+ p_SchemeRegs->kgse_bmcl = maskTmp;
+ /* kgse_fqb will be written t the end of the routine */
+
+ /* configure kgse_hc */
+ if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT));
+ if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT));
+
+ tmpReg = 0;
+
+ tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift);
+ tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
+
+ if (p_KeyAndHash->symmetricHash)
+ {
+ if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing"));
+ tmpReg |= KG_SCH_HASH_CONFIG_SYM;
+ }
+ p_SchemeRegs->kgse_hc = tmpReg;
+
+ /* build the return array describing the order of the extractions */
+
+ /* the last currGenId places of the array
+ are for generic extracts that are always last.
+ We now sort for the calculation of the order of the known
+ extractions we sort the known extracts between orderedArray[0] and
+ orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1].
+ for the calculation of the order of the generic extractions we use:
+ num_of_generic - currGenId
+ num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId
+ first_generic_index = num_of_known */
+ curr = 0;
+ for (i=0;i<p_KeyAndHash->numOfUsedExtracts ; i++)
+ {
+ if (p_LocalExtractsArray->extractsArray[i].known)
+ {
+ ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId));
+ j = curr;
+ /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original
+ index in the user's extractions array */
+ /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1]
+ location */
+ while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id <
+ p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id))
+ {
+ p_Scheme->orderedArray[j] =
+ p_Scheme->orderedArray[j-1];
+ j--;
+ }
+ p_Scheme->orderedArray[j] = (uint8_t)i;
+ curr++;
+ }
+ else
+ {
+ /* index is first_generic_index + generic index (id) */
+ idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id);
+ ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY);
+ p_Scheme->orderedArray[idx]= (uint8_t)i;
+ }
+ }
+ XX_Free(p_LocalExtractsArray);
+ p_LocalExtractsArray = NULL;
+
+ }
+ else
+ {
+ /* clear all unused registers: */
+ p_SchemeRegs->kgse_ekfc = 0;
+ p_SchemeRegs->kgse_ekdv = 0;
+ p_SchemeRegs->kgse_bmch = 0;
+ p_SchemeRegs->kgse_bmcl = 0;
+ p_SchemeRegs->kgse_hc = 0;
+ p_SchemeRegs->kgse_dv0 = 0;
+ p_SchemeRegs->kgse_dv1 = 0;
+ }
+
+ if (p_SchemeParams->bypassFqidGeneration)
+ p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID;
+
+ /* configure kgse_spc */
+ if ( p_SchemeParams->schemeCounter.update)
+ p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value;
+
+
+ /* check that are enough generic registers */
+ if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS)
+ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
+
+ /* extracted OR mask on Qid */
+ for ( i=0 ;i<p_SchemeParams->numOfUsedExtractedOrs ; i++)
+ {
+
+ p_Scheme->extractedOrs = TRUE;
+ /* configure kgse_gec[i] */
+ p_ExtractOr = &p_SchemeParams->extractedOrs[i];
+ switch (p_ExtractOr->type)
+ {
+ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
+ code = KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ offset = 0;
+ break;
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ /* get the header code for the generic extract */
+ code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation);
+ /* set generic register fields */
+ offset = p_ExtractOr->extractionOffset;
+ break;
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* get the field code for the generic extract */
+ offset = 0;
+ code = GetGenCode(p_ExtractOr->src, &offset);
+ offset += p_ExtractOr->extractionOffset;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ /* set generic register fields */
+ if (!code)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+ genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID;
+ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
+ genTmp |= offset;
+ if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile"));
+
+ /************************************************************************************
+ bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter
+ in the following way:
+
+ Driver API and implementation:
+ ==============================
+ FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID.
+ if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that
+ are not overlapping FQID.
+ ------------------------
+ | FQID (24) |
+ ------------------------
+ --------
+ | | extracted OR byte
+ --------
+
+ Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the
+ PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that
+ are not overlapping PP id.
+
+ --------
+ | PP (8) |
+ --------
+ --------
+ | | extracted OR byte
+ --------
+
+ HW implementation
+ =================
+ FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located
+ as the highest byte of that word and may be rotated to effect any part os the FQID or
+ the PP.
+ ------------------------ --------
+ | FQID (24) || PP (8) |
+ ------------------------ --------
+ --------
+ | | extracted OR byte
+ --------
+
+ ************************************************************************************/
+
+ if (p_ExtractOr->bitOffsetInFqid)
+ {
+ if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET )
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)"));
+ if (p_ExtractOr->bitOffsetInFqid<8)
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT);
+ else
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT);
+ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE);
+ }
+ else /* effect policer profile */
+ {
+ if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET )
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)"));
+ p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile;
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT);
+ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE);
+ }
+
+ genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT);
+ /* clear bits that need masking */
+ genTmp &= ~KG_SCH_GEN_MASK ;
+ /* set mask bits */
+ genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT);
+ p_SchemeRegs->kgse_gec[currGenId++] = genTmp;
+
+ }
+ /* clear all unused GEC registers */
+ for ( i=currGenId ;i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ p_SchemeRegs->kgse_gec[i] = 0;
+
+ /* add base Qid for this scheme */
+ /* add configuration for kgse_fqb */
+ if (p_SchemeParams->baseFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1"));
+
+ fqbTmp |= p_SchemeParams->baseFqid;
+ p_SchemeRegs->kgse_fqb = fqbTmp;
+
+ p_Scheme->nextEngine = p_SchemeParams->nextEngine;
+ p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
+ t_FmPcdIpcKgClsPlanParams kgAlloc;
+ t_Error err = E_OK;
+ uint32_t oredVectors = 0;
+ int i, j;
+
+ /* this routine is protected by the calling routine ! */
+ if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected."));
+
+ /* find a new clsPlan group */
+ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
+ if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used)
+ break;
+ if (i == FM_MAX_NUM_OF_PORTS)
+ RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available."));
+
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE;
+
+ p_Grp->clsPlanGrpId = (uint8_t)i;
+
+ if (p_Grp->numOfOptions == 0)
+ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i;
+
+ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i];
+ p_ClsPlanGrp->netEnvId = p_Grp->netEnvId;
+ p_ClsPlanGrp->owners = 0;
+ FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId);
+ if (p_Grp->numOfOptions != 0)
+ FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId);
+
+ p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions);
+ /* a minimal group of 8 is required */
+ if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP)
+ p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP;
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry);
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ }
+ else
+ {
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ memset(&kgAlloc, 0, sizeof(kgAlloc));
+ kgAlloc.guestId = p_FmPcd->guestId;
+ kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
+ msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry));
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ if ((t_Error)reply.error != E_OK)
+ RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG);
+
+ p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody);
+ }
+
+ /* build classification plan entries parameters */
+ p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry;
+ p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
+
+ oredVectors = 0;
+ for (i = 0; i<p_Grp->numOfOptions; i++)
+ {
+ oredVectors |= p_Grp->optVectors[i];
+ /* save an array of used options - the indexes represent the power of 2 index */
+ p_ClsPlanGrp->optArray[i] = p_Grp->options[i];
+ }
+ /* set the classification plan relevant entries so that all bits
+ * relevant to the list of options is cleared
+ */
+ for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
+ p_ClsPlanSet->vectors[j] = ~oredVectors;
+
+ for (i = 0; i<p_Grp->numOfOptions; i++)
+ {
+ /* option i got the place 2^i in the clsPlan array. all entries that
+ * have bit i set, should have the vector bit cleared. So each option
+ * has one location that it is exclusive (1,2,4,8...) and represent the
+ * presence of that option only, and other locations that represent a
+ * combination of options.
+ * e.g:
+ * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2
+ * now represents a frame with ethernet-BC header - so the bit
+ * representing ethernet-BC should be set and all other option bits
+ * should be cleared.
+ * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit
+ * vector[1] set, but they also have other bits set:
+ * 3=1+2, options 0 and 1
+ * 6=2+4, options 1 and 2
+ * 7=1+2+4, options 0,1,and 2
+ * 10=2+8, options 1 and 3
+ * etc.
+ * */
+
+ /* now for each option (i), we set their bits in all entries (j)
+ * that contain bit 2^i.
+ */
+ for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
+ {
+ if (j & (1<<i))
+ p_ClsPlanSet->vectors[j] |= p_Grp->optVectors[i];
+ }
+ }
+
+ return E_OK;
+}
+
+void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdIpcKgClsPlanParams kgAlloc;
+ t_Error err;
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ /* check that no port is bound to this clsPlan */
+ if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to"));
+ return;
+ }
+
+ FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN);
+
+ if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
+ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
+ else
+ FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId);
+
+ /* free blocks */
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ KgFreeClsPlanEntries(h_FmPcd,
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry);
+ else /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
+ {
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ kgAlloc.guestId = p_FmPcd->guestId;
+ kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp;
+ kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry;
+ msg.msgId = FM_PCD_FREE_KG_CLSPLAN;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != sizeof(uint32_t))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return;
+ }
+ if ((t_Error)reply.error != E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed"));
+ return;
+ }
+ }
+
+ /* clear clsPlan driver structure */
+ memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp));
+}
+
+t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t j, schemesPerPortVector = 0;
+ t_FmPcdKgScheme *p_Scheme;
+ uint8_t i, relativeSchemeId;
+ uint32_t tmp, walking1Mask;
+ uint8_t swPortIndex = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ /* for each scheme */
+ for (i = 0; i<p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (add)
+ {
+ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
+ if (!FmPcdKgIsSchemeValidSw(p_Scheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
+ /* check netEnvId of the port against the scheme netEnvId */
+ if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId"));
+
+ /* if next engine is private port policer profile, we need to check that it is valid */
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId);
+ if (p_Scheme->nextRelativePlcrProfile)
+ {
+ for (j = 0;j<p_Scheme->numOfProfiles;j++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort);
+ if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j)))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid."));
+ }
+ }
+ if (!p_BindPort->useClsPlan)
+ {
+ /* This check may be redundant as port is a assigned to the whole NetEnv */
+
+ /* if this port does not use clsPlan, it may not be bound to schemes with units that contain
+ cls plan options. Schemes that are used only directly, should not be checked.
+ it also may not be bound to schemes that go to CC with units that are options - so we OR
+ the match vector and the grpBits (= ccUnits) */
+ if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits)
+ {
+ walking1Mask = 0x80000000;
+ tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector;
+ tmp |= p_Scheme->ccUnits;
+ while (tmp)
+ {
+ if (tmp & walking1Mask)
+ {
+ tmp &= ~walking1Mask;
+ if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, p_Scheme->netEnvId, walking1Mask))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options"));
+ }
+ walking1Mask >>= 1;
+ }
+ }
+ }
+ }
+ /* build vector */
+ schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]);
+ }
+
+ *p_SpReg = schemesPerPortVector;
+
+ return E_OK;
+}
+
+t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t spReg;
+ t_Error err = E_OK;
+
+ err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ IncSchemeOwners(p_FmPcd, p_SchemeBind);
+
+ return E_OK;
+}
+
+t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t spReg;
+ t_Error err = E_OK;
+
+ err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ DecSchemeOwners(p_FmPcd, p_SchemeBind);
+
+ return E_OK;
+}
+
+bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme)
+{
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
+
+ return p_Scheme->valid;
+}
+
+bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t i, j;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++)
+ {
+ if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated)
+ {
+ p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE;
+ p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId;
+ p_SchemesIds[j] = i;
+ j++;
+ }
+ }
+
+ if (j != numOfSchemes)
+ {
+ /* roll back */
+ for (j--; j; j--)
+ {
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0;
+ p_SchemesIds[j] = 0;
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found"));
+ }
+
+ return E_OK;
+}
+
+t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC */
+
+ for (i = 0; i < numOfSchemes; i++)
+ {
+ if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated"));
+ }
+ if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. "));
+ }
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0;
+ }
+
+ return E_OK;
+}
+
+t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t numOfBlocks, blocksFound=0, first=0;
+ uint8_t i, j;
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ if (!numOfClsPlanEntries)
+ return E_OK;
+
+ if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8"));
+
+ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
+
+ /* try to find consequent blocks */
+ first = 0;
+ for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;)
+ {
+ if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated)
+ {
+ blocksFound++;
+ i++;
+ if (blocksFound == numOfBlocks)
+ break;
+ }
+ else
+ {
+ blocksFound = 0;
+ /* advance i to the next aligned address */
+ first = i = (uint8_t)(first + numOfBlocks);
+ }
+ }
+
+ if (blocksFound == numOfBlocks)
+ {
+ *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP);
+ for (j = first; j < (first + numOfBlocks); j++)
+ {
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE;
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId;
+ }
+ return E_OK;
+ }
+ else
+ RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan"));
+}
+
+void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t numOfBlocks;
+ uint8_t i, baseBlock;
+
+#ifdef DISABLE_ASSERTIONS
+UNUSED(guestId);
+#endif /* DISABLE_ASSERTIONS */
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
+ ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP));
+
+ baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP);
+ for (i=baseBlock;i<baseBlock+numOfBlocks;i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated);
+ ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId);
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0;
+ }
+}
+
+void KgEnable(t_FmPcd *p_FmPcd)
+{
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ fman_kg_enable(p_Regs);
+}
+
+void KgDisable(t_FmPcd *p_FmPcd)
+{
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ fman_kg_disable(p_Regs);
+}
+
+void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ struct fman_kg_cp_regs *p_FmPcdKgPortRegs;
+ uint32_t tmpKgarReg = 0, intFlags;
+ uint16_t i, j;
+
+ /* This routine is protected by the calling routine ! */
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs;
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ for (i=p_Set->baseEntry;i<p_Set->baseEntry+p_Set->numOfClsPlanEntries;i+=8)
+ {
+ tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
+
+ for (j = i; j < i+8; j++)
+ {
+ ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1));
+ WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]);
+ }
+
+ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED"));
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ return;
+ }
+ }
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+}
+
+t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdKg *p_FmPcdKg;
+
+ UNUSED(p_FmPcd);
+
+ if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES));
+ return NULL;
+ }
+
+ p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg));
+ if (!p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg));
+
+
+ if (FmIsMaster(p_FmPcd->h_Fm))
+ {
+ p_FmPcdKg->p_FmPcdKgRegs = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm));
+ p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions;
+ p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0];
+ }
+
+ p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes;
+ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes)
+ {
+ p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
+ DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES"));
+ }
+
+ p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ return p_FmPcdKg;
+}
+
+t_Error KgInit(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+
+ p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock"));
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ err = KgInitMaster(p_FmPcd);
+ else
+ err = KgInitGuest(p_FmPcd);
+
+ if (err != E_OK)
+ {
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+ }
+
+ return err;
+}
+
+t_Error KgFree(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdIpcKgSchemesParams kgAlloc;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR);
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ err = FmPcdKgFreeSchemes(p_FmPcd,
+ p_FmPcd->p_FmPcdKg->numOfSchemes,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->schemesIds);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+
+ return E_OK;
+ }
+
+ /* guest */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
+ kgAlloc.guestId = p_FmPcd->guestId;
+ ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES);
+ memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes);
+ msg.msgId = FM_PCD_FREE_KG_SCHEMES;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+
+ return (t_Error)reply.error;
+}
+
+t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdKgInterModuleClsPlanGrpParams grpParams, *p_GrpParams;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+ t_Error err;
+
+ /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules,
+ so no need for lock here */
+
+ memset(&grpParams, 0, sizeof(grpParams));
+ grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN;
+ p_GrpParams = &grpParams;
+
+ p_GrpParams->netEnvId = netEnvId;
+
+ /* Get from the NetEnv the information of the clsPlan (can be already created,
+ * or needs to build) */
+ err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams);
+ if (err)
+ RETURN_ERROR(MINOR,err,NO_MSG);
+
+ if (p_GrpParams->grpExists)
+ {
+ /* this group was already updated (at least) in SW */
+ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
+ }
+ else
+ {
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */
+ err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet);
+ if (err)
+ {
+ XX_Free(p_ClsPlanSet);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
+
+ if (p_FmPcd->h_Hc)
+ {
+ /* write clsPlan entries to memory */
+ err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet);
+ if (err)
+ {
+ XX_Free(p_ClsPlanSet);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ else
+ /* write clsPlan entries to memory */
+ KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
+
+ XX_Free(p_ClsPlanSet);
+ }
+
+ /* Set caller parameters */
+
+ /* mark if this is an empty classification group */
+ if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
+ *p_IsEmptyClsPlanGrp = TRUE;
+ else
+ *p_IsEmptyClsPlanGrp = FALSE;
+
+ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId];
+
+ /* increment owners number */
+ p_ClsPlanGrp->owners++;
+
+ /* copy options array for port */
+ memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t));
+
+ /* bind port to the new or existing group */
+ err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId];
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+ t_Error err;
+
+ /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules,
+ so no need for lock here */
+
+ UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId);
+
+ /* decrement owners number */
+ ASSERT_COND(p_ClsPlanGrp->owners);
+ p_ClsPlanGrp->owners--;
+
+ if (!p_ClsPlanGrp->owners)
+ {
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId);
+ return err;
+ }
+ else
+ {
+ /* clear clsPlan entries in memory */
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ {
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+ }
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+
+ p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry;
+ p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp;
+ KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
+ XX_Free(p_ClsPlanSet);
+
+ FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId);
+ }
+ }
+ return E_OK;
+}
+
+uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction;
+}
+
+uint32_t FmPcdKgGetPointedOwners(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].pointedOwners;
+}
+
+bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr;
+}
+
+
+uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId;
+}
+
+bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs &&
+ p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) ||
+ p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile)
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine;
+}
+
+e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction;
+}
+
+void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction)
+{
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_Scheme->valid);
+
+ p_Scheme->requiredAction |= requiredAction;
+}
+
+bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg)
+{
+ return (bool)!!(schemeModeReg & KG_SCH_MODE_EN);
+}
+
+uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter)
+{
+ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ DUMMY_PORT_ID |
+ (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0));
+}
+
+uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId)
+{
+ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ DUMMY_PORT_ID |
+ FM_KG_KGAR_SCM_WSEL_UPDATE_CNT);
+
+}
+
+uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId)
+{
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ DUMMY_PORT_ID |
+ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_PCD_KG_KGAR_WSEL_MASK);
+
+ /* if we ever want to write 1 by 1, use:
+ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
+ */
+}
+
+uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
+}
+
+uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry;
+}
+
+uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp;
+}
+
+
+uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme)
+{
+ return ((t_FmPcdKgScheme*)h_Scheme)->schemeId;
+
+}
+
+#if (DPAA_VERSION >= 11)
+bool FmPcdKgGetVspe(t_Handle h_Scheme)
+{
+ return ((t_FmPcdKgScheme*)h_Scheme)->vspe;
+
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t i;
+
+ for (i = 0;i<p_FmPcd->p_FmPcdKg->numOfSchemes;i++)
+ if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId)
+ return i;
+
+ if (i == p_FmPcd->p_FmPcdKg->numOfSchemes)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range"));
+
+ return FM_PCD_KG_NUM_OF_SCHEMES;
+}
+
+t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ uint32_t tmpKgarReg, tmpReg32 = 0, intFlags;
+ t_Error err;
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
+
+ /* Calling function locked all PCD modules, so no need to lock here */
+
+ if (!FmPcdKgIsSchemeValidSw(h_Scheme))
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value);
+
+ UpateSchemePointedOwner(h_Scheme,TRUE);
+ FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction);
+ return err;
+ }
+
+ physicalSchemeId = p_Scheme->schemeId;
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].pointedOwners ||
+ !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine)
+ {
+ case (e_FM_PCD_DONE):
+ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ break;
+ case (e_FM_PCD_PLCR):
+ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr ||
+ (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs &&
+ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) ||
+ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile)
+ {
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
+ }
+ err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction);
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME"));
+ }
+ }
+ if (requiredAction & UPDATE_KG_NIA_CC_WA)
+ {
+ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ tmpReg32 &= ~NIA_FM_CTL_AC_CC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ }
+ if (requiredAction & UPDATE_KG_OPT_MODE)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ if (requiredAction & UPDATE_KG_NIA)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
+ tmpReg32 |= value;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ }
+
+ UpateSchemePointedOwner(h_Scheme, TRUE);
+ FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction);
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API routines */
+/****************************************/
+
+t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, t_FmPcdKgSchemeParams *p_SchemeParams)
+{
+ t_FmPcd *p_FmPcd;
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_scheme_regs *p_MemRegs;
+ uint8_t i;
+ t_Error err = E_OK;
+ uint32_t tmpKgarReg;
+ uint32_t intFlags;
+ uint8_t physicalSchemeId, relativeSchemeId = 0;
+ t_FmPcdKgScheme *p_Scheme;
+
+ if (p_SchemeParams->modify)
+ {
+ p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme;
+ p_FmPcd = p_Scheme->h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
+
+ if (!FmPcdKgIsSchemeValidSw(p_Scheme))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
+ ("Scheme is invalid"));
+ return NULL;
+ }
+
+ if (!KgSchemeFlagTryLock(p_Scheme))
+ {
+ DBG(TRACE, ("Scheme Try Lock - BUSY"));
+ /* Signal to caller BUSY condition */
+ p_SchemeParams->id.h_Scheme = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
+
+ relativeSchemeId = p_SchemeParams->id.relativeSchemeId;
+ /* check that schemeId is in range */
+ if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
+ return NULL;
+ }
+
+ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
+ if (FmPcdKgIsSchemeValidSw(p_Scheme))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
+ ("Scheme id (%d)!", relativeSchemeId));
+ return NULL;
+ }
+
+ p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId];
+ p_Scheme->h_FmPcd = p_FmPcd;
+
+ p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_Scheme->p_Lock)
+ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!"));
+ }
+
+ err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ if (p_SchemeParams->modify)
+ KgSchemeFlagUnlock(p_Scheme);
+ if (!p_SchemeParams->modify &&
+ p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc,
+ (t_Handle)p_Scheme,
+ &schemeRegs,
+ p_SchemeParams->schemeCounter.update);
+ if (p_SchemeParams->modify)
+ KgSchemeFlagUnlock(p_Scheme);
+ if (err)
+ {
+ if (!p_SchemeParams->modify &&
+ p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return NULL;
+ }
+ if (!p_SchemeParams->modify)
+ ValidateSchemeSw(p_Scheme);
+ return (t_Handle)p_Scheme;
+ }
+
+ physicalSchemeId = p_Scheme->schemeId;
+
+ /* configure all 21 scheme registers */
+ p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs;
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WRITE_UINT32(p_MemRegs->kgse_ppc, schemeRegs.kgse_ppc);
+ WRITE_UINT32(p_MemRegs->kgse_ccbs, schemeRegs.kgse_ccbs);
+ WRITE_UINT32(p_MemRegs->kgse_mode, schemeRegs.kgse_mode);
+ WRITE_UINT32(p_MemRegs->kgse_mv, schemeRegs.kgse_mv);
+ WRITE_UINT32(p_MemRegs->kgse_dv0, schemeRegs.kgse_dv0);
+ WRITE_UINT32(p_MemRegs->kgse_dv1, schemeRegs.kgse_dv1);
+ WRITE_UINT32(p_MemRegs->kgse_ekdv, schemeRegs.kgse_ekdv);
+ WRITE_UINT32(p_MemRegs->kgse_ekfc, schemeRegs.kgse_ekfc);
+ WRITE_UINT32(p_MemRegs->kgse_bmch, schemeRegs.kgse_bmch);
+ WRITE_UINT32(p_MemRegs->kgse_bmcl, schemeRegs.kgse_bmcl);
+ WRITE_UINT32(p_MemRegs->kgse_hc, schemeRegs.kgse_hc);
+ WRITE_UINT32(p_MemRegs->kgse_spc, schemeRegs.kgse_spc);
+ WRITE_UINT32(p_MemRegs->kgse_fqb, schemeRegs.kgse_fqb);
+ WRITE_UINT32(p_MemRegs->kgse_om, schemeRegs.kgse_om);
+ WRITE_UINT32(p_MemRegs->kgse_vsp, schemeRegs.kgse_vsp);
+ for (i=0 ; i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ WRITE_UINT32(p_MemRegs->kgse_gec[i], schemeRegs.kgse_gec[i]);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ if (!p_SchemeParams->modify)
+ ValidateSchemeSw(p_Scheme);
+ else
+ KgSchemeFlagUnlock(p_Scheme);
+
+ return (t_Handle)p_Scheme;
+}
+
+t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme)
+{
+ t_FmPcd *p_FmPcd;
+ uint8_t physicalSchemeId;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err = E_OK;
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
+
+ SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE);
+
+ p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd);
+
+ /* check that no port is bound to this scheme */
+ err = InvalidateSchemeSw(h_Scheme);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme);
+ if (p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return err;
+ }
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ /* clear mode register, including enable bit */
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ if (p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+
+ return E_OK;
+}
+
+uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme)
+{
+ t_FmPcd *p_FmPcd;
+ uint32_t tmpKgarReg, spc, intFlags;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
+
+ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme);
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+
+ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+ spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return spc;
+}
+
+t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value)
+{
+ t_FmPcd *p_FmPcd;
+ uint32_t tmpKgarReg, intFlags;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
+
+ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
+
+ if (!FmPcdKgIsSchemeValidSw(h_Scheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value);
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+ /* check that schemeId is in range */
+ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ /* read specified scheme into scheme registers */
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
+ {
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+ }
+
+ /* change counter value */
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_kg_regs *p_Regs;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
+
+ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!"));
+
+ WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_kg_regs *p_Regs;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
+
+ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!"));
+
+ if (valueId == 0)
+ WRITE_UINT32(p_Regs->fmkg_gdv0r,value);
+ else
+ WRITE_UINT32(p_Regs->fmkg_gdv1r,value);
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i = 0, j = 0;
+ uint8_t hardwarePortId = 0;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err = E_OK;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, ("FmPcdKgRegs Regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eeer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seeer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gsr);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_tpc);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_serc);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_fdor);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv0r);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv1r);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_feer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_ar);
+
+ DUMP_SUBTITLE(("\n"));
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ for (j = 0;j<FM_PCD_KG_NUM_OF_SCHEMES;j++)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg((uint8_t)j);
+ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs, ("FmPcdKgIndirectAccessSchemeRegs Scheme %d Regs", j));
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mode);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekfc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekdv);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmch);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmcl);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_fqb);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_hc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ppc);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec, ("kgse_gec"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_KG_NUM_OF_GENERIC_REGS)
+ {
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec[i], sizeof(uint32_t));
+ }
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_spc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv0);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv1);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ccbs);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mv);
+ }
+ DUMP_SUBTITLE(("\n"));
+
+ for (i=0;i<FM_MAX_NUM_OF_PORTS;i++)
+ {
+ SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, i);
+
+ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, ("FmPcdKgIndirectAccessPortRegs PCD Port %d regs", hardwarePortId));
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_sp);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_cpp);
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ for (j=0;j<FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;j++)
+ {
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs, ("FmPcdKgIndirectAccessClsPlanRegs Regs group %d", j));
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe, ("kgcpe"));
+
+ tmpKgarReg = ReadClsPlanBlockActionReg((uint8_t)j);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe[i], sizeof(uint32_t));
+ }
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h
new file mode 100644
index 0000000..cb7521a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_kg.h
+
+ @Description FM KG private header
+*//***************************************************************************/
+#ifndef __FM_KG_H
+#define __FM_KG_H
+
+#include "std_ext.h"
+
+/***********************************************************************/
+/* Keygen defines */
+/***********************************************************************/
+/* maskes */
+#if (DPAA_VERSION >= 11)
+#define KG_SCH_VSP_SHIFT_MASK 0x0003f000
+#define KG_SCH_OM_VSPE 0x00000001
+#define KG_SCH_VSP_NO_KSP_EN 0x80000000
+
+#define MAX_SP_SHIFT 23
+#define KG_SCH_VSP_MASK_SHIFT 12
+#define KG_SCH_VSP_SHIFT 24
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef uint32_t t_KnownFieldsMasks;
+#define KG_SCH_KN_PORT_ID 0x80000000
+#define KG_SCH_KN_MACDST 0x40000000
+#define KG_SCH_KN_MACSRC 0x20000000
+#define KG_SCH_KN_TCI1 0x10000000
+#define KG_SCH_KN_TCI2 0x08000000
+#define KG_SCH_KN_ETYPE 0x04000000
+#define KG_SCH_KN_PPPSID 0x02000000
+#define KG_SCH_KN_PPPID 0x01000000
+#define KG_SCH_KN_MPLS1 0x00800000
+#define KG_SCH_KN_MPLS2 0x00400000
+#define KG_SCH_KN_MPLS_LAST 0x00200000
+#define KG_SCH_KN_IPSRC1 0x00100000
+#define KG_SCH_KN_IPDST1 0x00080000
+#define KG_SCH_KN_PTYPE1 0x00040000
+#define KG_SCH_KN_IPTOS_TC1 0x00020000
+#define KG_SCH_KN_IPV6FL1 0x00010000
+#define KG_SCH_KN_IPSRC2 0x00008000
+#define KG_SCH_KN_IPDST2 0x00004000
+#define KG_SCH_KN_PTYPE2 0x00002000
+#define KG_SCH_KN_IPTOS_TC2 0x00001000
+#define KG_SCH_KN_IPV6FL2 0x00000800
+#define KG_SCH_KN_GREPTYPE 0x00000400
+#define KG_SCH_KN_IPSEC_SPI 0x00000200
+#define KG_SCH_KN_IPSEC_NH 0x00000100
+#define KG_SCH_KN_IPPID 0x00000080
+#define KG_SCH_KN_L4PSRC 0x00000004
+#define KG_SCH_KN_L4PDST 0x00000002
+#define KG_SCH_KN_TFLG 0x00000001
+
+typedef uint8_t t_GenericCodes;
+#define KG_SCH_GEN_SHIM1 0x70
+#define KG_SCH_GEN_DEFAULT 0x10
+#define KG_SCH_GEN_PARSE_RESULT_N_FQID 0x20
+#define KG_SCH_GEN_START_OF_FRM 0x40
+#define KG_SCH_GEN_SHIM2 0x71
+#define KG_SCH_GEN_IP_PID_NO_V 0x72
+#define KG_SCH_GEN_ETH 0x03
+#define KG_SCH_GEN_ETH_NO_V 0x73
+#define KG_SCH_GEN_SNAP 0x04
+#define KG_SCH_GEN_SNAP_NO_V 0x74
+#define KG_SCH_GEN_VLAN1 0x05
+#define KG_SCH_GEN_VLAN1_NO_V 0x75
+#define KG_SCH_GEN_VLAN2 0x06
+#define KG_SCH_GEN_VLAN2_NO_V 0x76
+#define KG_SCH_GEN_ETH_TYPE 0x07
+#define KG_SCH_GEN_ETH_TYPE_NO_V 0x77
+#define KG_SCH_GEN_PPP 0x08
+#define KG_SCH_GEN_PPP_NO_V 0x78
+#define KG_SCH_GEN_MPLS1 0x09
+#define KG_SCH_GEN_MPLS2 0x19
+#define KG_SCH_GEN_MPLS3 0x29
+#define KG_SCH_GEN_MPLS1_NO_V 0x79
+#define KG_SCH_GEN_MPLS_LAST 0x0a
+#define KG_SCH_GEN_MPLS_LAST_NO_V 0x7a
+#define KG_SCH_GEN_IPV4 0x0b
+#define KG_SCH_GEN_IPV6 0x1b
+#define KG_SCH_GEN_L3_NO_V 0x7b
+#define KG_SCH_GEN_IPV4_TUNNELED 0x0c
+#define KG_SCH_GEN_IPV6_TUNNELED 0x1c
+#define KG_SCH_GEN_MIN_ENCAP 0x2c
+#define KG_SCH_GEN_IP2_NO_V 0x7c
+#define KG_SCH_GEN_GRE 0x0d
+#define KG_SCH_GEN_GRE_NO_V 0x7d
+#define KG_SCH_GEN_TCP 0x0e
+#define KG_SCH_GEN_UDP 0x1e
+#define KG_SCH_GEN_IPSEC_AH 0x2e
+#define KG_SCH_GEN_SCTP 0x3e
+#define KG_SCH_GEN_DCCP 0x4e
+#define KG_SCH_GEN_IPSEC_ESP 0x6e
+#define KG_SCH_GEN_L4_NO_V 0x7e
+#define KG_SCH_GEN_NEXTHDR 0x7f
+/* shifts */
+#define KG_SCH_PP_SHIFT_HIGH_SHIFT 27
+#define KG_SCH_PP_SHIFT_LOW_SHIFT 12
+#define KG_SCH_PP_MASK_SHIFT 16
+#define KG_SCH_MODE_CCOBASE_SHIFT 24
+#define KG_SCH_DEF_MAC_ADDR_SHIFT 30
+#define KG_SCH_DEF_TCI_SHIFT 28
+#define KG_SCH_DEF_ENET_TYPE_SHIFT 26
+#define KG_SCH_DEF_PPP_SESSION_ID_SHIFT 24
+#define KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT 22
+#define KG_SCH_DEF_MPLS_LABEL_SHIFT 20
+#define KG_SCH_DEF_IP_ADDR_SHIFT 18
+#define KG_SCH_DEF_PROTOCOL_TYPE_SHIFT 16
+#define KG_SCH_DEF_IP_TOS_TC_SHIFT 14
+#define KG_SCH_DEF_IPV6_FLOW_LABEL_SHIFT 12
+#define KG_SCH_DEF_IPSEC_SPI_SHIFT 10
+#define KG_SCH_DEF_L4_PORT_SHIFT 8
+#define KG_SCH_DEF_TCP_FLAG_SHIFT 6
+#define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24
+#define KG_SCH_GEN_MASK_SHIFT 16
+#define KG_SCH_GEN_HT_SHIFT 8
+#define KG_SCH_GEN_SIZE_SHIFT 24
+#define KG_SCH_GEN_DEF_SHIFT 29
+#define FM_PCD_KG_KGAR_NUM_SHIFT 16
+
+/* others */
+#define NUM_OF_SW_DEFAULTS 3
+#define MAX_PP_SHIFT 23
+#define MAX_KG_SCH_SIZE 16
+#define MASK_FOR_GENERIC_BASE_ID 0x20
+#define MAX_HASH_SHIFT 40
+#define MAX_KG_SCH_FQID_BIT_OFFSET 31
+#define MAX_KG_SCH_PP_BIT_OFFSET 15
+#define MAX_DIST_FQID_SHIFT 23
+
+#define GET_MASK_SEL_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 26;break; \
+ case (1):shift = 20;break; \
+ case (2):shift = 10;break; \
+ case (3):shift = 4;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+#define GET_MASK_OFFSET_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 16;break; \
+ case (1):shift = 0;break; \
+ case (2):shift = 28;break; \
+ case (3):shift = 24;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+#define GET_MASK_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 24;break; \
+ case (1):shift = 16;break; \
+ case (2):shift = 8;break; \
+ case (3):shift = 0;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+/***********************************************************************/
+/* Keygen defines */
+/***********************************************************************/
+
+#define KG_DOUBLE_MEANING_REGS_OFFSET 0x100
+#define NO_VALIDATION 0x70
+#define KG_ACTION_REG_TO 1024
+#define KG_MAX_PROFILE 255
+#define SCHEME_ALWAYS_DIRECT 0xFFFFFFFF
+
+
+#endif /* __FM_KG_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c
new file mode 100644
index 0000000..e6c8d2d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c
@@ -0,0 +1,4193 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_manip.c
+
+ @Description FM PCD manip ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_port_ext.h"
+#include "fm_muram_ext.h"
+#include "memcpy_ext.h"
+
+#include "fm_common.h"
+#include "fm_hc.h"
+#include "fm_manip.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+static t_Handle GetManipInfo(t_FmPcdManip *p_Manip, e_ManipInfo manipInfo)
+{
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ p_CurManip = p_Manip;
+ else
+ {
+ /* go to first unified */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+
+ switch (manipInfo)
+ {
+ case (e_MANIP_HMCT):
+ return p_CurManip->p_Hmct;
+ case (e_MANIP_HMTD):
+ return p_CurManip->h_Ad;
+ case (e_MANIP_HANDLER_TABLE_OWNER):
+ return (t_Handle)p_CurManip;
+ default:
+ return NULL;
+ }
+}
+static uint16_t GetHmctSize(t_FmPcdManip *p_Manip)
+{
+ uint16_t size = 0;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ return p_Manip->tableSize;
+
+ /* accumulate sizes, starting with the first node */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ {
+ size += p_CurManip->tableSize;
+ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip;
+ }
+ size += p_CurManip->tableSize; /* add last size */
+
+ return(size);
+}
+static uint16_t GetDataSize(t_FmPcdManip *p_Manip)
+{
+ uint16_t size = 0;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ return p_Manip->dataSize;
+
+ /* accumulate sizes, starting with the first node */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ {
+ size += p_CurManip->dataSize;
+ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip;
+ }
+ size += p_CurManip->dataSize; /* add last size */
+
+ return(size);
+}
+static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, uint16_t *p_TableSize, uint8_t *p_DataSize)
+{
+ uint8_t localDataSize, remain, tableSize = 0, dataSize = 0;
+
+ if (p_FmPcdManipParams->u.hdr.rmv)
+ {
+ switch (p_FmPcdManipParams->u.hdr.rmvParams.type){
+ case (e_FM_PCD_MANIP_RMV_GENERIC):
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ /* As long as the only rmv command is the L2, no check on type is required */
+ tableSize += HMCD_BASIC_SIZE;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown rmvParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.insrt)
+ {
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.type){
+ case (e_FM_PCD_MANIP_INSRT_GENERIC):
+ remain = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size % 4);
+ if (remain)
+ localDataSize = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size + 4 - remain);
+ else
+ localDataSize = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size;
+ tableSize += (uint8_t)(HMCD_BASIC_SIZE + localDataSize);
+ break;
+ case (e_FM_PCD_MANIP_INSRT_BY_HDR):
+ /* As long as the only insert command is the internal L2, no check on type is required */
+ tableSize += HMCD_BASIC_SIZE+HMCD_PTR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2)
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS):
+ dataSize += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown insrtParams.type"));
+ }
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdate)
+ {
+ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ tableSize += HMCD_PTR_SIZE;
+ dataSize += DSCP_TO_VLAN_TABLE_SIZE;
+ }
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ {
+ tableSize += HMCD_PARAM_SIZE;
+ dataSize += 2;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ tableSize += HMCD_IPV4_ADDR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ tableSize += HMCD_IPV4_ADDR_SIZE;
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_SRC)
+ tableSize += HMCD_IPV6_ADDR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_DST)
+ tableSize += HMCD_IPV6_ADDR_SIZE;
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP):
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM)
+ /* we implement this case with the update-checksum descriptor */
+ tableSize += HMCD_BASIC_SIZE;
+ else
+ /* we implement this case with the TCP/UDP-update descriptor */
+ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.custom)
+ {
+ switch (p_FmPcdManipParams->u.hdr.customParams.type){
+ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE):
+ {
+ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE + HMCD_PARAM_SIZE;
+ dataSize += p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize;
+ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) &&
+ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id))
+ dataSize += 2;
+ }
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type"));
+ }
+ }
+
+ *p_TableSize = tableSize;
+ *p_DataSize = dataSize;
+
+ return E_OK;
+}
+
+static t_Error BuildHmct(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams, uint8_t *p_DestHmct, uint8_t *p_DestData, bool new)
+{
+ uint32_t *p_TmpHmct = (uint32_t*)p_DestHmct, *p_LocalData;
+ uint32_t tmpReg=0, *p_Last = NULL;
+ uint8_t remain, i, size=0, origSize, *p_UsrData = NULL, *p_TmpData = p_DestData;
+ t_Handle h_FmPcd = p_Manip->h_FmPcd;
+ uint8_t j=0;
+
+ if (p_FmPcdManipParams->u.hdr.rmv)
+ {
+ if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_GENERIC)
+ {
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_RMV) << HMCD_OC_SHIFT;
+ /* tmp, should be conditional */
+ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.offset << HMCD_RMV_OFFSET_SHIFT;
+ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.size << HMCD_RMV_SIZE_SHIFT;
+ }
+ else if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_BY_HDR)
+ {
+ uint8_t hmcdOpt;
+ if (!p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type == e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_L2_RMV) << HMCD_OC_SHIFT;
+
+ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET):
+ hmcdOpt = HMCD_RMV_L2_ETHERNET;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS):
+ hmcdOpt = HMCD_RMV_L2_STACKED_QTAGS;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS):
+ hmcdOpt = HMCD_RMV_L2_ETHERNET_AND_MPLS;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_MPLS):
+ hmcdOpt = HMCD_RMV_L2_MPLS;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header remove type!"));
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ /* advance to next command */
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.insrt)
+ {
+ if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_GENERIC)
+ {
+ /* initialize HMCD */
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.generic.replace)
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_REPLACE) << HMCD_OC_SHIFT;
+ else
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_INSRT) << HMCD_OC_SHIFT;
+
+ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.offset << HMCD_INSRT_OFFSET_SHIFT;
+ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size << HMCD_INSRT_SIZE_SHIFT;
+
+ size = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size;
+ p_UsrData = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.p_Data;
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ /* initialize data to be inserted */
+ /* if size is not a multiple of 4, padd with 0's */
+ origSize = size;
+ remain = (uint8_t)(size % 4);
+ if (remain)
+ {
+ size += (uint8_t)(4 - remain);
+ p_LocalData = (uint32_t *)XX_Malloc(size);
+ memset((uint8_t *)p_LocalData, 0, size);
+ memcpy((uint8_t *)p_LocalData, p_UsrData, origSize);
+ }
+ else
+ p_LocalData = (uint32_t*)p_UsrData;
+
+ /* initialize data and advance pointer to next command */
+ for (i = 0; i<size/4 ; i++, p_TmpHmct += HMCD_BASIC_SIZE/4)
+ WRITE_UINT32(*p_TmpHmct, *(p_LocalData+i));
+
+ if (remain)
+ XX_Free(p_LocalData);
+ }
+
+ else if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_BY_HDR)
+ {
+ uint8_t hmcdOpt;
+ if (!p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_L2_INSRT) << HMCD_OC_SHIFT;
+
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS):
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.update)
+ hmcdOpt = HMCD_INSRT_N_UPDATE_L2_MPLS;
+ else
+ hmcdOpt = HMCD_INSRT_L2_MPLS;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT;
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ /* set size and pointer of user's data */
+ size = (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size;
+
+ ASSERT_COND(p_TmpData);
+ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, size);
+ tmpReg = (size << HMCD_INSRT_L2_SIZE_SHIFT) | (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase));
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ p_TmpData += size;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header insert type!"));
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdate)
+ {
+ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_VLAN_PRI_UPDATE) << HMCD_OC_SHIFT;
+
+ /* set mode & table pointer */
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ /* set Mode */
+ tmpReg |= (uint32_t)(HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI) << HMCD_VLAN_PRI_REP_MODE_SHIFT;
+ /* set VPRI default */
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal;
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ /* write the table pointer into the Manip descriptor */
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ tmpReg = 0;
+ ASSERT_COND(p_TmpData);
+ for (i=0; i<FM_PCD_MANIP_DSCP_VALUES; i++)
+ {
+ /* first we build from each 8 values a 32bit register */
+ tmpReg |= (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i]) << (32-4*(j+1));
+ j++;
+ /* Than we write this register to the next table word
+ * (i=7-->word 0, i=15-->word 1,... i=63-->word 7) */
+ if ((i%8) == 7)
+ {
+ WRITE_UINT32(*((uint32_t*)p_TmpData + (i+1)/8-1), tmpReg);
+ tmpReg = 0;
+ j = 0;
+ }
+ }
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)));
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+
+ p_TmpData += DSCP_TO_VLAN_TABLE_SIZE;
+ }
+ else if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI)
+ {
+ /* set Mode */
+ /* line commented out as it has no-side-effect ('0' value). */
+ /*tmpReg |= HMCD_VLAN_PRI_UPDATE << HMCD_VLAN_PRI_REP_MODE_SHIFT*/;
+ /* set VPRI parameter */
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri;
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_IPV4_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TTL)
+ tmpReg |= HMCD_IPV4_UPDATE_TTL;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TOS)
+ {
+ tmpReg |= HMCD_IPV4_UPDATE_TOS;
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.tos << HMCD_IPV4_UPDATE_TOS_SHIFT;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ tmpReg |= HMCD_IPV4_UPDATE_ID;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ tmpReg |= HMCD_IPV4_UPDATE_SRC;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ tmpReg |= HMCD_IPV4_UPDATE_DST;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ {
+ ASSERT_COND(p_TmpData);
+ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.id);
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)));
+ p_TmpData += 2;
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ {
+ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.src);
+ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ {
+ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.dst);
+ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_IPV6_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_HL)
+ tmpReg |= HMCD_IPV6_UPDATE_HL;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_TC)
+ {
+ tmpReg |= HMCD_IPV6_UPDATE_TC;
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.trafficClass << HMCD_IPV6_UPDATE_TC_SHIFT;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC)
+ tmpReg |= HMCD_IPV6_UPDATE_SRC;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST)
+ tmpReg |= HMCD_IPV6_UPDATE_DST;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC)
+ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4)
+ {
+ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.src[i]);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST)
+ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4)
+ {
+ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.dst[i]);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP):
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM)
+ {
+ /* we implement this case with the update-checksum descriptor */
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_CHECKSUM) << HMCD_OC_SHIFT;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+ else
+ {
+ /* we implement this case with the TCP/UDP update descriptor */
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST)
+ tmpReg |= HMCD_TCP_UDP_UPDATE_DST;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC)
+ tmpReg |= HMCD_TCP_UDP_UPDATE_SRC;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ tmpReg = 0;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC)
+ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.src) << HMCD_TCP_UDP_UPDATE_SRC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST)
+ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.dst);
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ break;
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.custom)
+ {
+ switch (p_FmPcdManipParams->u.hdr.customParams.type)
+ {
+ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_REPLACE_IP) << HMCD_OC_SHIFT;
+
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.decTtlHl)
+ tmpReg |= HMCD_IP_REPLACE_TTL_HL;
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6)
+ /* line commented out as it has no-side-effect ('0' value). */
+ /*tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV4*/;
+ else if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4)
+ {
+ tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV6;
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)
+ tmpReg |= HMCD_IP_REPLACE_ID;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("One flag out of HDR_MANIP_IP_REPLACE_IPV4, HDR_MANIP_IP_REPLACE_IPV6 - must be set."));
+
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ size = p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize;
+ ASSERT_COND(p_TmpData);
+ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, size);
+ tmpReg = (uint32_t)(size << HMCD_IP_REPLACE_L3HDRSIZE_SHIFT);
+ tmpReg |= (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase));
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ p_TmpData += size;
+
+ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) &&
+ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id))
+ {
+ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.id);
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)));
+ p_TmpData += 2;
+ }
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type"));
+ }
+ }
+
+
+ /* If this node has a nextManip, and no parsing is required after it, the old table must be copied to the new table
+ the old table and should be freed */
+ if (p_FmPcdManipParams->h_NextManip &&
+ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)))
+ {
+ if (new)
+ {
+ /* If this is the first time this manip is created we need to free unused memory. If it
+ * is a dynamic changes case, the memory used is either the CC shadow or the existing
+ * table - no allocation, no free */
+ MANIP_UPDATE_UNIFIED_POSITION(p_FmPcdManipParams->h_NextManip);
+
+ p_Manip->unifiedPosition = e_MANIP_UNIFIED_FIRST;
+
+ /* The HMTD of the next Manip is never going to be used */
+ if (((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->muramAllocate)
+ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad);
+ else
+ XX_Free(((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad);
+ ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad = NULL;
+
+ /* advance pointer */
+ p_TmpHmct += MANIP_GET_HMCT_SIZE(p_FmPcdManipParams->h_NextManip)/4;
+ }
+ }
+ else
+ {
+ ASSERT_COND(p_Last);
+ /* set the "last" indication on the last command of the current table */
+ WRITE_UINT32(*p_Last, GET_UINT32(*p_Last) | HMCD_LAST);
+ }
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionNew(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ t_FmPcdManip *p_CurManip;
+ t_Error err;
+ uint32_t nextSize = 0, totalSize;
+ uint16_t tmpReg;
+ uint8_t *p_OldHmct, *p_TmpHmctPtr, *p_TmpDataPtr;
+
+ /* set Manip structure */
+ if (p_FmPcdManipParams->h_NextManip)
+ {
+ if (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))
+ nextSize = (uint32_t)(GetHmctSize(p_FmPcdManipParams->h_NextManip) + GetDataSize(p_FmPcdManipParams->h_NextManip));
+ else
+ p_Manip->cascadedNext = TRUE;
+ }
+ p_Manip->dontParseAfterManip = p_FmPcdManipParams->u.hdr.dontParseAfterManip;
+
+ /* Allocate new table */
+ /* calculate table size according to manip parameters */
+ err = CalculateTableSize(p_FmPcdManipParams, &p_Manip->tableSize, &p_Manip->dataSize);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ totalSize =(uint16_t)(p_Manip->tableSize + p_Manip->dataSize + nextSize);
+
+ p_Manip->p_Hmct = (uint8_t*)FM_MURAM_AllocMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, totalSize, 4);
+ if (!p_Manip->p_Hmct)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc failed"));
+
+ if (p_Manip->dataSize)
+ p_Manip->p_Data = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + nextSize));
+
+ /* update shadow size to allow runtime replacement of Header manipulation */
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ --------------------------------
+ | Shadow | Shadow HMTD |
+ | HMTD | Match Table |
+ | (16 bytes) | (maximal size) |
+ --------------------------------
+ */
+
+ err = FmPcdUpdateCcShadow (p_Manip->h_FmPcd, (uint32_t)(totalSize + 16), (uint16_t)FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err != E_OK)
+ {
+ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for HdrManip node shadow"));
+ }
+
+
+ if (p_FmPcdManipParams->h_NextManip &&
+ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)))
+ {
+ p_OldHmct = (uint8_t *)GetManipInfo(p_FmPcdManipParams->h_NextManip, e_MANIP_HMCT);
+ p_CurManip = p_FmPcdManipParams->h_NextManip;
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a unified table, point to the part of the table
+ * which is the relative offset in HMCT.
+ */
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct,
+ (p_Manip->tableSize +
+ (PTR_TO_UINT(p_CurManip->p_Hmct) -
+ PTR_TO_UINT(p_OldHmct))));
+ if (p_CurManip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct,
+ (p_Manip->tableSize +
+ (PTR_TO_UINT(p_CurManip->p_Data) -
+ PTR_TO_UINT(p_OldHmct))));
+ else
+ p_TmpDataPtr = NULL;
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+ /* update old manip table pointer */
+ MANIP_SET_HMCT_PTR(p_CurManip, p_TmpHmctPtr);
+ MANIP_SET_DATA_PTR(p_CurManip, p_TmpDataPtr);
+
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ /* We copied the HMCT to create a new large HMCT so we can free the old one */
+ FM_MURAM_FreeMem(MANIP_GET_MURAM(p_FmPcdManipParams->h_NextManip), p_OldHmct);
+ }
+
+ /* Fill table */
+ err = BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, TRUE);
+ if (err)
+ {
+ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* Build HMTD (table descriptor) */
+ tmpReg = HMTD_CFG_TYPE; /* NADEN = 0 */
+ /* add parseAfterManip */
+ if (!p_Manip->dontParseAfterManip)
+ tmpReg |= HMTD_CFG_PRS_AFTER_HM;
+ /* create cascade */
+ if (p_FmPcdManipParams->h_NextManip &&
+ !MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))
+ {
+ /* indicate that there's another HM table descriptor */
+ tmpReg |= HMTD_CFG_NEXT_AD_EN;
+ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->nextAdIdx,
+ (uint16_t)((uint32_t)(XX_VirtToPhys(MANIP_GET_HMTD_PTR(p_FmPcdManipParams->h_NextManip)) -
+ (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4));
+ }
+
+ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->cfg, tmpReg);
+ WRITE_UINT32(((t_Hmtd *)p_Manip->h_Ad)->hmcdBasePtr,
+ (uint32_t)(XX_VirtToPhys(p_Manip->p_Hmct) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)));
+
+ WRITE_UINT8(((t_Hmtd *)p_Manip->h_Ad)->opCode, HMAN_OC);
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionShadow(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ uint8_t *p_WholeHmct, *p_TmpHmctPtr, newDataSize, *p_TmpDataPtr = NULL;
+ uint16_t newSize;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ t_Error err;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ err = CalculateTableSize(p_FmPcdManipParams, &newSize, &newDataSize);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* check coherency of new table parameters */
+ if (newSize > p_Manip->tableSize)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (command table)."));
+ if (newDataSize > p_Manip->dataSize)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (data)."));
+ if (p_FmPcdManipParams->h_NextManip)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration can not contain h_NextManip."));
+ if (MANIP_IS_UNIFIED(p_Manip) && (newSize != p_Manip->tableSize))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration in a chained manipulation requires different size than current one."));
+ if (p_Manip->dontParseAfterManip != p_FmPcdManipParams->u.hdr.dontParseAfterManip)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration differs in dontParseAfterManip value."));
+
+ p_Manip->tableSize = newSize;
+ p_Manip->dataSize = newDataSize;
+
+
+ /* Build the new table in the shadow */
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ {
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16);
+ if (p_Manip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_TmpHmctPtr,
+ (PTR_TO_UINT(p_Manip->p_Data) - PTR_TO_UINT(p_Manip->p_Hmct)));
+
+ BuildHmct(p_Manip, p_FmPcdManipParams, p_TmpHmctPtr, p_Manip->p_Data, FALSE);
+ }
+ else
+ {
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a non-head node in a unified table, point to the part of the shadow
+ * which is the relative offset in HMCT.
+ * else, point to the beginning of the
+ * shadow table (we save 16 for the HMTD.
+ */
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow,
+ (16 + PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_WholeHmct)));
+ if (p_CurManip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow,
+ (16 + PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_WholeHmct)));
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionBackToOrig(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ uint8_t *p_WholeHmct, *p_TmpHmctPtr, *p_TmpDataPtr;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ /* Build the new table in the shadow */
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, FALSE);
+ else
+ {
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a unified table, point to the part of the table
+ * which is the relative offset in HMCT.
+ */
+ p_TmpHmctPtr = p_CurManip->p_Hmct; /*- (uint32_t)p_WholeHmct*/
+ p_TmpDataPtr = p_CurManip->p_Data; /*- (uint32_t)p_WholeHmct*/
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateManipIc(t_Handle h_Manip, uint8_t icOffset)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Handle p_Ad;
+ uint32_t tmpReg32 = 0;
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET)
+ {
+ tmpReg32 = *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets;
+ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16);
+ *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets = tmpReg32;
+ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET;
+ p_Manip->icOffset = icOffset;
+ }
+ else
+ {
+ if (p_Manip->icOffset != icOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previously by different value"););
+ }
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET)
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ tmpReg32 |= GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets);
+ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, tmpReg32);
+ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET;
+ p_Manip->icOffset = icOffset;
+ }
+ else
+ {
+ if (p_Manip->icOffset != icOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previousely by different value"););
+ }
+ }
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate)
+{
+
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+ uint32_t tmpReg32;
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode & HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->muramAllocate, E_INVALID_STATE);
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & OFFSET_OF_PR)) ||
+ (p_Manip->shadowUpdateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO;
+ fmPortGetSetCcParams.setCcParams.psoSize = 16;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely"));
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND(!(fmPortGetSetCcParams.getCcParams.prOffset % 16));
+#endif
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ||
+ (p_Manip->updateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO;
+ fmPortGetSetCcParams.setCcParams.psoSize = 16;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely"));
+
+ }
+
+ ASSERT_COND(p_Ad);
+
+ if (p_Manip->updateParams & OFFSET_OF_PR)
+ {
+ tmpReg32 = 0;
+ tmpReg32 |= fmPortGetSetCcParams.getCcParams.prOffset;
+ WRITE_UINT32(p_Ad->matchTblPtr, (GET_UINT32(p_Ad->matchTblPtr) | tmpReg32));
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+ else if (validate)
+ {
+ tmpReg32 = GET_UINT32(p_Ad->matchTblPtr);
+ if ((uint8_t)tmpReg32 != fmPortGetSetCcParams.getCcParams.prOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"););
+ }
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error UpdateModifyCapwapFragmenation(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate,t_Handle h_FmTree)
+{
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad;
+ t_FmPcdCcSavedManipParams *p_SavedManipParams = NULL;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+
+ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree);
+ if (!p_SavedManipParams)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
+ p_Manip->fragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset;
+
+ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
+ tmpReg32 |= ((uint32_t)p_Manip->fragParams.dataOffset<< 16);
+ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
+
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ }
+ else if (validate)
+ {
+
+ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree);
+ if (!p_SavedManipParams)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
+ if (p_Manip->fragParams.dataOffset != p_SavedManipParams->capwapParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"));
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitCapwapFragmentation(t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ t_Handle h_FmTree)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+ uint32_t tmpReg32 = 0;
+ t_FmPcdCcSavedManipParams *p_SavedManipParams;
+
+ UNUSED(h_Ad);
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) ||
+ (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+ /* For CAPWAP Rassembly used FMAN_CTRL2 hardcoded - so for fragmentation its better to use FMAN_CTRL1 */
+ fmPortGetSetCcParams.setCcParams.orFmanCtrl = FPM_PORT_FM_CTL1;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely"));
+
+ p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams));
+ p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16));
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+
+ FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams);
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->updateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
+ tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16);
+ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
+
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+ }
+ else if (validate)
+ {
+ if (p_Manip->fragParams.dataOffset != fmPortGetSetCcParams.getCcParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"));
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate)
+{
+ t_CapwapReasmPram *p_ReassmTbl;
+ t_Error err;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ uint8_t i = 0;
+ uint16_t size;
+ uint32_t tmpReg32;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeoutParams;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE);
+
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("handler of PCD previously was initiated by different value"));
+
+ UNUSED(h_Ad);
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+ p_ReassmTbl = (t_CapwapReasmPram *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & NUM_OF_TASKS) &&
+ !(p_Manip->updateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->updateParams & OFFSET_OF_PR) &&
+ !(p_Manip->updateParams & HW_PORT_ID)) ||
+ ((p_Manip->shadowUpdateParams & NUM_OF_TASKS) ||
+ (p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR) ||
+ (p_Manip->shadowUpdateParams & HW_PORT_ID)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Num of tasks wasn't configured previousely"));
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previousely"));
+ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated"));
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND((fmPortGetSetCcParams.getCcParams.dataOffset % 16) == 0);
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR) &&
+ !(p_Manip->shadowUpdateParams & HW_PORT_ID)) &&
+ ((p_Manip->updateParams & NUM_OF_TASKS) ||
+ (p_Manip->updateParams & OFFSET_OF_DATA) || (p_Manip->updateParams & OFFSET_OF_PR) ||
+ (p_Manip->updateParams & HW_PORT_ID)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("NumOfTasks wasn't configured previously"));
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ if (p_Manip->updateParams & NUM_OF_TASKS)
+ {
+ /*recommendation of Microcode team - (maxNumFramesInProcess * 2) */
+ size = (uint16_t)(p_Manip->fragParams.maxNumFramesInProcess*2 + fmPortGetSetCcParams.getCcParams.numOfTasks);
+ if (size > 255)
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256"));
+
+ p_Manip->fragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks;
+
+ /*p_ReassmFrmDescrIndxPoolTbl*/
+ p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(size + 1),
+ 4);
+ if (!p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table"));
+
+ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1));
+
+ for ( i = 0; i < size; i++)
+ WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32);
+
+ /*p_ReassmFrmDescrPoolTbl*/
+ p_Manip->fragParams.p_ReassmFrmDescrPoolTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)((size + 1) * FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE),
+ 4);
+
+ if (!p_Manip->fragParams.p_ReassmFrmDescrPoolTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table"));
+
+ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32);
+
+ /*p_TimeOutTbl*/
+
+ p_Manip->fragParams.p_TimeOutTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)((size + 1)* FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE),
+ 4);
+
+ if (!p_Manip->fragParams.p_TimeOutTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table"));
+
+ IOMemSet32(p_Manip->fragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32);
+
+ p_Manip->updateParams &= ~NUM_OF_TASKS;
+ p_Manip->shadowUpdateParams |= NUM_OF_TASKS;
+ }
+
+ if (p_Manip->updateParams & OFFSET_OF_DATA)
+ {
+ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+ tmpReg32 = GET_UINT32(p_ReassmTbl->mode);
+ tmpReg32|= p_Manip->fragParams.dataOffset;
+ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32);
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ }
+
+ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
+ {
+ p_Manip->fragParams.prOffset = fmPortGetSetCcParams.getCcParams.prOffset;
+
+ tmpReg32 = GET_UINT32(p_ReassmTbl->mode);
+ tmpReg32|= FM_PCD_MANIP_CAPWAP_REASM_PR_COPY;
+ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32);
+
+ tmpReg32 = GET_UINT32(p_ReassmTbl->intStatsTblPtr);
+ tmpReg32 |= (uint32_t)p_Manip->fragParams.prOffset << 24;
+ WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32);
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+ else
+ {
+ p_Manip->fragParams.prOffset = 0xff;
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+
+ p_Manip->fragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId;
+ p_Manip->updateParams &= ~HW_PORT_ID;
+ p_Manip->shadowUpdateParams |= HW_PORT_ID;
+
+ /*timeout hc */
+ ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->fragParams.fqidForTimeOutFrames;
+ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->fragParams.hwPortId << 24;
+ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase));
+ ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<<p_Manip->fragParams.bitFor1Micro) * p_Manip->fragParams.timeoutRoutineRequestTime)/2;
+ return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams);
+ }
+
+ else if (validate)
+ {
+ if (fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->fragParams.hwPortId)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port"));
+ if (fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->fragParams.numOfTasks)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value "));
+
+
+ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
+ {
+ if (p_Manip->fragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
+ }
+ else
+ {
+ if (p_Manip->fragParams.prOffset != 0xff)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
+ }
+ if (fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->fragParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value "));
+ }
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0};
+ t_Error err = E_OK;
+ uint8_t result;
+ uint32_t bitFor1Micro, tsbs, log2num;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_IpReasmCommonPramTbl);
+
+ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);
+ bitFor1Micro = 32 - bitFor1Micro;
+ LOG2(FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH, log2num);
+ tsbs = bitFor1Micro - log2num;
+
+ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase);
+ ccIpReassmTimeoutParams.tsbs = (uint8_t)tsbs;
+ ccIpReassmTimeoutParams.activate = TRUE;
+ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ switch (result)
+ {
+ case (0):
+ return E_OK;
+ case (1):
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate TNUM"));
+ case (2):
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate internal buffer"));
+ case (3):
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("'Disable Timeout Task' with invalid IPRCPT"));
+ case (4):
+ RETURN_ERROR(MAJOR, E_FULL, ("too many timeout tasks"));
+ case (5):
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("invalid sub command"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+ return E_OK;
+}
+
+static t_Error CreateIpReassCommonTable(t_FmPcdManip *p_Manip)
+{
+ uint32_t tmpReg32 = 0, i;
+ uint64_t tmpReg64, size;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ t_Error err = E_OK;
+
+ /* Allocation of the IP Reassembly Common Parameters table. This table is located in the
+ MURAM. Its size is 64 bytes and its base address should be 8-byte aligned.
+ It contains parameters that are common to both the IPv4 reassembly function and IPv6
+ reassembly function.*/
+ p_Manip->ipReassmParams.p_IpReassCommonTbl =
+ (t_IpReassCommonTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE,
+ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN);
+
+ if (!p_Manip->ipReassmParams.p_IpReassCommonTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly common parameters table"));
+
+ IOMemSet32(p_Manip->ipReassmParams.p_IpReassCommonTbl, 0, FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE);
+
+ /* Setting the TimeOut Mode.*/
+ tmpReg32 = 0;
+ if (p_Manip->ipReassmParams.timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES)
+ tmpReg32 |= FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES;
+
+ /* Setting TimeOut FQID - Frames that time out are enqueued to this FQID.
+ In order to cause TimeOut frames to be discarded, this queue should be configured accordingly*/
+ tmpReg32 |= p_Manip->ipReassmParams.fqidForTimeOutFrames;
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeoutModeAndFqid, tmpReg32);
+
+ /* Calculation the size of IP Reassembly Frame Descriptor - number of frames that are allowed to be reassembled simultaneously + 129.*/
+ size = p_Manip->ipReassmParams.maxNumFramesInProcess + 129;
+
+ /*Allocation of IP Reassembly Frame Descriptor Indexes Pool - This pool resides in the MURAM */
+ p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(size * 2),
+ 256));
+ if (!p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly frame descriptor indexes pool"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), 0, (uint32_t)(size * 2));
+
+ /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to
+ the maximum number of frames that are allowed to be reassembled simultaneously + 128.
+ The last entry in this pool must contain the index zero*/
+ for (i=0; i<(size-1); i++)
+ WRITE_UINT16(*(uint16_t *)PTR_MOVE(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), (i<<1)),
+ (uint16_t)(i+1));
+
+ /* Sets the IP Reassembly Frame Descriptor Indexes Pool offset from MURAM */
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescIndexPoolTblPtr, tmpReg32);
+
+ /* Allocation of the Reassembly Frame Descriptors Pool - This pool resides in external memory.
+ The number of entries in this pool should be equal to the number of entries in IP Reassembly Frame Descriptor Indexes Pool.*/
+ p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr =
+ PTR_TO_UINT(XX_MallocSmart((uint32_t)(size * 64), p_Manip->ipReassmParams.dataMemId, 64));
+
+ if (!p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr), 0, (uint32_t)(size * 64));
+
+ /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/
+ tmpReg64 = (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)));
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->liodnAndReassFrmDescPoolPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescPoolPtrLow, (uint32_t)tmpReg64);
+
+ /*Allocation of the TimeOut table - This table resides in the MURAM.
+ The number of entries in this table is identical to the number of entries in the Reassembly Frame Descriptors Pool*/
+ p_Manip->ipReassmParams.timeOutTblAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 8),8));
+
+ if (!p_Manip->ipReassmParams.timeOutTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly timeout table"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr), 0, (uint16_t)(size * 8));
+
+ /* Sets the TimeOut table offset from MURAM */
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr)) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeOutTblPtr, tmpReg32);
+
+ /* Sets the Expiration Delay */
+ tmpReg32 = 0;
+ tmpReg32 |= (((uint32_t)(1 << FmGetTimeStampScale(p_FmPcd->h_Fm))) * p_Manip->ipReassmParams.timeoutThresholdForReassmProcess);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->expirationDelay, tmpReg32);
+
+ err = FmPcdRegisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ if (err != E_OK)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ RETURN_ERROR(MAJOR, err, ("port registration"));
+ }
+
+ return err;
+}
+
+static t_Error CreateIpReassTable(t_FmPcdManip *p_Manip, bool ipv4)
+{
+ t_FmPcd *p_FmPcd = p_Manip->h_FmPcd;
+ uint32_t tmpReg32, autoLearnHashTblSize;
+ uint32_t numOfWays, setSize, setSizeCode, keySize;
+ uint32_t waySize, numOfSets, numOfEntries;
+ uint64_t tmpReg64;
+ uint16_t minFragSize;
+ uintptr_t *p_AutoLearnHashTblAddr, *p_AutoLearnSetLockTblAddr;
+ t_IpReassTbl **p_IpReassTbl;
+
+ if (ipv4)
+ {
+ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv4ReassTbl;
+ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr;
+ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr;
+ minFragSize = p_Manip->ipReassmParams.minFragSize[0];
+ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[0];
+ keySize = 4 + 4 + 1 + 2; /* 3-tuple + IP-Id */
+ }
+ else
+ {
+ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv6ReassTbl;
+ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr;
+ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr;
+ minFragSize = p_Manip->ipReassmParams.minFragSize[1];
+ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[1];
+ keySize = 16 + 16 + 4; /* 2-tuple + IP-Id */
+ if (numOfWays > e_FM_PCD_MANIP_SIX_WAYS_HASH)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("num of ways"));
+ }
+ keySize += 2; /* 2 bytes reserved for RFDIndex */
+#if (DPAA_VERSION >= 11)
+ keySize += 2; /* 2 bytes reserved */
+#endif /* (DPAA_VERSION >= 11) */
+ waySize = ROUND_UP(keySize, 8);
+
+ /* Allocates the IP Reassembly Parameters Table - This table is located in the MURAM.*/
+ *p_IpReassTbl = (t_IpReassTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_IP_REASM_TABLE_SIZE,
+ FM_PCD_MANIP_IP_REASM_TABLE_ALIGN);
+ if (!*p_IpReassTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly IPv4/IPv6 specific parameters table"));
+ memset(*p_IpReassTbl, 0, sizeof(t_IpReassTbl));
+
+ /* Sets the IP Reassembly common Parameters table offset from MURAM in the IP Reassembly Table descriptor*/
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_IpReassCommonTbl) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32((*p_IpReassTbl)->ipReassCommonPrmTblPtr, tmpReg32);
+
+ /* Calculate set size (set size is rounded-up to next power of 2) */
+ NEXT_POWER_OF_2(numOfWays * waySize, setSize);
+
+ /* Get set size code */
+ LOG2(setSize, setSizeCode);
+
+ /* Sets ways number and set size code */
+ WRITE_UINT16((*p_IpReassTbl)->waysNumAndSetSize, (uint16_t)((numOfWays << 8) | setSizeCode));
+
+ /* It is recommended that the total number of entries in this table
+ (number of sets * number of ways) will be twice the number of frames that
+ are expected to be reassembled simultaneously.*/
+ numOfEntries = (uint32_t)(p_Manip->ipReassmParams.maxNumFramesInProcess * 2);
+
+ /* sets number calculation - number of entries = number of sets * number of ways */
+ numOfSets = numOfEntries / numOfWays;
+
+ /* Sets AutoLearnHashKeyMask*/
+ NEXT_POWER_OF_2(numOfSets, numOfSets);
+
+ WRITE_UINT16((*p_IpReassTbl)->autoLearnHashKeyMask, (uint16_t)(numOfSets - 1));
+
+ /* Allocation of IP Reassembly Automatic Learning Hash Table - This table resides in external memory.
+ The size of this table is determined by the number of sets and the set size.
+ Table size = set size * number of sets
+ This table base address should be aligned to SetSize.*/
+ autoLearnHashTblSize = numOfSets * setSize;
+
+ *p_AutoLearnHashTblAddr = PTR_TO_UINT(XX_MallocSmart(autoLearnHashTblSize, p_Manip->ipReassmParams.dataMemId, setSize));
+ if (!*p_AutoLearnHashTblAddr)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl);
+ *p_IpReassTbl = NULL;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+ }
+ IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize);
+
+ /* Sets the IP Reassembly Automatic Learning Hash Table and liodn offset */
+ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnHashTblAddr));
+ WRITE_UINT32((*p_IpReassTbl)->liodnAlAndAutoLearnHashTblPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32((*p_IpReassTbl)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64);
+
+ /* Allocation of the Set Lock table - This table resides in external memory
+ The size of this table is (number of sets in the IP Reassembly Automatic Learning Hash table)*4 bytes.
+ This table resides in external memory and its base address should be 4-byte aligned */
+ *p_AutoLearnSetLockTblAddr = PTR_TO_UINT(XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->ipReassmParams.dataMemId, 4));
+ if (!*p_AutoLearnSetLockTblAddr)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl);
+ *p_IpReassTbl = NULL;
+ XX_FreeSmart(UINT_TO_PTR(*p_AutoLearnHashTblAddr));
+ *p_AutoLearnHashTblAddr = 0;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+ }
+ IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4));
+
+ /* sets Set Lock table pointer and liodn offset*/
+ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr));
+ WRITE_UINT32((*p_IpReassTbl)->liodnSlAndAutoLearnSetLockTblPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32((*p_IpReassTbl)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64);
+
+ /* Sets user's requested minimum fragment size (in Bytes) for First/Middle fragment */
+ WRITE_UINT16((*p_IpReassTbl)->minFragSize, minFragSize);
+
+ return E_OK;
+}
+
+static t_Error UpdateInitIpReasm(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate)
+{
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ uint32_t tmpReg32;
+ t_Error err;
+ t_FmPortPcdParams *p_PcdParams = (t_FmPortPcdParams *)h_PcdParams;
+#if (DPAA_VERSION >= 11)
+ uint8_t *p_Ptr;
+#endif /* (DPAA_VERSION >= 11) */
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->updateParams || h_PcdParams, E_INVALID_HANDLE);
+
+ UNUSED(h_Ad);
+
+ if (!p_Manip->updateParams)
+ return E_OK;
+
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value"));
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))) ||
+ ((p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))) ||
+ ((p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ if (p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS))
+ {
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t *p_Ptr, i, totalNumOfTnums;
+
+ totalNumOfTnums = (uint8_t)(fmPortGetSetCcParams.getCcParams.numOfTasks +
+ fmPortGetSetCcParams.getCcParams.numOfExtraTasks);
+
+ p_Manip->ipReassmParams.internalBufferPoolAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS),
+ BMI_FIFO_UNITS));
+ if (!p_Manip->ipReassmParams.internalBufferPoolAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers pool"));
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr),
+ 0,
+ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS));
+
+ p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(5 + totalNumOfTnums),
+ 4));
+ if (!p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers management"));
+
+ p_Ptr = (uint8_t*)UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr);
+ WRITE_UINT32(*(uint32_t*)p_Ptr, (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr)) - p_FmPcd->physicalMuramBase));
+ for (i=0, p_Ptr += 4; i < totalNumOfTnums; i++, p_Ptr++)
+ WRITE_UINT8(*p_Ptr, i);
+ WRITE_UINT8(*p_Ptr, 0xFF);
+
+ tmpReg32 = (4 << FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT) |
+ ((uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)) - p_FmPcd->physicalMuramBase));
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->internalBufferManagement, tmpReg32);
+
+ p_Manip->updateParams &= ~(NUM_OF_TASKS | NUM_OF_EXTRA_TASKS);
+ p_Manip->shadowUpdateParams |= (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS);
+ }
+ }
+
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ {
+ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv4Scheme;
+ p_PcdParams->p_KgParams->numOfSchemes++;
+ }
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ {
+ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv6Scheme;
+ p_PcdParams->p_KgParams->numOfSchemes++;
+ }
+
+#if (DPAA_VERSION >= 11)
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = FM_REV;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev >= 6)
+ {
+ if ((err = FmPortSetGprFunc(h_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_Ptr)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 = NIA_ENG_KG;
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ {
+ tmpReg32 |= NIA_KG_DIRECT;
+ tmpReg32 |= NIA_KG_CC_EN;
+ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv4Scheme);
+ WRITE_UINT32(*(uint32_t*)PTR_MOVE(p_Ptr, NIA_IPR_DIRECT_SCHEME_IPV4_OFFSET), tmpReg32);
+ }
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ {
+ tmpReg32 &= ~NIA_AC_MASK;
+ tmpReg32 |= NIA_KG_DIRECT;
+ tmpReg32 |= NIA_KG_CC_EN;
+ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv6Scheme);
+ WRITE_UINT32(*(uint32_t*)PTR_MOVE(p_Ptr, NIA_IPR_DIRECT_SCHEME_IPV6_OFFSET), tmpReg32);
+ }
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION == 10)
+static t_Error FmPcdFragHcScratchPoolFill(t_Handle h_FmPcd, uint8_t scratchBpid)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams));
+
+ fmPcdCcFragScratchPoolCmdParams.numOfBuffers = NUM_OF_SCRATCH_POOL_BUFFERS;
+ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid;
+ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, TRUE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPcdCcFragScratchPoolCmdParams.numOfBuffers != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Fill scratch pool failed,"
+ "Failed to release %d buffers to the BM (missing FBPRs)",
+ fmPcdCcFragScratchPoolCmdParams.numOfBuffers));
+
+ return E_OK;
+}
+
+static t_Error FmPcdFragHcScratchPoolEmpty(t_Handle h_FmPcd, uint8_t scratchBpid)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams));
+
+ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid;
+ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, FALSE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION == 10) */
+
+static void ReleaseManipHandler(t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
+{
+ if (p_Manip->h_Ad)
+ {
+ if (p_Manip->muramAllocate)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Ad);
+ else
+ XX_Free(p_Manip->h_Ad);
+ p_Manip->h_Ad = NULL;
+ }
+ if (p_Manip->p_Template)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_Template);
+ p_Manip->p_Template = NULL;
+ }
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->fragParams.p_AutoLearnHashTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_AutoLearnHashTbl);
+ if (p_Manip->fragParams.p_ReassmFrmDescrPoolTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrPoolTbl);
+ if (p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl);
+ if (p_Manip->fragParams.p_TimeOutTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_TimeOutTbl);
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag);
+
+ }
+ if (p_Manip->frag)
+ {
+ if (p_Manip->ipFragParams.p_Frag)
+ {
+#if (DPAA_VERSION == 10)
+ FmPcdFragHcScratchPoolEmpty((t_Handle)p_FmPcd, p_Manip->ipFragParams.scratchBpid);
+#endif /* (DPAA_VERSION == 10) */
+
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag);
+ }
+ }
+ else if (p_Manip->reassm)
+ {
+ FmPcdUnregisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+
+ if (p_Manip->ipReassmParams.timeOutTblAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr));
+ if (p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr));
+
+ if (p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr));
+ if (p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr));
+ if (p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr));
+ if (p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr));
+ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv4ReassTbl);
+ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv6ReassTbl);
+ if (p_Manip->ipReassmParams.p_IpReassCommonTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ if (p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr));
+ if (p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr));
+ if (p_Manip->ipReassmParams.internalBufferPoolAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr));
+
+ if (p_Manip->ipReassmParams.h_Ipv6Ad)
+ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv6Ad);
+ if (p_Manip->ipReassmParams.h_Ipv4Ad)
+ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv4Ad);
+ }
+
+ if (p_Manip->p_StatsTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl);
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ if (p_ManipParams->u.hdr.rmv)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START) :
+ if (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.include)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP_DTLS) :
+ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ p_Manip->muramAllocate = TRUE;
+ if (p_ManipParams->u.hdr.insrt)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for CAPWAP_DTLS_HDR remove can not be insrt manipualtion after"));
+ if (p_ManipParams->fragOrReasm)
+ {
+ if (!p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("unsupported header for Reassembly"));
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for this type of manipulation frag can not be TRUE"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid net header of remove location"));
+ }
+ }
+ else
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP_DTLS) :
+ case (HEADER_TYPE_CAPWAP) :
+ if (p_ManipParams->fragOrReasm || p_ManipParams->u.hdr.insrt)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_CAPWAP can not be insert or fragOrReasm TRUE"));
+ p_Manip->opcode = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
+ p_Manip->muramAllocate = TRUE;
+ p_ManipParams->u.hdr.insrt = TRUE; //internal frame header
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ }
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ }
+ else if (p_ManipParams->u.hdr.insrt)
+ {
+ switch (p_ManipParams->u.hdr.insrtParams.type)
+ {
+ case (e_FM_PCD_MANIP_INSRT_BY_TEMPLATE) :
+
+ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ p_Manip->muramAllocate = FALSE;
+ if (p_ManipParams->fragOrReasm)
+ {
+ if (p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header for fragmentation"));
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("can not reach this point"));
+ }
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type"));
+ }
+ }
+ else if (p_ManipParams->fragOrReasm)
+ {
+ if (p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION;
+ p_Manip->muramAllocate = FALSE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for fragmentation"));
+ }
+ }
+ else
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Reassembly has to be with additional operation - rmv = TRUE, type of remove - e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION,type = e_FM_PCD_MANIP_LOC_BY_HDR, hdr = HEADER_TYPE_CAPWAP_DTLS"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly"));
+ }
+ }
+
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("User didn't ask for any manipulation"));
+
+ p_Manip->insrt = p_ManipParams->u.hdr.insrt;
+ p_Manip->rmv = p_ManipParams->u.hdr.rmv;
+
+ return E_OK;
+}
+
+#else /* not FM_CAPWAP_SUPPORT */
+static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ switch (p_ManipParams->type)
+ {
+ case e_FM_PCD_MANIP_HDR :
+ /* Check that next-manip is not already used */
+ if (p_ManipParams->h_NextManip)
+ {
+ if (!MANIP_IS_FIRST(p_ManipParams->h_NextManip))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_NextManip is already a part of another chain"));
+ if (MANIP_GET_TYPE(p_ManipParams->h_NextManip) != e_FM_PCD_MANIP_HDR)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("For a Header Manipulation node - no support of h_NextManip of type other than Header Manipulation."));
+ }
+
+ if (p_ManipParams->u.hdr.rmv)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2) :
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ break;
+ case (e_FM_PCD_MANIP_RMV_GENERIC):
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ p_Manip->rmv = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.insrt)
+ {
+ switch (p_ManipParams->u.hdr.insrtParams.type)
+ {
+ case (e_FM_PCD_MANIP_INSRT_BY_HDR) :
+ case (e_FM_PCD_MANIP_INSRT_GENERIC):
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type"));
+ }
+ p_Manip->insrt = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.fieldUpdate)
+ {
+ /* Check parameters */
+ if (p_ManipParams->u.hdr.fieldUpdateParams.type == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN)
+ {
+ if ((p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI)
+ && (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri > 7))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpri should get values of 0-7 "));
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ int i;
+
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal > 7)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpriDefVal should get values of 0-7 "));
+ for (i = 0 ; i < FM_PCD_MANIP_DSCP_TO_VLAN_TRANS ; i++)
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i] & 0xf0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dscpToVpriTabl value out of range (0-15)"));
+ }
+
+ }
+
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ p_Manip->fieldUpdate = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.custom)
+ {
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ p_Manip->custom = TRUE;
+ }
+ break;
+ case e_FM_PCD_MANIP_REASSEM :
+ if (p_ManipParams->h_NextManip)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with reassembly"));
+ switch (p_ManipParams->u.reassem.hdr)
+ {
+ case (HEADER_TYPE_IPv4):
+ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv4;
+ break;
+ case (HEADER_TYPE_IPv6):
+ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv6;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for reassembly"));
+ }
+ p_Manip->opcode = HMAN_OC_IP_REASSEMBLY;
+ break;
+ case e_FM_PCD_MANIP_FRAG :
+ if (p_ManipParams->h_NextManip)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with fragmentation"));
+ switch (p_ManipParams->u.frag.hdr)
+ {
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for fragmentation"));
+ }
+ p_Manip->opcode = HMAN_OC_IP_FRAGMENTATION;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ case e_FM_PCD_MANIP_SPECIAL_OFFLOAD :
+ switch (p_ManipParams->u.specialOffload.type)
+ {
+ case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC):
+ p_Manip->opcode = HMAN_OC_IPSEC_MANIP;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("special offload type"));
+ }
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("manip type"));
+ }
+
+ return E_OK;
+}
+#endif /* not FM_CAPWAP_SUPPORT */
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error UpdateIndxStats(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t tmpReg32 = 0;
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("handler of PCD previously was initiated by different value"));
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ if (!p_Manip->p_StatsTbl)
+ {
+
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 = GET_UINT32(p_Ad->ccAdBase);
+
+ p_Manip->p_StatsTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)p_Manip->owner * FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE,
+ 4);
+ if (!p_Manip->p_StatsTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table"));
+
+ IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4));
+
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase);
+
+ if (p_Manip->cnia)
+ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_CNIA;
+
+ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_DPD;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+ }
+ else
+ {
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error FmPcdManipInitUpdate(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ int level,
+ t_Handle h_FmTree)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+
+ UNUSED(level);
+ UNUSED(h_FmPcd);
+ UNUSED(h_FmTree);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, p_Manip, h_Ad, validate);
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if (!p_Manip->h_Frag)
+ break;
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ err = UpdateInitCapwapFragmentation(h_FmPort, p_Manip, h_Ad, validate, h_FmTree);
+ break;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate);
+ break;
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ case (HMAN_OC_IP_REASSEMBLY):
+ err = UpdateInitIpReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate);
+ break;
+ default:
+ return E_OK;
+ }
+
+ return err;
+}
+
+static t_Error FmPcdManipModifyUpdate(t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree)
+{
+
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ UNUSED(level);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation is not suppported"));
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+
+ if (p_Manip->h_Frag)
+ {
+ if (!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation requires manipulation be updated previously in SetPcd function"));
+ }
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if (p_Manip->h_Frag)
+ err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ default:
+ return E_OK;
+ }
+
+ return err;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error GetPrOffsetByHeaderOrField(t_FmManipHdrInfo *p_HdrInfo, uint8_t *parseArrayOffset)
+{
+ e_NetHeaderType hdr = p_HdrInfo->hdr;
+ e_FmPcdHdrIndex hdrIndex = p_HdrInfo->hdrIndex;
+ bool byField = p_HdrInfo->byField;
+ t_FmPcdFields field;
+
+ if (byField)
+ field = p_HdrInfo->fullField;
+
+ if (byField)
+ {
+ switch (hdr)
+ {
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type Ethernet with this field not supported"));
+ }
+ break;
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI) :
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type VLAN with this field not supported"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header by field not supported"));
+ }
+ }
+ else
+ {
+ switch (hdr){
+ case (HEADER_TYPE_ETH):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET;
+ break;
+ case (HEADER_TYPE_LLC_SNAP):
+ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET;
+ break;
+ case (HEADER_TYPE_PPPoE):
+ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET;
+ break;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET;
+ break;
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_IP1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET;
+ break;
+ case (HEADER_TYPE_MINENCAP):
+ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET;
+ break;
+ case (HEADER_TYPE_GRE):
+ *parseArrayOffset = CC_PC_PR_GRE_OFFSET;
+ break;
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_SCTP):
+ *parseArrayOffset = CC_PC_PR_L4_OFFSET;
+ break;
+ case (HEADER_TYPE_CAPWAP):
+ case (HEADER_TYPE_CAPWAP_DTLS):
+ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header is not supported"));
+ }
+ }
+ return E_OK;
+}
+
+static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipHdrRmvParams *p_ManipParams, t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+ uint8_t prsArrayOffset = 0;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->rmv)
+ {
+ err = GetPrOffsetByHeaderOrField(&p_ManipParams->u.byHdr.u.fromStartByHdr.hdrInfo, &prsArrayOffset);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 |= (uint32_t)prsArrayOffset << 24;
+ tmpReg32 |= HMAN_RMV_HDR;
+ }
+
+ if (p_Manip->insrt)
+ tmpReg32 |= HMAN_INSRT_INT_FRM_HDR;
+
+ tmpReg32 |= (uint32_t)HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
+
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error MvIntFrameHeaderFromFrameToBufferPrefix(t_FmPcdManip *p_Manip, bool caamUsed)
+{
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Ad,E_INVALID_HANDLE);
+
+ p_Manip->updateParams |= OFFSET_OF_PR | INTERNAL_CONTEXT_OFFSET;
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ *(uint32_t *)&p_Ad->ccAdBase = tmpReg32;
+
+ tmpReg32 = 0;
+ tmpReg32 |= HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX;
+ tmpReg32 |= (uint32_t)0x16 << 16;
+ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32;
+
+ if (caamUsed)
+ *(uint32_t *)&p_Ad->gmask = 0xf0000000;
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CapwapRmvDtlsHdr(t_FmPcd *p_FmPcd, t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+
+
+ if (p_Manip->h_Frag)
+ {
+ p_Manip->updateParams |= INTERNAL_CONTEXT_OFFSET;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase));
+ }
+
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return err;
+}
+
+static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams,
+ t_FmPcdManip *p_Manip,
+ t_FmPcd *p_FmPcd,
+ uint8_t poolId)
+{
+ t_Handle p_Table;
+ uint32_t tmpReg32 = 0;
+ int i = 0;
+ uint8_t log2Num;
+ uint8_t numOfSets;
+ uint32_t j = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!p_FmPcd->h_Hc)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("hc port has to be initialized in this mode"));
+ if (!POWER_OF_2(p_ManipParams->timeoutRoutineRequestTime))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("timeoutRoutineRequestTime has to be power of 2"));
+ if (!POWER_OF_2(p_ManipParams->maxNumFramesInProcess))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2"));
+ if (!p_ManipParams->timeoutRoutineRequestTime && p_ManipParams->timeoutThresholdForReassmProcess)
+ DBG(WARNING, ("if timeoutRoutineRequestTime 0, timeoutThresholdForReassmProcess is uselessly"));
+ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH)
+ {
+ if ((p_ManipParams->maxNumFramesInProcess < 4) ||
+ (p_ManipParams->maxNumFramesInProcess > 512))
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_EIGHT_WAYS_HASH maxNumFramesInProcess has to be in the range 4-512"));
+ }
+ else
+ {
+ if ((p_ManipParams->maxNumFramesInProcess < 8) ||
+ (p_ManipParams->maxNumFramesInProcess > 2048))
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_FOUR_WAYS_HASH maxNumFramesInProcess has to be in the range 8-2048"));
+ }
+
+ p_Manip->updateParams |= (NUM_OF_TASKS | OFFSET_OF_PR | OFFSET_OF_DATA | HW_PORT_ID);
+
+ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE,
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN);
+ if (!p_Manip->h_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table"));
+
+ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE);
+
+ p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag;
+
+ p_Manip->fragParams.p_AutoLearnHashTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE),
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN);
+
+ if (!p_Manip->fragParams.p_AutoLearnHashTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table"));
+
+ IOMemSet32(p_Manip->fragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE));
+
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->autoLearnHashTblPtr, tmpReg32);
+
+ tmpReg32 = 0;
+ if (p_ManipParams->timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES;
+ if (p_ManipParams->haltOnDuplicationFrag)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG;
+ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH)
+ {
+ i = 8;
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS;
+ }
+ else
+ i = 4;
+
+ numOfSets = (uint8_t)((p_ManipParams->maxNumFramesInProcess * 2) / i);
+ LOG2(numOfSets, log2Num);
+ tmpReg32 |= (uint32_t)(log2Num - 1) << 24;
+
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->mode, tmpReg32);
+
+ for (j=0; j<p_ManipParams->maxNumFramesInProcess*2; j++)
+ if (((j / i) % 2)== 0)
+ WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->fragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000);
+
+ tmpReg32 = 0x00008000;
+ tmpReg32 |= (uint32_t)poolId << 16;
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, tmpReg32);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000);
+
+ p_Manip->fragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess;
+
+ p_Manip->fragParams.sgBpid = poolId;
+
+ p_Manip->fragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames;
+ p_Manip->fragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime;
+ p_Manip->fragParams.bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);
+
+ tmpReg32 = 0;
+ tmpReg32 |= (((uint32_t)1<<p_Manip->fragParams.bitFor1Micro) * p_ManipParams->timeoutThresholdForReassmProcess);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->expirationDelay, tmpReg32);
+
+ return E_OK;
+}
+
+static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams,
+ t_FmPcdManip *p_Manip,
+ t_FmPcd *p_FmPcd,
+ uint8_t poolId)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Manip->updateParams |= OFFSET_OF_DATA;
+
+ p_Manip->frag = TRUE;
+
+ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->h_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor"));
+
+ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION;
+
+ if (p_ManipParams->headerOptionsCompr)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN;
+ tmpReg32 |= ((uint32_t)poolId << 8);
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation;
+ p_Manip->fragParams.sgBpid = poolId;
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, bool ipv4)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ uint32_t tmpReg32;
+ t_Error err = E_OK;
+
+ /* Creates the IP Reassembly Parameters table. It contains parameters that are specific to either the IPv4 reassembly
+ function or to the IPv6 reassembly function. If both IPv4 reassembly and IPv6 reassembly are required, then
+ two separate IP Reassembly Parameter tables are required.*/
+ if ((err = CreateIpReassTable(p_Manip, ipv4)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Sets the first Ad register (ccAdBase) - Action Descriptor Type and Pointer to the IP Reassembly Parameters Table offset from MURAM*/
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+
+ /* Gets the required Action descriptor table pointer */
+ if (ipv4)
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv4Ad;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv4ReassTbl) - (p_FmPcd->physicalMuramBase));
+ }
+ else
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv6Ad;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv6ReassTbl) - (p_FmPcd->physicalMuramBase));
+ }
+
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ /* Sets the second Ad register (matchTblPtr) - Buffer pool ID (BPID for V2) and Scatter/Gather table offset*/
+ /* mark the Scatter/Gather table offset to be set later on when the port will be known */
+ p_Manip->updateParams = (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS);
+
+#if (DPAA_VERSION == 10)
+ tmpReg32 = (uint32_t)(p_Manip->ipReassmParams.sgBpid << 8);
+ WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32);
+#endif /* (DPAA_VERSION == 10) */
+#if (DPAA_VERSION >= 11)
+ if (p_Manip->ipReassmParams.nonConsistentSpFqid != 0)
+ {
+ tmpReg32 = FM_PCD_AD_NCSPFQIDM_MASK | (uint32_t)(p_Manip->ipReassmParams.nonConsistentSpFqid);
+ WRITE_UINT32(p_Ad->gmask, tmpReg32);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Sets the third Ad register (pcAndOffsets)- IP Reassemble Operation Code*/
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ p_Manip->reassm = TRUE;
+
+ return E_OK;
+}
+
+static t_Error SetIpv4ReassmManip(t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+
+ /* Allocation if IPv4 Action descriptor */
+ p_Manip->ipReassmParams.h_Ipv4Ad =
+ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE,
+ p_Manip->ipReassmParams.dataMemId,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipReassmParams.h_Ipv4Ad)
+ {
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv4 table descriptor"));
+ }
+
+ memset(p_Manip->ipReassmParams.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */
+ return FillReassmManipParams(p_Manip, TRUE);
+}
+
+static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+
+ /* Allocation if IPv6 Action descriptor */
+ p_Manip->ipReassmParams.h_Ipv6Ad =
+ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE,
+ p_Manip->ipReassmParams.dataMemId,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipReassmParams.h_Ipv6Ad)
+ {
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv6 table descriptor"));
+ }
+
+ memset(p_Manip->ipReassmParams.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */
+ return FillReassmManipParams(p_Manip, FALSE);
+}
+
+static t_Error IpReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams,
+ t_FmPcdManip *p_Manip)
+{
+ uint32_t maxSetNumber = 10000;
+ t_FmPcdManipReassemIpParams reassmManipParams = p_ManipReassmParams->u.ipReassem;
+ t_Error res;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, E_INVALID_HANDLE);
+
+ /* Check validation of user's parameter.*/
+ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) ||
+ (reassmManipParams.timeoutThresholdForReassmProcess > 8000000))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("timeoutThresholdForReassmProcess should be 1msec - 8sec"));
+ /* It is recommended that the total number of entries in this table (number of sets * number of ways)
+ will be twice the number of frames that are expected to be reassembled simultaneously.*/
+ if (reassmManipParams.maxNumFramesInProcess >
+ (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)"));
+
+ if ((p_ManipReassmParams->hdr == HEADER_TYPE_IPv6) &&
+ (reassmManipParams.minFragSize[1] < 256))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("minFragSize[1] must be >= 256"));
+
+ /* Saves user's reassembly manipulation parameters */
+ p_Manip->ipReassmParams.relativeSchemeId[0] = reassmManipParams.relativeSchemeId[0];
+ p_Manip->ipReassmParams.relativeSchemeId[1] = reassmManipParams.relativeSchemeId[1];
+ p_Manip->ipReassmParams.numOfFramesPerHashEntry[0] = reassmManipParams.numOfFramesPerHashEntry[0];
+ p_Manip->ipReassmParams.numOfFramesPerHashEntry[1] = reassmManipParams.numOfFramesPerHashEntry[1];
+ p_Manip->ipReassmParams.minFragSize[0] = reassmManipParams.minFragSize[0];
+ p_Manip->ipReassmParams.minFragSize[1] = reassmManipParams.minFragSize[1];
+ p_Manip->ipReassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess;
+ p_Manip->ipReassmParams.timeOutMode = reassmManipParams.timeOutMode;
+ p_Manip->ipReassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames;
+ p_Manip->ipReassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess;
+ p_Manip->ipReassmParams.dataMemId = reassmManipParams.dataMemId;
+ p_Manip->ipReassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset;
+#if (DPAA_VERSION == 10)
+ p_Manip->ipReassmParams.sgBpid = reassmManipParams.sgBpid;
+#endif /* (DPAA_VERSION == 10) */
+#if (DPAA_VERSION >= 11)
+ if (reassmManipParams.nonConsistentSpFqid != 0)
+ {
+ p_Manip->ipReassmParams.nonConsistentSpFqid = reassmManipParams.nonConsistentSpFqid;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Creates and initializes the IP Reassembly common parameter table */
+ CreateIpReassCommonTable(p_Manip);
+
+ /* Creation of IPv4 reassembly manipulation */
+ if ((p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6) || (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4))
+ {
+ res = SetIpv4ReassmManip(p_Manip);
+ if (res != E_OK)
+ return res;
+ }
+
+ /* Creation of IPv6 reassembly manipulation */
+ if (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6)
+ {
+ res = SetIpv6ReassmManip(p_Manip);
+ if (res != E_OK)
+ return res;
+ }
+
+ return E_OK;
+}
+
+static void setReassmSchemeParams(t_FmPcd* p_FmPcd, t_FmPcdKgSchemeParams *p_Scheme, t_Handle h_CcTree, bool ipv4, uint8_t groupId)
+{
+ uint32_t j;
+ uint8_t res;
+
+ /* Configures scheme's network environment parameters */
+ p_Scheme->netEnvParams.numOfDistinctionUnits = 2;
+ if (ipv4)
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv4, FALSE, 0);
+ else
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv6, FALSE, 0);
+ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ p_Scheme->netEnvParams.unitIds[0] = res;
+
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0);
+ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ p_Scheme->netEnvParams.unitIds[1] = res;
+
+ /* Configures scheme's next engine parameters*/
+ p_Scheme->nextEngine = e_FM_PCD_CC;
+ p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree;
+ p_Scheme->kgNextEngineParams.cc.grpId = groupId;
+ p_Scheme->useHash = TRUE;
+
+ /* Configures scheme's key*/
+ if (ipv4 == TRUE)
+ {
+ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv4 ;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_DST_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_SRC_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_PROTO;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.ignoreProtocolValidation = FALSE;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.size = 2;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.offset = 4;
+ }
+ else /* IPv6 */
+ {
+ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 3;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv6 ;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_DST_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv6;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_SRC_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.size = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.offset = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.ignoreProtocolValidation = TRUE;
+ }
+
+ p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x01020304;
+ p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x11121314;
+ p_Scheme->keyExtractAndHashParams.numOfUsedDflts = FM_PCD_KG_NUM_OF_DEFAULT_GROUPS;
+ for (j=0; j<FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; j++)
+ {
+ p_Scheme->keyExtractAndHashParams.dflts[j].type = (e_FmPcdKgKnownFieldsDfltTypes)j; /* all types */
+ p_Scheme->keyExtractAndHashParams.dflts[j].dfltSelect = e_FM_PCD_KG_DFLT_GBL_0;
+ }
+}
+
+static t_Error IpReassemblyStats(t_FmPcdManip *p_Manip, t_FmPcdManipReassemIpStats *p_Stats)
+{
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_Stats);
+ ASSERT_COND(p_Manip->ipReassmParams.p_IpReassCommonTbl);
+
+ p_Stats->timeout = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalTimeOutCounter);
+ p_Stats->rfdPoolBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalRfdPoolBusyCounter);
+ p_Stats->internalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalInternalBufferBusy);
+ p_Stats->externalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalExternalBufferBusy);
+ p_Stats->sgFragments = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalSgFragmentCounter);
+ p_Stats->dmaSemaphoreDepletion = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalDmaSemaphoreDepletionCounter);
+
+ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl)
+ {
+ p_Stats->specificHdrStatistics[0].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSuccessfullyReasmFramesCounter);
+ p_Stats->specificHdrStatistics[0].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalValidFragmentCounter);
+ p_Stats->specificHdrStatistics[0].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalProcessedFragCounter);
+ p_Stats->specificHdrStatistics[0].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMalformdFragCounter);
+ p_Stats->specificHdrStatistics[0].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSetBusyCounter);
+ p_Stats->specificHdrStatistics[0].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalDiscardedFragsCounter);
+ p_Stats->specificHdrStatistics[0].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMoreThan16FramesCounter);
+ }
+ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl)
+ {
+ p_Stats->specificHdrStatistics[1].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSuccessfullyReasmFramesCounter);
+ p_Stats->specificHdrStatistics[1].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalValidFragmentCounter);
+ p_Stats->specificHdrStatistics[1].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalProcessedFragCounter);
+ p_Stats->specificHdrStatistics[1].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMalformdFragCounter);
+ p_Stats->specificHdrStatistics[1].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSetBusyCounter);
+ p_Stats->specificHdrStatistics[1].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalDiscardedFragsCounter);
+ p_Stats->specificHdrStatistics[1].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMoreThan16FramesCounter);
+ }
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error IndxStats(t_FmPcdStatsParams *p_StatsParams,t_FmPcdManip *p_Manip,t_FmPcd *p_FmPcd)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ UNUSED(p_FmPcd);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_INDEXED_STATS;
+ if (p_StatsParams->type == e_FM_PCD_STATS_PER_FLOWID)
+ tmpReg32 |= (uint32_t)0x16 << 16;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return E_OK;
+}
+
+static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
+{
+ t_FmPcdManipHdrInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->u.byTemplate;
+ uint8_t tmpReg8 = 0xff;
+ t_AdOfTypeContLookup *p_Ad;
+ bool ipModify = FALSE;
+ uint32_t tmpReg32 = 0, tmpRegNia = 0;
+ uint16_t tmpReg16 = 0;
+ t_Error err = E_OK;
+ uint8_t extraAddedBytes = 0, blockSize = 0, extraAddedBytesAlignedToBlockSize = 0, log2Num = 0;
+ uint8_t *p_Template = NULL;
+
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_NULL_POINTER);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->insrt)
+ {
+ if ((!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp) ||
+ (!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterVlan))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : asking for header template modifications with no template for insertion (template size)"));
+
+ if (p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp && (p_InsrtByTemplate->size <= p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : size of template < ipOuterOffset"));
+
+ if (p_InsrtByTemplate->size > 128)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size of header template for insertion can not be more than 128"));
+
+ if (p_InsrtByTemplate->size)
+ {
+ p_Manip->p_Template = (uint8_t *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ p_InsrtByTemplate->size,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if(!p_Manip->p_Template)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->p_Template) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 |= (uint32_t)p_InsrtByTemplate->size << 24;
+ *(uint32_t *)&p_Ad->matchTblPtr = tmpReg32;
+ }
+
+ tmpReg32 = 0;
+
+ p_Template = (uint8_t *)XX_Malloc(p_InsrtByTemplate->size * sizeof(uint8_t));
+
+ if (!p_Template)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("XX_Malloc allocation FAILED"));
+
+ memcpy(p_Template, p_InsrtByTemplate->hdrTemplate, p_InsrtByTemplate->size * sizeof(uint8_t));
+
+
+ if (p_InsrtByTemplate->modifyOuterIp)
+ {
+ ipModify = TRUE;
+
+ tmpReg8 = (uint8_t)p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset];
+
+ if((tmpReg8 & 0xf0) == 0x40)
+ tmpReg8 = 4;
+ else if((tmpReg8 & 0xf0) == 0x60)
+ tmpReg8 = 6;
+ else
+ tmpReg8 = 0xff;
+
+ if (tmpReg8 != 0xff)
+ {
+ if(p_InsrtByTemplate->modifyOuterIpParams.dscpEcn & 0xff00)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IPV4 present in header template, dscpEcn has to be only 1 byte"));
+ if(p_InsrtByTemplate->modifyOuterIpParams.recalculateLength)
+ {
+
+ if((p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize) > 255)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("extra Byte added can not be more than 256 bytes"));
+ extraAddedBytes = (uint8_t) (p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize);
+ blockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.blockSize;
+ extraAddedBytesAlignedToBlockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize;
+ /*IP header template - IP totalLength -
+ (1 byte) extraByteForIp = headerTemplateSize - ipOffset + insertedBytesAfterThisStage ,
+ in the case of SEC insertedBytesAfterThisStage - SEC trailer (21/31) + header(13)
+ second byte - extraByteForIp = headerTemplate - ipOffset + insertedBytesAfterThisStage*/
+ }
+ if (blockSize)
+ {
+ if (!POWER_OF_2(blockSize))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("inputFrmPaddingUpToBlockSize has to be power of 2"));
+ }
+
+ }
+ if (tmpReg8 == 4)
+ {
+ if ((IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IP present in header template, user asked for IP modifications but ipOffset + ipTotalLengthFieldOffset in header template bigger than template size"));
+
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn;
+
+ if (blockSize)
+ blockSize -= 1;
+
+ if ((p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes) > 255)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes has to be less than 255"));
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize;// IPV6 - in AD instead of SEQ IND
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);// for IPV6 decrement additional 40 bytes of IPV6 heade size
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize;
+
+
+
+ /*IP header template - relevant only for ipv4 CheckSum = 0*/
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00;
+
+
+ /*UDP checksum has to be 0*/
+ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent)
+ {
+ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template"));
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00;
+
+ }
+
+ if (p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId > 7)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("ipIdentGenId has to be one out of 8 sequence number generators (0 - 7) for IP identification field"));
+
+ tmpRegNia |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId<<24;
+ }
+ else if (tmpReg8 == 6)
+ {
+ /*TODO - add check for maximum value of blockSize;*/
+ if (blockSize)
+ LOG2(blockSize, log2Num);
+ tmpRegNia |= (uint32_t)log2Num << 24;
+
+ // for IPV6 decrement additional 40 bytes of IPV6 heade size - because IPV6 header size is not included in payloadLength
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes - 40);
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize;
+ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent)
+ {
+ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template"));
+ if (p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_NEXT_HEADER_OFFSET_FROM_IP] != 0x88)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("OUr suppport is only IPv6/UDPLite"));
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP + 1] = 0x08;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00;
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("IP version supported only IPV4"));
+ }
+
+ tmpReg32 = tmpReg16 = tmpReg8 = 0;
+ /*TODO - check it*/
+ if (p_InsrtByTemplate->modifyOuterVlan)
+ {
+ if (p_InsrtByTemplate->modifyOuterVlanParams.vpri & ~0x07)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but VPRI more than 3 bits"));
+
+ memcpy(&tmpReg16, &p_Template[VLAN_TAG_FIELD_OFFSET_FROM_ETH], 2*(sizeof(uint8_t)));
+ if ((tmpReg16 != 0x9100) && (tmpReg16!= 0x9200) && (tmpReg16 != 0x8100))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but Tag Protocol identifier is not VLAN "));
+
+ memcpy(&tmpReg8, &p_Template[14],1*(sizeof(uint8_t)));
+ tmpReg8 &= 0x1f;
+ tmpReg8 |= (uint8_t)(p_InsrtByTemplate->modifyOuterVlanParams.vpri << 5);
+
+ p_Template[14] = tmpReg8;
+ }
+
+ Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size);
+
+ XX_Free(p_Template);
+ }
+
+ tmpReg32 = 0;
+ if (p_Manip->h_Frag)
+ {
+ tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16;
+ }
+ else
+ tmpReg32 = 0xffff0000;
+
+ if (ipModify)
+ tmpReg32 |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset << 8;
+ else
+ tmpReg32 |= (uint32_t)0x0000ff00;
+
+ tmpReg32 |= (uint32_t)HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32;
+
+ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ *(uint32_t *)&p_Ad->ccAdBase = tmpRegNia;
+
+ return err;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error IpFragmentationStats(t_FmPcdManip *p_Manip, t_FmPcdManipFragIpStats *p_Stats)
+{
+ t_AdOfTypeContLookup *p_Ad;
+
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_Stats);
+ ASSERT_COND(p_Manip->h_Ad);
+ ASSERT_COND(p_Manip->ipFragParams.p_Frag);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ p_Stats->totalFrames = GET_UINT32(p_Ad->gmask);
+ p_Stats->fragmentedFrames = GET_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase) & 0x00ffffff;
+ p_Stats->generatedFragments = GET_UINT32(p_Manip->ipFragParams.p_Frag->matchTblPtr);
+
+ return E_OK;
+}
+
+static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, t_FmPcdManip *p_Manip)
+{
+ uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0;
+ t_FmPcd *p_FmPcd;
+#if (DPAA_VERSION == 10)
+ t_Error err = E_OK;
+#endif /* (DPAA_VERSION == 10) */
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, E_INVALID_VALUE);
+
+ p_FmPcd = p_Manip->h_FmPcd;
+ /* Allocation of fragmentation Action Descriptor */
+ p_Manip->ipFragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipFragParams.p_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Fragmentation table descriptor"));
+ IOMemSet32( p_Manip->ipFragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Prepare the third Ad register (pcAndOffsets)- OperationCode */
+ pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION;
+
+ /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/
+ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE;
+ ccAdBaseReg |= (p_ManipParams->dontFragAction << FM_PCD_MANIP_IP_FRAG_DF_SHIFT);
+
+
+ /* Set Scatter/Gather BPid */
+ if (p_ManipParams->sgBpidEn)
+ {
+ ccAdBaseReg |= FM_PCD_MANIP_IP_FRAG_SG_BDID_EN;
+ pcAndOffsetsReg |= ((p_ManipParams->sgBpid << FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT) & FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK);
+ }
+
+ /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */
+ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)) - p_FmPcd->physicalMuramBase);
+#if (DPAA_VERSION == 10)
+ gmaskReg |= p_ManipParams->scratchBpid << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID;
+#else
+ gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID;
+#endif /* (DPAA_VERSION == 10) */
+
+ /* Set all Ad registers */
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg);
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase, ccAdBaseReg);
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->gmask, gmaskReg);
+
+ /* Saves user's fragmentation manipulation parameters */
+ p_Manip->frag = TRUE;
+ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation;
+
+#if (DPAA_VERSION == 10)
+ p_Manip->ipFragParams.scratchBpid = p_ManipParams->scratchBpid;
+
+ /* scratch buffer pool initialization */
+ if ((err = FmPcdFragHcScratchPoolFill((t_Handle)p_FmPcd, p_ManipParams->scratchBpid)) != E_OK)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag);
+ p_Manip->ipFragParams.p_Frag = NULL;
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+#endif /* (DPAA_VERSION == 10) */
+
+ return E_OK;
+}
+
+static t_Error IPManip(t_FmPcdManip *p_Manip)
+{
+ t_Error err = E_OK;
+ t_FmPcd *p_FmPcd;
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0, tmpRegNia = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ p_FmPcd = p_Manip->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = FM_PCD_MANIP_IP_NO_FRAGMENTATION;
+ if (p_Manip->frag == TRUE)
+ {
+ tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->ipFragParams.p_Frag) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation << FM_PCD_MANIP_IP_MTU_SHIFT;
+ }
+
+ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= HMAN_OC_IP_MANIP;
+
+#if (DPAA_VERSION >= 11)
+ tmpRegNia |= FM_PCD_MANIP_IP_CNIA;
+#endif /* (DPAA_VERSION >= 11) */
+
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+ WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia);
+ WRITE_UINT32(p_Ad->gmask, 0); /* Total frame counter - MUST be initialized to zero.*/
+
+ return err;
+}
+
+static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams,
+ t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPcdManipSpecialOffloadIPSecParams *p_IPSecParams;
+ t_Error err = E_OK;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE);
+
+ p_IPSecParams = &p_ManipParams->u.specialOffload.u.ipsec;
+
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpHdrLen ||
+ p_IPSecParams->decryption, E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion ||
+ !p_IPSecParams->decryption, E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion ||
+ p_IPSecParams->outerIPHdrLen, E_INVALID_VALUE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= (p_IPSecParams->decryption)?FM_PCD_MANIP_IPSEC_DEC:0;
+ tmpReg32 |= (p_IPSecParams->ecnCopy)?FM_PCD_MANIP_IPSEC_ECN_EN:0;
+ tmpReg32 |= (p_IPSecParams->dscpCopy)?FM_PCD_MANIP_IPSEC_DSCP_EN:0;
+ tmpReg32 |= (p_IPSecParams->variableIpHdrLen)?FM_PCD_MANIP_IPSEC_VIPL_EN:0;
+ tmpReg32 |= (p_IPSecParams->variableIpVersion)?FM_PCD_MANIP_IPSEC_VIPV_EN:0;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ tmpReg32 = HMAN_OC_IPSEC_MANIP;
+ tmpReg32 |= p_IPSecParams->outerIPHdrLen << FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT;
+ if (p_ManipParams->h_NextManip)
+ {
+ WRITE_UINT32(p_Ad->matchTblPtr,
+ (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)-
+ (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4);
+
+ tmpReg32 |= FM_PCD_MANIP_IPSEC_NADEN;
+ }
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ return err;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CheckStatsParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdStatsParams *p_StatsParams)
+{
+
+ switch (p_StatsParams->type)
+ {
+ case (e_FM_PCD_STATS_PER_FLOWID):
+ p_Manip->opcode = HMAN_OC_CAPWAP_INDEXED_STATS;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type"));
+ }
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, bool stats)
+{
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+
+ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip));
+ if (!p_Manip)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_Manip, 0, sizeof(t_FmPcdManip));
+
+ p_Manip->type = ((t_FmPcdManipParams *)p_Params)->type;
+ memcpy((uint8_t*)&p_Manip->manipParams, p_Params, sizeof(p_Manip->manipParams));
+
+ if (!stats)
+ err = CheckManipParamsAndSetType(p_Manip, (t_FmPcdManipParams *)p_Params);
+#ifdef FM_CAPWAP_SUPPORT
+ else
+ err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params);
+#else
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Statistics node!"));
+ return NULL;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("INVALID HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (p_Manip->opcode != HMAN_OC_IP_REASSEMBLY)
+ {
+ /* In Case of IP reassembly manipulation the IPv4/IPv6 reassembly action descriptor will
+ be defines later on */
+ if (p_Manip->muramAllocate)
+ {
+ p_Manip->h_Ad = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation action descriptor"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ else
+ {
+ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ }
+ }
+
+ p_Manip->h_FmPcd = h_FmPcd;
+
+ return p_Manip;
+}
+
+static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(t_FmPcdManip *p_CrntMdfManip,
+ t_List *h_NodesLst)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcNode *p_NodePtrOnCurrentMdfManip = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfManip->nodesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_NodePtrOnCurrentMdfManip = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_NodePtrOnCurrentMdfManip);
+
+ /* Search in the previous node which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_NodePtrOnCurrentMdfManip->numOfKeys + 1; i++)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.h_Manip == (t_Handle)p_CrntMdfManip)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj)
+ p_AdTablePtOnCrntCurrentMdfNode =
+ p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd;
+ else
+ p_AdTablePtOnCrntCurrentMdfNode =
+ PTR_MOVE(p_NodePtrOnCurrentMdfManip->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode;
+ EnqueueNodeInfoToRelevantLst(h_NodesLst, &ccNodeInfo, NULL);
+ }
+ }
+ }
+
+ ASSERT_COND(i != p_NodePtrOnCurrentMdfManip->numOfKeys);
+ }
+}
+
+static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, t_FmPcd *p_FmPcd)
+{
+ t_Error err;
+
+ /* Copy the HMTD */
+ IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16);
+ /* Replace the HMCT table pointer */
+ WRITE_UINT32(((t_Hmtd *)p_Dest)->hmcdBasePtr,
+ (uint32_t)(XX_VirtToPhys(p_Hmcd) - ((t_FmPcd*)p_FmPcd)->physicalMuramBase));
+ /* Call Host Command to replace HMTD by a new HMTD */
+ err = FmHcPcdCcDoDynamicChange(p_FmPcd->h_Hc,
+ (uint32_t)(XX_VirtToPhys(p_Src) - p_FmPcd->physicalMuramBase),
+ (uint32_t)(XX_VirtToPhys(p_Dest) - p_FmPcd->physicalMuramBase));
+ if (err)
+ REPORT_ERROR(MINOR, err, ("Failed in dynamic manip change, continued to the rest of the owners."));
+}
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Error FmPcdManipUpdate(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ int level,
+ t_Handle h_FmTree,
+ bool modify)
+{
+ t_Error err;
+
+ if (!modify)
+ err = FmPcdManipInitUpdate(h_FmPcd, h_PcdParams, h_FmPort, h_Manip, h_Ad, validate, level, h_FmTree);
+ else
+ err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree);
+
+ return err;
+}
+
+uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(h_Manip);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ return UPDATE_NIA_ENQ_WITHOUT_DMA;
+ default:
+ return 0;
+ }
+}
+
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add)
+{
+
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock);
+ if (add)
+ ((t_FmPcdManip *)h_Manip)->owner++;
+ else
+ {
+ ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner);
+ ((t_FmPcdManip *)h_Manip)->owner--;
+ }
+ XX_UnlockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock, intFlags);
+}
+
+t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip)
+{
+ ASSERT_COND(h_Manip);
+ return &((t_FmPcdManip *)h_Manip)->nodesLst;
+}
+
+t_List *FmPcdManipGetSpinlock(t_Handle h_Manip)
+{
+ ASSERT_COND(h_Manip);
+ return ((t_FmPcdManip *)h_Manip)->h_Spinlock;
+}
+
+t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, uint32_t *requiredAction)
+{
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+ bool pointFromCc = TRUE;
+
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams->h_Manip, E_NULL_POINTER);
+
+ p_Manip = (t_FmPcdManip *)(p_FmPcdCcNextEngineParams->h_Manip);
+ *requiredAction = 0;
+
+ while (p_Manip)
+ {
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE"));
+ if (p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ p_Manip->cnia = TRUE;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA;
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) &&
+ !p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE with fqidForCtrlFlow FALSE"));
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_CC) &&
+ (FmPcdCcGetParseCode(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) != CC_PC_GENERIC_IC_HASH_INDEXED))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation next engine has to be CC and action = e_FM_PCD_ACTION_INDEXED_LOOKUP"));
+ err = UpdateManipIc(p_FmPcdCcNextEngineParams->h_Manip, FmPcdCcGetOffset(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode));
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA;
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+#if (DPAA_VERSION == 10)
+ if (!(p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_DONE))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE"));
+#else
+ if (!((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_DONE) ||
+ (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_PLCR)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("For this type of header manipulation has to be nextEngine "
+ "e_FM_PCD_DONE or e_FM_PCD_PLCR"));
+#endif /* (DPAA_VERSION == 10) */
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_IP_REASSEMBLY):
+ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE"));
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_IPSEC_MANIP):
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC):
+ if (( p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) && MANIP_IS_CASCADE_NEXT(p_Manip))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't have a cascaded manipulation when and Next Engine is CC"));
+ if (!MANIP_IS_FIRST(p_Manip) && pointFromCc)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_Manip is already used and may not be shared (no sharing of non-head manip nodes)"));
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("invalid type of header manipulation for this state"));
+ }
+ p_Manip = p_Manip->h_NextManip;
+ pointFromCc = FALSE;
+ }
+ return E_OK;
+}
+
+
+t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcNode, E_INVALID_HANDLE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type statistics flowId if exist has to be pointed by all numOfKeys"));
+ break;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type remove DTLS if exist has to be pointed by all numOfKeys"));
+ err = UpdateManipIc(h_Manip, FmPcdCcGetOffset(h_FmPcdCcNode));
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_Handle p_Ad,
+ t_Handle *p_AdNewPtr)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+
+ /* This routine creates a Manip AD and can return in "p_AdNewPtr"
+ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */
+
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_CcNextEngineParams);
+ ASSERT_COND(p_Ad);
+ ASSERT_COND(p_AdNewPtr);
+
+ FmPcdManipUpdateOwner(h_Manip, TRUE);
+
+ /* According to "type", either build & initialize a new AD (p_AdNew) or initialize
+ * p_Ad ( the AD in the match table) and set p_AdNew = NULL. */
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IPSEC_MANIP):
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_DONE) &&
+ (!p_CcNextEngineParams->params.enqueueParams.overrideFqid))
+ {
+ memcpy((uint8_t *)p_Ad, (uint8_t *)p_Manip->h_Ad, sizeof(t_AdOfTypeContLookup));
+#if (DPAA_VERSION >= 11)
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase,
+ GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) & ~FM_PCD_MANIP_IP_CNIA);
+#endif /* (DPAA_VERSION >= 11) */
+ *p_AdNewPtr = NULL;
+ }
+ else
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IP_REASSEMBLY):
+ if (FmPcdManipIpReassmIsIpv6Hdr(p_Manip))
+ {
+ if (!p_Manip->ipReassmParams.ipv6Assigned)
+ {
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv6Ad;
+ p_Manip->ipReassmParams.ipv6Assigned = TRUE;
+ FmPcdManipUpdateOwner(h_Manip, FALSE);
+ }
+ else
+ {
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad;
+ p_Manip->ipReassmParams.ipv6Assigned = FALSE;
+ }
+ }
+ else
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad;
+ memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, sizeof(t_AdOfTypeContLookup));
+ *p_AdNewPtr = NULL;
+ break;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->fqid, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->fqid);
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->plcrProfile, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->plcrProfile);
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->nia, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->nia);
+ *p_AdNewPtr = NULL;
+ break;
+ case (HMAN_OC):
+ /* Allocate and initialize HMTD */
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ default:
+ break;
+ }
+}
+
+void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNewPtr, uint32_t adTableOffset)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ /* This routine creates a Manip AD and can return in "p_AdNewPtr"
+ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */
+ ASSERT_COND(p_Manip);
+
+ FmPcdManipUpdateOwner(h_Manip, TRUE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->ccAdBase);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->matchTblPtr, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->matchTblPtr);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->pcAndOffsets);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->gmask, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->gmask);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, (GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) | adTableOffset));
+ *p_AdNewPtr = NULL;
+ break;
+
+ case (HMAN_OC):
+ /* Initialize HMTD within the match table*/
+ IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+ /* copy the existing HMTD */ /* ask Alla - memcpy??? */
+ memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd));
+ /* update NADEN to be "1"*/
+ WRITE_UINT16(((t_Hmtd *)p_Ad)->cfg,
+ (uint16_t)(GET_UINT16(((t_Hmtd *)p_Ad)->cfg) | HMTD_CFG_NEXT_AD_EN));
+ /* update next action descriptor */
+ WRITE_UINT16(((t_Hmtd *)p_Ad)->nextAdIdx, (uint16_t)(adTableOffset >> 4));
+ /* mark that Manip's HMTD is not used */
+ *p_AdNewPtr = NULL;
+ break;
+
+ default:
+ break;
+ }
+}
+
+t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_FmPcdKgSchemeParams *p_SchemeParams = NULL;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_NetEnv);
+ ASSERT_COND(p_Manip);
+
+ /* scheme was already build, no need to check for IPv6 */
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ return E_OK;
+
+ p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams));
+ if (!p_SchemeParams)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation failed for scheme"));
+
+ /* Configures the IPv4 or IPv6 scheme*/
+ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams));
+ p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv;
+ p_SchemeParams->id.relativeSchemeId =
+ (uint8_t)((isIpv4 == TRUE) ?
+ p_Manip->ipReassmParams.relativeSchemeId[0] :
+ p_Manip->ipReassmParams.relativeSchemeId[1]);
+ p_SchemeParams->schemeCounter.update = TRUE;
+#if (DPAA_VERSION >= 11)
+ p_SchemeParams->alwaysDirect = TRUE;
+ p_SchemeParams->bypassFqidGeneration = TRUE;
+#else
+ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids = 1;
+ p_SchemeParams->baseFqid = 0xFFFFFF; /*TODO- baseFqid*/
+#endif /* (DPAA_VERSION >= 11) */
+
+ setReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, isIpv4, groupId);
+
+ /* Sets the new scheme */
+ if (isIpv4)
+ p_Manip->ipReassmParams.h_Ipv4Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams);
+ else
+ p_Manip->ipReassmParams.h_Ipv6Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams);
+
+ XX_Free(p_SchemeParams);
+
+ return E_OK;
+}
+
+t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(p_Manip);
+
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv4Scheme);
+
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv6Scheme);
+
+ return E_OK;
+}
+
+bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(p_Manip);
+
+ return (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6);
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FmPcdManipApplSpecificBuild(void)
+{
+ t_FmPcdManip *p_Manip;
+
+ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip));
+ if (!p_Manip)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_Manip, 0, sizeof(t_FmPcdManip));
+
+ p_Manip->opcode = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX;
+ p_Manip->muramAllocate = FALSE;
+
+ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor"));
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+
+ /*treatFdStatusFieldsAsErrors = TRUE hardcoded - assumption its always come after CAAM*/
+ /*Application specific = type of flowId index, move internal frame header from data to IC,
+ SEC errors check*/
+ if (MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE)!= E_OK)
+ {
+ XX_Free(p_Manip->h_Ad);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ return p_Manip;
+}
+
+bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ ASSERT_COND(h_Manip);
+
+ return (bool)((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST) ? TRUE : FALSE);
+}
+#endif /* FM_CAPWAP_SUPPORT */
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_ManipParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL);
+ SANITY_CHECK_RETURN_VALUE(p_ManipParams,E_INVALID_HANDLE,NULL);
+
+ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_ManipParams, FALSE);
+ if (!p_Manip)
+ return NULL;
+
+ if (((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) ||
+ (p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION) ||
+ (p_Manip->opcode == HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX) ||
+ (p_Manip->opcode == HMAN_OC) ||
+ (p_Manip->opcode == HMAN_OC_IPSEC_MANIP)) &&
+ (!FmPcdIsAdvancedOffloadSupported(p_FmPcd)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ p_Manip->h_Spinlock = XX_InitSpinlock();
+ if (!p_Manip->h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ INIT_LIST(&p_Manip->nodesLst);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_IP_REASSEMBLY):
+ /* IpReassembly */
+ err = IpReassembly(&p_ManipParams->u.reassem, p_Manip);
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ /* IpFragmentation */
+ err = IpFragmentation(&p_ManipParams->u.frag.u.ipFrag ,p_Manip);
+ if (err)
+ break;
+ err = IPManip(p_Manip);
+ break;
+ case (HMAN_OC_IPSEC_MANIP) :
+ err = IPSecManip(p_ManipParams, p_Manip);
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ /* HmanType1 */
+ err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->u.hdr.rmvParams, p_Manip);
+ break;
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.u.capwapFragParams,
+ p_Manip,
+ p_FmPcd,
+ p_ManipParams->fragOrReasmParams.sgBpid);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ if (p_Manip->insrt)
+ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ /* HmanType2 + if user asked only for fragmentation still need to allocate HmanType2 */
+ err = InsrtHdrByTempl(&p_ManipParams->u.hdr.insrtParams, p_Manip, p_FmPcd);
+ break;
+ case (HMAN_OC_CAPWAP_REASSEMBLY):
+ err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.u.capwapReasmParams,
+ p_Manip,
+ p_FmPcd,
+ p_ManipParams->fragOrReasmParams.sgBpid);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ if (p_Manip->rmv)
+ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ /*CAPWAP decapsulation + if user asked only for reassembly still need to allocate CAPWAP decapsulation*/
+ err = CapwapRmvDtlsHdr(p_FmPcd, p_Manip);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ /*Application Specific type 1*/
+ err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE);
+ break;
+ case (HMAN_OC):
+ /* New Manip */
+ err = CreateManipActionNew(p_Manip, p_ManipParams);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (p_ManipParams->h_NextManip)
+ {
+ /* in the check routine we've verified that h_NextManip has no owners
+ * and that only supported types are allowed. */
+ p_Manip->h_NextManip = p_ManipParams->h_NextManip;
+ /* save a "prev" pointer in h_NextManip */
+ MANIP_SET_PREV(p_Manip->h_NextManip, p_Manip);
+ FmPcdManipUpdateOwner(p_Manip->h_NextManip, TRUE);
+ }
+
+ return p_Manip;
+}
+
+t_Error FM_PCD_ManipNodeReplace(t_Handle h_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip, *p_FirstManip;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Manip->h_FmPcd);
+ t_Error err;
+ uint8_t *p_WholeHmct = NULL, *p_ShadowHmct = NULL, *p_Hmtd = NULL;
+ t_List lstOfNodeshichPointsOnCrntMdfManip, *p_Pos;
+ t_CcNodeInformation *p_CcNodeInfo;
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE);
+
+ INIT_LIST(&lstOfNodeshichPointsOnCrntMdfManip);
+
+ if ((p_ManipParams->type != e_FM_PCD_MANIP_HDR) ||
+ (p_Manip->type != e_FM_PCD_MANIP_HDR))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("FM_PCD_ManipNodeReplace Functionality supported only for Header Manipulation."));
+
+ ASSERT_COND(p_Manip->opcode == HMAN_OC);
+ ASSERT_COND(p_Manip->manipParams.h_NextManip == p_Manip->h_NextManip);
+ memcpy((uint8_t*)&p_Manip->manipParams, p_ManipParams, sizeof(p_Manip->manipParams));
+ p_Manip->manipParams.h_NextManip = p_Manip->h_NextManip;
+
+ /* The replacement of the HdrManip depends on the node type.*/
+ /*
+ * (1) If this is an independent node, all its owners should be updated.
+ *
+ * (2) If it is the head of a cascaded chain (it does not have a "prev" but
+ * it has a "next" and it has a "cascaded-next" indication), the next
+ * node remains unchanged, and the behavior is as in (1).
+ *
+ * (3) If it is not the head, but a part of a cascaded chain, in can be
+ * also replaced as a regular node with just one owner.
+ *
+ * (4) If it is a part of a chain implemented as a unified table, the
+ * whole table is replaced and the owners of the head node must be updated.
+ *
+ */
+ /* lock shadow */
+ if (!p_FmPcd->p_CcShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ return ERROR_CODE(E_BUSY);
+
+ /* this routine creates a new manip action in the CC Shadow. */
+ err = CreateManipActionShadow(p_Manip, p_ManipParams);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* If the owners list is empty (these are NOT the "owners" counter, but pointers from CC)
+ * replace only HMTD and no lcok is required. Otherwise
+ * lock the whole PCD
+ * In case 4 MANIP_IS_UNIFIED_NON_FIRST(p_Manip) - Use the head node instead. */
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ p_ShadowHmct = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16);
+
+ p_FirstManip = (t_FmPcdManip*)GetManipInfo(p_Manip, e_MANIP_HANDLER_TABLE_OWNER);
+ ASSERT_COND(p_FirstManip);
+
+ if (!LIST_IsEmpty(&p_FirstManip->nodesLst))
+ UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(p_FirstManip, &lstOfNodeshichPointsOnCrntMdfManip);
+
+ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD);
+ ASSERT_COND(p_Hmtd);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+
+ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+ }
+
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* re-build the HMCT n the original location */
+ err = CreateManipActionBackToOrig(p_Manip, p_ManipParams);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD);
+ ASSERT_COND(p_Hmtd);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_WholeHmct,((t_FmPcd*)p_Manip->h_FmPcd));
+
+ /* If LIST > 0, create a list of p_Ad's that point to the HMCT. Join also t_HMTD to this list.
+ * For each p_Hmct (from list+fixed):
+ * call Host Command to replace HMTD by a new one */
+ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_WholeHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+ }
+
+
+ ReleaseLst(&lstOfNodeshichPointsOnCrntMdfManip);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ /* unlock shadow */
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+
+ if (p_Manip->owner)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This manipulation node not be removed because this node is occupied, first - unbind this node "));
+
+ if (p_Manip->h_NextManip)
+ {
+ MANIP_SET_PREV(p_Manip->h_NextManip, NULL);
+ FmPcdManipUpdateOwner(p_Manip->h_NextManip, FALSE);
+ }
+
+ if (p_Manip->p_Hmct && MANIP_IS_UNIFIED_FIRST(p_Manip))
+ FM_MURAM_FreeMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, p_Manip->p_Hmct);
+
+ if (p_Manip->h_Spinlock)
+ {
+ XX_FreeSpinlock(p_Manip->h_Spinlock);
+ p_Manip->h_Spinlock = NULL;
+ }
+
+ ReleaseManipHandler(p_Manip, p_Manip->h_FmPcd);
+
+ XX_Free(h_ManipNode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdManipStats, E_NULL_POINTER);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_IP_REASSEMBLY):
+ return IpReassemblyStats(p_Manip, &p_FmPcdManipStats->u.reassem.u.ipReassem);
+ case (HMAN_OC_IP_FRAGMENTATION):
+ return IpFragmentationStats(p_Manip, &p_FmPcdManipStats->u.frag.u.ipFrag);
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("no statistics to this type of manip"));
+ }
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_StatsParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL);
+ SANITY_CHECK_RETURN_VALUE(p_StatsParams,E_INVALID_HANDLE,NULL);
+
+ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_StatsParams, TRUE);
+ if (!p_Manip)
+ return NULL;
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ /* Indexed statistics */
+ err = IndxStats(p_StatsParams, p_Manip, p_FmPcd);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED Statistics type"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ return p_Manip;
+}
+#endif /* FM_CAPWAP_SUPPORT */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h
new file mode 100644
index 0000000..390ca6e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_manip.h
+
+ @Description FM PCD manip...
+*//***************************************************************************/
+#ifndef __FM_MANIP_H
+#define __FM_MANIP_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_cc.h"
+
+
+/***********************************************************************/
+/* Header manipulations defines */
+/***********************************************************************/
+
+#define NUM_OF_SCRATCH_POOL_BUFFERS 1000 /*TODO - Change it!!*/
+
+#define HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR 0x2e
+#define HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER 0x31
+#define HMAN_OC_CAPWAP_FRAGMENTATION 0x33
+#define HMAN_OC_IP_MANIP 0x34
+#define HMAN_OC_IP_FRAGMENTATION 0x74
+#define HMAN_OC_IP_REASSEMBLY 0xB4
+#define HMAN_OC_IPSEC_MANIP 0xF4
+#define HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX 0x2f
+#define HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST 0x30
+#define HMAN_OC_CAPWAP_REASSEMBLY 0x11 /* dummy */
+#define HMAN_OC_CAPWAP_INDEXED_STATS 0x32 /* dummy */
+#define HMAN_OC 0x35
+
+#define HMAN_RMV_HDR 0x80000000
+#define HMAN_INSRT_INT_FRM_HDR 0x40000000
+
+#define UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP 6
+#define UDP_CHECKSUM_FIELD_SIZE 2
+#define UDP_LENGTH_FIELD_OFFSET_FROM_UDP 4
+
+#define IPv4_DSCECN_FIELD_OFFSET_FROM_IP 1
+#define IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP 2
+#define IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP 10
+#define VLAN_TAG_FIELD_OFFSET_FROM_ETH 12
+#define IPv4_ID_FIELD_OFFSET_FROM_IP 4
+
+#define IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP 4
+#define IPv6_NEXT_HEADER_OFFSET_FROM_IP 6
+
+#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE 0x80
+#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN 8
+#define FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE 32
+#define FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE 4
+#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE 8
+
+
+#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES 0x40000000
+#define FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG 0x10000000
+#define FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS 0x08000000
+#define FM_PCD_MANIP_CAPWAP_REASM_PR_COPY 0x00800000
+
+#define FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN 0x80000000
+
+#define FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE 4
+#define FM_PCD_MANIP_INDEXED_STATS_CNIA 0x20000000
+#define FM_PCD_MANIP_INDEXED_STATS_DPD 0x10000000
+
+#define FM_PCD_MANIP_IP_REASM_TABLE_SIZE 0x40
+#define FM_PCD_MANIP_IP_REASM_TABLE_ALIGN 8
+
+#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE 64
+#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN 8
+#define FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES 0x80000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_ENABLE 0x40000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_MASK 0xFF000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_SHIFT 24
+#define FM_PCD_MANIP_IP_REASM_LIODN_MASK 0x0000003F
+#define FM_PCD_MANIP_IP_REASM_LIODN_SHIFT 56
+#define FM_PCD_MANIP_IP_REASM_ELIODN_MASK 0x000003c0
+#define FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT 38
+#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_MASK 0x000000FF
+#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT 24
+
+#define FM_PCD_MANIP_IP_MTU_SHIFT 16
+#define FM_PCD_MANIP_IP_NO_FRAGMENTATION 0xFFFF0000
+#define FM_PCD_MANIP_IP_CNIA 0x20000000
+
+#define FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH 1024
+#define FM_PCD_MANIP_IP_FRAG_DF_SHIFT 28
+#define FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID 24
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_EN 0x08000000
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK 0xFF000000
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT 24
+
+#define FM_PCD_MANIP_IPSEC_DEC 0x10000000
+#define FM_PCD_MANIP_IPSEC_VIPV_EN 0x08000000
+#define FM_PCD_MANIP_IPSEC_ECN_EN 0x04000000
+#define FM_PCD_MANIP_IPSEC_DSCP_EN 0x02000000
+#define FM_PCD_MANIP_IPSEC_VIPL_EN 0x01000000
+#define FM_PCD_MANIP_IPSEC_NADEN 0x20000000
+
+#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_MASK 0x00FF0000
+#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT 16
+
+#define e_FM_MANIP_IP_INDX 1
+
+#define HMCD_OPCODE_GENERIC_RMV 0x01
+#define HMCD_OPCODE_GENERIC_INSRT 0x02
+#define HMCD_OPCODE_GENERIC_REPLACE 0x05
+#define HMCD_OPCODE_L2_RMV 0x08
+#define HMCD_OPCODE_L2_INSRT 0x09
+#define HMCD_OPCODE_VLAN_PRI_UPDATE 0x0B
+#define HMCD_OPCODE_IPV4_UPDATE 0x0C
+#define HMCD_OPCODE_IPV6_UPDATE 0x10
+#define HMCD_OPCODE_TCP_UDP_UPDATE 0x0E
+#define HMCD_OPCODE_TCP_UDP_CHECKSUM 0x14
+#define HMCD_OPCODE_REPLACE_IP 0x12
+
+#define HMCD_DSCP_VALUES 64
+
+#define HMCD_BASIC_SIZE 4
+#define HMCD_PTR_SIZE 4
+#define HMCD_PARAM_SIZE 4
+#define HMCD_IPV4_ADDR_SIZE 4
+#define HMCD_IPV6_ADDR_SIZE 0x10
+
+#define HMCD_LAST 0x00800000
+
+#define HMCD_OC_SHIFT 24
+
+#define HMCD_RMV_OFFSET_SHIFT 0
+#define HMCD_RMV_SIZE_SHIFT 8
+
+#define HMCD_INSRT_OFFSET_SHIFT 0
+#define HMCD_INSRT_SIZE_SHIFT 8
+
+#define HMTD_CFG_TYPE 0x4000
+#define HMTD_CFG_EXT_HMCT 0x0080
+#define HMTD_CFG_PRS_AFTER_HM 0x0040
+#define HMTD_CFG_NEXT_AD_EN 0x0020
+
+#define HMCD_RMV_L2_ETHERNET 0
+#define HMCD_RMV_L2_STACKED_QTAGS 1
+#define HMCD_RMV_L2_ETHERNET_AND_MPLS 2
+#define HMCD_RMV_L2_MPLS 3
+
+#define HMCD_INSRT_L2_MPLS 0
+#define HMCD_INSRT_N_UPDATE_L2_MPLS 1
+#define HMCD_INSRT_L2_SIZE_SHIFT 24
+
+#define HMCD_L2_MODE_SHIFT 16
+
+#define HMCD_VLAN_PRI_REP_MODE_SHIFT 16
+#define HMCD_VLAN_PRI_UPDATE 0
+#define HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI 1
+
+#define HMCD_IPV4_UPDATE_TTL 0x00000001
+#define HMCD_IPV4_UPDATE_TOS 0x00000002
+#define HMCD_IPV4_UPDATE_DST 0x00000020
+#define HMCD_IPV4_UPDATE_SRC 0x00000040
+#define HMCD_IPV4_UPDATE_ID 0x00000080
+#define HMCD_IPV4_UPDATE_TOS_SHIFT 8
+
+#define HMCD_IPV6_UPDATE_HL 0x00000001
+#define HMCD_IPV6_UPDATE_TC 0x00000002
+#define HMCD_IPV6_UPDATE_DST 0x00000040
+#define HMCD_IPV6_UPDATE_SRC 0x00000080
+#define HMCD_IPV6_UPDATE_TC_SHIFT 8
+
+#define HMCD_TCP_UDP_UPDATE_DST 0x00004000
+#define HMCD_TCP_UDP_UPDATE_SRC 0x00008000
+#define HMCD_TCP_UDP_UPDATE_SRC_SHIFT 16
+
+#define HMCD_IP_REPLACE_REPLACE_IPV4 0x00000000
+#define HMCD_IP_REPLACE_REPLACE_IPV6 0x00010000
+#define HMCD_IP_REPLACE_TTL_HL 0x00200000
+#define HMCD_IP_REPLACE_ID 0x00400000
+
+#define HMCD_IP_REPLACE_L3HDRSIZE_SHIFT 24
+
+#define DSCP_TO_VLAN_TABLE_SIZE 32
+
+#define MANIP_GET_HMCT_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->tableSize)
+#define MANIP_GET_DATA_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->dataSize)
+
+#define MANIP_GET_HMCT_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Hmct)
+#define MANIP_GET_DATA_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Data)
+
+#define MANIP_SET_HMCT_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Hmct = h_NewPtr)
+#define MANIP_SET_DATA_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Data = h_NewPtr)
+
+#define MANIP_GET_HMTD_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->h_Ad)
+#define MANIP_DONT_REPARSE(h_Manip) (((t_FmPcdManip *)h_Manip)->dontParseAfterManip)
+#define MANIP_SET_PREV(h_Manip, h_Prev) (((t_FmPcdManip *)h_Manip)->h_PrevManip = h_Prev)
+#define MANIP_GET_OWNERS(h_Manip) (((t_FmPcdManip *)h_Manip)->owner)
+#define MANIP_GET_TYPE(h_Manip) (((t_FmPcdManip *)h_Manip)->type)
+#define MANIP_SET_UNIFIED_TBL_PTR_INDICATION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedTablePtr = TRUE)
+#define MANIP_GET_MURAM(h_Manip) (((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram)
+#define MANIP_FREE_HMTD(h_Manip) \
+ {if (((t_FmPcdManip *)h_Manip)->muramAllocate) \
+ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)h_Manip)->h_Ad);\
+ else \
+ XX_Free(((t_FmPcdManip *)h_Manip)->h_Ad); \
+ ((t_FmPcdManip *)h_Manip)->h_Ad = NULL; \
+ }
+/* position regarding Manip SW structure */
+#define MANIP_IS_FIRST(h_Manip) (!(((t_FmPcdManip *)h_Manip)->h_PrevManip))
+#define MANIP_IS_CASCADE_NEXT(h_Manip) (((t_FmPcdManip *)h_Manip)->cascadedNext)
+#define MANIP_IS_UNIFIED(h_Manip) (!(((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE))
+#define MANIP_IS_UNIFIED_NON_FIRST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID) || \
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST))
+#define MANIP_IS_UNIFIED_NON_LAST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ||\
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID))
+#define MANIP_IS_UNIFIED_FIRST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST)
+#define MANIP_IS_UNIFIED_LAST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST)
+
+#define MANIP_UPDATE_UNIFIED_POSITION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition = \
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)? \
+ e_MANIP_UNIFIED_LAST : e_MANIP_UNIFIED_MID)
+
+typedef enum e_ManipUnifiedPosition {
+ e_MANIP_UNIFIED_NONE = 0,
+ e_MANIP_UNIFIED_FIRST,
+ e_MANIP_UNIFIED_MID,
+ e_MANIP_UNIFIED_LAST
+} e_ManipUnifiedPosition;
+
+typedef enum e_ManipInfo {
+ e_MANIP_HMTD,
+ e_MANIP_HMCT,
+ e_MANIP_HANDLER_TABLE_OWNER
+}e_ManipInfo;
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct t_CapwapReasmPram {
+ volatile uint32_t mode;
+ volatile uint32_t autoLearnHashTblPtr;
+ volatile uint32_t intStatsTblPtr;
+ volatile uint32_t reasmFrmDescPoolTblPtr;
+ volatile uint32_t reasmFrmDescIndexPoolTblPtr;
+ volatile uint32_t timeOutTblPtr;
+ volatile uint32_t bufferPoolIdAndRisc1SetIndexes;
+ volatile uint32_t risc23SetIndexes;
+ volatile uint32_t risc4SetIndexesAndExtendedStatsTblPtr;
+ volatile uint32_t extendedStatsTblPtr;
+ volatile uint32_t expirationDelay;
+ volatile uint32_t totalProcessedFragCounter;
+ volatile uint32_t totalUnsuccessfulReasmFramesCounter;
+ volatile uint32_t totalDuplicatedFragCounter;
+ volatile uint32_t totalMalformdFragCounter;
+ volatile uint32_t totalTimeOutCounter;
+ volatile uint32_t totalSetBusyCounter;
+ volatile uint32_t totalRfdPoolBusyCounter;
+ volatile uint32_t totalDiscardedFragsCounter;
+ volatile uint32_t totalMoreThan16FramesCounter;
+ volatile uint32_t internalBufferBusy;
+ volatile uint32_t externalBufferBusy;
+ volatile uint32_t reserved1[4];
+} _PackedType t_CapwapReasmPram;
+
+typedef _Packed struct t_IpReassTbl {
+ volatile uint16_t waysNumAndSetSize;
+ volatile uint16_t autoLearnHashKeyMask;
+ volatile uint32_t ipReassCommonPrmTblPtr;
+ volatile uint32_t liodnAlAndAutoLearnHashTblPtrHi;
+ volatile uint32_t autoLearnHashTblPtrLow;
+ volatile uint32_t liodnSlAndAutoLearnSetLockTblPtrHi;
+ volatile uint32_t autoLearnSetLockTblPtrLow;
+ volatile uint16_t minFragSize;
+ volatile uint16_t reserved1;
+ volatile uint32_t totalSuccessfullyReasmFramesCounter;
+ volatile uint32_t totalValidFragmentCounter;
+ volatile uint32_t totalProcessedFragCounter;
+ volatile uint32_t totalMalformdFragCounter;
+ volatile uint32_t totalSetBusyCounter;
+ volatile uint32_t totalDiscardedFragsCounter;
+ volatile uint32_t totalMoreThan16FramesCounter;
+ volatile uint32_t reserved2[2];
+} _PackedType t_IpReassTbl;
+
+typedef _Packed struct t_IpReassCommonTbl {
+ volatile uint32_t timeoutModeAndFqid;
+ volatile uint32_t reassFrmDescIndexPoolTblPtr;
+ volatile uint32_t liodnAndReassFrmDescPoolPtrHi;
+ volatile uint32_t reassFrmDescPoolPtrLow;
+ volatile uint32_t timeOutTblPtr;
+ volatile uint32_t expirationDelay;
+ volatile uint32_t internalBufferManagement;
+ volatile uint32_t reserved2;
+ volatile uint32_t totalTimeOutCounter;
+ volatile uint32_t totalRfdPoolBusyCounter;
+ volatile uint32_t totalInternalBufferBusy;
+ volatile uint32_t totalExternalBufferBusy;
+ volatile uint32_t totalSgFragmentCounter;
+ volatile uint32_t totalDmaSemaphoreDepletionCounter;
+ volatile uint32_t reserved3[2];
+} _PackedType t_IpReassCommonTbl;
+
+typedef _Packed struct t_Hmtd {
+ volatile uint16_t cfg;
+ volatile uint8_t eliodnOffset;
+ volatile uint8_t extHmcdBasePtrHi;
+ volatile uint32_t hmcdBasePtr;
+ volatile uint16_t nextAdIdx;
+ volatile uint8_t res1;
+ volatile uint8_t opCode;
+ volatile uint32_t res2;
+} _PackedType t_Hmtd;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+typedef struct
+{
+ t_Handle p_AutoLearnHashTbl;
+ t_Handle p_ReassmFrmDescrPoolTbl;
+ t_Handle p_ReassmFrmDescrIndxPoolTbl;
+ t_Handle p_TimeOutTbl;
+ uint16_t maxNumFramesInProcess;
+ uint8_t numOfTasks;
+ //uint8_t poolId;
+ uint8_t prOffset;
+ uint16_t dataOffset;
+ uint8_t sgBpid;
+ uint8_t hwPortId;
+ uint32_t fqidForTimeOutFrames;
+ uint32_t timeoutRoutineRequestTime;
+ uint32_t bitFor1Micro;
+} t_FragParams;
+
+typedef struct
+{
+ t_AdOfTypeContLookup *p_Frag;
+#if (DPAA_VERSION == 10)
+ uint8_t scratchBpid;
+#endif /* (DPAA_VERSION == 10) */
+} t_IpFragParams;
+
+typedef struct t_IpReassmParams
+{
+ t_Handle h_Ipv4Ad;
+ t_Handle h_Ipv6Ad;
+ bool ipv6Assigned;
+ e_NetHeaderType hdr; /* Header selection */
+ t_IpReassCommonTbl *p_IpReassCommonTbl;
+ t_IpReassTbl *p_Ipv4ReassTbl;
+ t_IpReassTbl *p_Ipv6ReassTbl;
+ uintptr_t ipv4AutoLearnHashTblAddr;
+ uintptr_t ipv6AutoLearnHashTblAddr;
+ uintptr_t ipv4AutoLearnSetLockTblAddr;
+ uintptr_t ipv6AutoLearnSetLockTblAddr;
+ uintptr_t reassFrmDescrIndxPoolTblAddr;
+ uintptr_t reassFrmDescrPoolTblAddr;
+ uintptr_t timeOutTblAddr;
+ uintptr_t internalBufferPoolManagementIndexAddr;
+ uintptr_t internalBufferPoolAddr;
+ uint32_t maxNumFramesInProcess;
+ uint8_t sgBpid;
+ uint8_t dataMemId;
+ uint16_t dataLiodnOffset;
+ uint32_t fqidForTimeOutFrames;
+ e_FmPcdManipReassemTimeOutMode timeOutMode;
+ uint32_t timeoutThresholdForReassmProcess;
+ uint16_t minFragSize[2];
+ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2];
+ uint8_t relativeSchemeId[2];
+ t_Handle h_Ipv4Scheme;
+ t_Handle h_Ipv6Scheme;
+ uint32_t nonConsistentSpFqid;
+} t_IpReassmParams;
+
+
+typedef struct{
+ e_FmPcdManipType type;
+ t_FmPcdManipParams manipParams;
+ bool muramAllocate;
+ t_Handle h_Ad;
+ uint32_t opcode;
+ bool rmv;
+ bool insrt;
+ t_Handle h_NextManip;
+ t_Handle h_PrevManip;
+ /* HdrManip parameters*/
+ uint8_t *p_Hmct;
+ uint8_t *p_Data;
+ bool dontParseAfterManip;
+ bool fieldUpdate;
+ bool custom;
+ uint16_t tableSize;
+ uint8_t dataSize;
+ bool cascadedNext;
+ e_ManipUnifiedPosition unifiedPosition;
+ /* end HdrManip */
+ uint8_t *p_Template;
+ t_Handle h_Frag;
+ bool frag;
+ bool reassm;
+ uint16_t sizeForFragmentation;
+ uint8_t owner;
+ uint32_t updateParams;
+ uint32_t shadowUpdateParams;
+ t_FragParams fragParams;
+ union {
+ t_IpReassmParams ipReassmParams;
+ t_IpFragParams ipFragParams;
+ };
+ uint8_t icOffset;
+ uint16_t ownerTmp;
+ bool cnia;
+ t_Handle p_StatsTbl;
+ t_Handle h_FmPcd;
+ t_List nodesLst;
+ t_Handle h_Spinlock;
+
+} t_FmPcdManip;
+
+typedef struct t_FmPcdCcSavedManipParams
+{
+ union
+ {
+ struct
+ {
+ uint16_t dataOffset;
+ //uint8_t poolId;
+ }capwapParams;
+ struct
+ {
+ uint16_t dataOffset;
+ uint8_t poolId;
+ }ipParams;
+ };
+
+} t_FmPcdCcSavedManipParams;
+
+
+#endif /* __FM_MANIP_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c
new file mode 100644
index 0000000..747347c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c
@@ -0,0 +1,2114 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_pcd.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "xx_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+#include "fm_pcd_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_pcd_ipc.h"
+#include "fm_hc.h"
+#include "fm_muram_ext.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static t_Error CheckFmPcdParameters(t_FmPcd *p_FmPcd)
+{
+ if (!p_FmPcd->h_Fm)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("h_Fm has to be initialized"));
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ if (p_FmPcd->p_FmPcdKg && !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG"));
+
+ if (p_FmPcd->p_FmPcdPlcr && !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG"));
+
+ if (!p_FmPcd->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdExceptions has to be initialized"));
+
+ if ((!p_FmPcd->f_FmPcdIndexedException) && (p_FmPcd->p_FmPcdPlcr || p_FmPcd->p_FmPcdKg))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdIndexedException has to be initialized"));
+
+ if (p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit > PRS_MAX_CYCLE_LIMIT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("prsMaxParseCycleLimit has to be less than 8191"));
+ }
+
+ return E_OK;
+}
+
+static volatile bool blockingFlag = FALSE;
+static void IpcMsgCompletionCB(t_Handle h_FmPcd,
+ uint8_t *p_Msg,
+ uint8_t *p_Reply,
+ uint32_t replyLength,
+ t_Error status)
+{
+ UNUSED(h_FmPcd);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);
+ blockingFlag = FALSE;
+}
+
+static t_Error IpcMsgHandlerCB(t_Handle h_FmPcd,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg *p_IpcMsg = (t_FmPcdIpcMsg*)p_Msg;
+ t_FmPcdIpcReply *p_IpcReply = (t_FmPcdIpcReply*)p_Reply;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_Msg);
+
+ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_PCD_MAX_REPLY_SIZE));
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_PCD_MASTER_IS_ALIVE):
+ *(uint8_t*)(p_IpcReply->replyBody) = 1;
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_PCD_MASTER_IS_ENABLED):
+ /* count partitions registrations */
+ if (p_FmPcd->enabled)
+ p_FmPcd->numOfEnabledGuestPartitionsPcds++;
+ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)p_FmPcd->enabled;
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_PCD_GUEST_DISABLE):
+ if (p_FmPcd->numOfEnabledGuestPartitionsPcds)
+ {
+ p_FmPcd->numOfEnabledGuestPartitionsPcds--;
+ p_IpcReply->error = E_OK;
+ }
+ else
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE,("Trying to disable an unregistered partition"));
+ p_IpcReply->error = E_INVALID_STATE;
+ }
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ case (FM_PCD_GET_COUNTER):
+ {
+ e_FmPcdCounters inCounter;
+ uint32_t outCounter;
+
+ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t));
+ outCounter = FM_PCD_GetCounter(h_FmPcd, inCounter);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t));
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_KG_SCHEMES):
+ {
+ t_FmPcdIpcKgSchemesParams ipcSchemesParams;
+
+ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams));
+ err = FmPcdKgAllocSchemes(h_FmPcd,
+ ipcSchemesParams.numOfSchemes,
+ ipcSchemesParams.guestId,
+ p_IpcReply->replyBody);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t) + ipcSchemesParams.numOfSchemes*sizeof(uint8_t);
+ break;
+ }
+ case (FM_PCD_FREE_KG_SCHEMES):
+ {
+ t_FmPcdIpcKgSchemesParams ipcSchemesParams;
+
+ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams));
+ err = FmPcdKgFreeSchemes(h_FmPcd,
+ ipcSchemesParams.numOfSchemes,
+ ipcSchemesParams.guestId,
+ ipcSchemesParams.schemesIds);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_KG_CLSPLAN):
+ {
+ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams;
+
+ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams));
+ err = KgAllocClsPlanEntries(h_FmPcd,
+ ipcKgClsPlanParams.numOfClsPlanEntries,
+ ipcKgClsPlanParams.guestId,
+ p_IpcReply->replyBody);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_PCD_FREE_KG_CLSPLAN):
+ {
+ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams;
+
+ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams));
+ KgFreeClsPlanEntries(h_FmPcd,
+ ipcKgClsPlanParams.numOfClsPlanEntries,
+ ipcKgClsPlanParams.guestId,
+ ipcKgClsPlanParams.clsPlanBase);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ uint16_t base;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ base = PlcrAllocProfilesForPartition(h_FmPcd,
+ ipcAllocParams.base,
+ ipcAllocParams.num,
+ ipcAllocParams.guestId);
+ memcpy(p_IpcReply->replyBody, (uint16_t*)&base, sizeof(uint16_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint16_t);
+ break;
+ }
+ case (FM_PCD_FREE_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrFreeProfilesForPartition(h_FmPcd,
+ ipcAllocParams.base,
+ ipcAllocParams.num,
+ ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_PCD_SET_PORT_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrSetPortProfiles(h_FmPcd,
+ ipcAllocParams.guestId,
+ ipcAllocParams.num,
+ ipcAllocParams.base);
+ break;
+ }
+ case (FM_PCD_CLEAR_PORT_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrClearPortProfiles(h_FmPcd,
+ ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_PCD_GET_SW_PRS_OFFSET):
+ {
+ t_FmPcdIpcSwPrsLable ipcSwPrsLable;
+ uint32_t swPrsOffset;
+
+ memcpy((uint8_t*)&ipcSwPrsLable, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcSwPrsLable));
+ swPrsOffset =
+ FmPcdGetSwPrsOffset(h_FmPcd,
+ (e_NetHeaderType)ipcSwPrsLable.enumHdr,
+ ipcSwPrsLable.indexPerHdr);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&swPrsOffset, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_PRS_INC_PORT_STATS):
+ {
+ t_FmPcdIpcPrsIncludePort ipcPrsIncludePort;
+
+ memcpy((uint8_t*)&ipcPrsIncludePort, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcPrsIncludePort));
+ PrsIncludePortInStatistics(h_FmPcd,
+ ipcPrsIncludePort.hardwarePortId,
+ ipcPrsIncludePort.include);
+ break;
+ }
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+static uint32_t NetEnvLock(t_Handle h_NetEnv)
+{
+ ASSERT_COND(h_NetEnv);
+ return XX_LockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock);
+}
+
+static void NetEnvUnlock(t_Handle h_NetEnv, uint32_t intFlags)
+{
+ ASSERT_COND(h_NetEnv);
+ XX_UnlockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock, intFlags);
+}
+
+static void EnqueueLockToFreeLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ LIST_AddToTail(&p_Lock->node, &p_FmPcd->freeLocksLst);
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+}
+
+static t_FmPcdLock * DequeueLockFromFreeLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock = NULL;
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ if (!LIST_IsEmpty(&p_FmPcd->freeLocksLst))
+ {
+ p_Lock = FM_PCD_LOCK_OBJ(p_FmPcd->freeLocksLst.p_Next);
+ LIST_DelAndInit(&p_Lock->node);
+ }
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+
+ return p_Lock;
+}
+
+static void EnqueueLockToAcquiredLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ LIST_AddToTail(&p_Lock->node, &p_FmPcd->acquiredLocksLst);
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+}
+
+static t_Error FillFreeLocksLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+ int i;
+
+ for (i=0; i<10; i++)
+ {
+ p_Lock = (t_FmPcdLock *)XX_Malloc(sizeof(t_FmPcdLock));
+ if (!p_Lock)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("FM-PCD lock obj!"));
+ memset(p_Lock, 0, sizeof(t_FmPcdLock));
+ INIT_LIST(&p_Lock->node);
+ p_Lock->h_Spinlock = XX_InitSpinlock();
+ if (!p_Lock->h_Spinlock)
+ {
+ XX_Free(p_Lock);
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("FM-PCD spinlock obj!"));
+ }
+ EnqueueLockToFreeLst(p_FmPcd, p_Lock);
+ }
+
+ return E_OK;
+}
+
+static void ReleaseFreeLocksLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+
+ p_Lock = DequeueLockFromFreeLst(p_FmPcd);
+ while (p_Lock)
+ {
+ XX_FreeSpinlock(p_Lock->h_Spinlock);
+ XX_Free(p_Lock);
+ p_Lock = DequeueLockFromFreeLst(p_FmPcd);
+ }
+}
+
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId)
+{
+ ASSERT_COND(p_FmPcd);
+ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = clsPlanGrpId;
+}
+
+t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams)
+{
+ uint8_t netEnvId = p_GrpParams->netEnvId;
+ int i, k, j;
+
+ ASSERT_COND(p_FmPcd);
+ if (p_FmPcd->netEnvs[netEnvId].clsPlanGrpId != ILLEGAL_CLS_PLAN)
+ {
+ p_GrpParams->grpExists = TRUE;
+ p_GrpParams->clsPlanGrpId = p_FmPcd->netEnvs[netEnvId].clsPlanGrpId;
+ return E_OK;
+ }
+
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ {
+ /* if an option exists, add it to the opts list */
+ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ {
+ /* check if this option already exists, add if it doesn't */
+ for (j = 0;j<p_GrpParams->numOfOptions;j++)
+ {
+ if (p_GrpParams->options[j] == p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ break;
+ }
+ p_GrpParams->optVectors[j] |= p_FmPcd->netEnvs[netEnvId].unitsVectors[i];
+ if (j == p_GrpParams->numOfOptions)
+ {
+ p_GrpParams->options[p_GrpParams->numOfOptions] = p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt;
+ p_GrpParams->numOfOptions++;
+ }
+ }
+ }
+ }
+
+ if (p_GrpParams->numOfOptions == 0)
+ {
+ if (p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId != ILLEGAL_CLS_PLAN)
+ {
+ p_GrpParams->grpExists = TRUE;
+ p_GrpParams->clsPlanGrpId = p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId;
+ }
+ }
+
+ return E_OK;
+
+}
+
+t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector)
+{
+ uint8_t j,k;
+
+ *p_Vector = 0;
+
+ ASSERT_COND(p_FmPcd);
+ for (j=0; ((j < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[0].hdr != HEADER_TYPE_NONE)); j++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].opt == opt)
+ *p_Vector |= p_FmPcd->netEnvs[netEnvId].unitsVectors[j];
+ }
+ }
+
+ if (!*p_Vector)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested option was not defined for this Network Environment Characteristics module"));
+ else
+ return E_OK;
+}
+
+t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params)
+{
+ int i;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_Params->netEnvId < FM_MAX_NUM_OF_PORTS);
+
+ p_Params->vector = 0;
+ for (i=0; i<p_Params->numOfDistinctionUnits ;i++)
+ {
+ if (p_FmPcd->netEnvs[p_Params->netEnvId].units[p_Params->unitIds[i]].hdrs[0].hdr == HEADER_TYPE_NONE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested unit was not defined for this Network Environment Characteristics module"));
+ ASSERT_COND(p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]);
+ p_Params->vector |= p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]];
+ }
+
+ return E_OK;
+}
+
+bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector)
+{
+ int i=0, k;
+
+ ASSERT_COND(p_FmPcd);
+ /* check whether a given unit may be used by non-clsPlan users. */
+ /* first, recognize the unit by its vector */
+ while (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].unitsVectors[i] == unitVector)
+ {
+ for (k=0;
+ ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE));
+ k++)
+ /* check that no option exists */
+ if ((protocolOpt_t)p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ return FALSE;
+ break;
+ }
+ i++;
+ }
+ /* assert that a unit was found to mach the vector */
+ ASSERT_COND(p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE);
+
+ return TRUE;
+}
+bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i, k;
+
+ ASSERT_COND(p_FmPcd);
+
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr)
+ return TRUE;
+ }
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangable, protocolOpt_t opt)
+{
+ uint8_t i, k;
+
+ ASSERT_COND(p_FmPcd);
+
+ if (interchangable)
+ {
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k=0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt == opt))
+
+ return i;
+ }
+ }
+ }
+ else
+ {
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].opt == opt) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[1].hdr == HEADER_TYPE_NONE))
+ return i;
+
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++)
+ if ((p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].opt == opt))
+ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr;
+ }
+
+ return FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS;
+}
+
+t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0};
+ uint8_t result;
+ t_Error err = E_OK;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_IpReasmCommonPramTbl);
+
+ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase);
+ ccIpReassmTimeoutParams.activate = FALSE; /*Disable Timeout Task*/
+
+ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ switch (result)
+ {
+ case (0):
+ return E_OK;
+ case (1):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, (""));
+ case (2):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, (""));
+ case (3):
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Disable Timeout Task with invalid IPRCPT"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr)
+{
+ int i;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(netEnvId < FM_MAX_NUM_OF_PORTS);
+
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS)
+ && (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr)
+ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr;
+ }
+
+ return HEADER_TYPE_NONE;
+}
+
+void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ ASSERT_COND(h_FmPcd);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort = h_FmPort;
+}
+
+uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(h_FmPcd);
+ return p_FmPcd->netEnvs[netEnvId].lcvs[hdrNum];
+}
+
+uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(h_FmPcd);
+ return p_FmPcd->netEnvs[netEnvId].macsecVector;
+}
+
+uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv)
+{
+ return ((t_FmPcdNetEnv*)h_NetEnv)->netEnvId;
+}
+
+void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(h_FmPcd);
+
+ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]);
+ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners++;
+ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags);
+}
+
+void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners);
+
+ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]);
+ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners--;
+ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags);
+}
+
+uint32_t FmPcdLock(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ return XX_LockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock);
+}
+
+void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcd);
+ XX_UnlockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock, intFlags);
+}
+
+t_FmPcdLock * FmPcdAcquireLock(t_Handle h_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+ ASSERT_COND(h_FmPcd);
+ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd);
+ if (!p_Lock)
+ {
+ FillFreeLocksLst(h_FmPcd);
+ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd);
+ }
+
+ if (p_Lock)
+ EnqueueLockToAcquiredLst((t_FmPcd*)h_FmPcd, p_Lock);
+ return p_Lock;
+}
+
+void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_DelAndInit(&p_Lock->node);
+ FmPcdUnlock(h_FmPcd, intFlags);
+ EnqueueLockToFreeLst((t_FmPcd*)h_FmPcd, p_Lock);
+}
+
+bool FmPcdLockTryLockAll(t_Handle h_FmPcd)
+{
+ uint32_t intFlags;
+ t_List *p_Pos, *p_SavedPos=NULL;
+
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ if (!FmPcdLockTryLock(p_Lock))
+ {
+ p_SavedPos = p_Pos;
+ break;
+ }
+ }
+ if (p_SavedPos)
+ {
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ if (p_Pos == p_SavedPos)
+ break;
+ FmPcdLockUnlock(p_Lock);
+ }
+ }
+ FmPcdUnlock(h_FmPcd, intFlags);
+
+ CORE_MemoryBarrier();
+
+ if (p_SavedPos)
+ return FALSE;
+
+ return TRUE;
+}
+
+void FmPcdLockUnlockAll(t_Handle h_FmPcd)
+{
+ uint32_t intFlags;
+ t_List *p_Pos;
+
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ p_Lock->flag = FALSE;
+ }
+ FmPcdUnlock(h_FmPcd, intFlags);
+
+ CORE_MemoryBarrier();
+}
+
+t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ SANITY_CHECK_RETURN_VALUE(((t_FmPcd*)h_FmPcd)->h_Hc, E_INVALID_HANDLE, NULL);
+ return ((t_FmPcd*)h_FmPcd)->h_Hc;
+}
+
+bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ return ((t_FmPcd*)h_FmPcd)->advancedOffloadSupport;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcd *p_FmPcd = NULL;
+ t_FmPhysAddr physicalMuramBase;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdParams, E_INVALID_HANDLE,NULL);
+
+ p_FmPcd = (t_FmPcd *) XX_Malloc(sizeof(t_FmPcd));
+ if (!p_FmPcd)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD"));
+ return NULL;
+ }
+ memset(p_FmPcd, 0, sizeof(t_FmPcd));
+
+ p_FmPcd->p_FmPcdDriverParam = (t_FmPcdDriverParam *) XX_Malloc(sizeof(t_FmPcdDriverParam));
+ if (!p_FmPcd->p_FmPcdDriverParam)
+ {
+ XX_Free(p_FmPcd);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Driver Param"));
+ return NULL;
+ }
+ memset(p_FmPcd->p_FmPcdDriverParam, 0, sizeof(t_FmPcdDriverParam));
+
+ p_FmPcd->h_Fm = p_FmPcdParams->h_Fm;
+ p_FmPcd->guestId = FmGetGuestId(p_FmPcd->h_Fm);
+ p_FmPcd->h_FmMuram = FmGetMuramHandle(p_FmPcd->h_Fm);
+ if (p_FmPcd->h_FmMuram)
+ {
+ FmGetPhysicalMuramBase(p_FmPcdParams->h_Fm, &physicalMuramBase);
+ p_FmPcd->physicalMuramBase = (uint64_t)((uint64_t)(&physicalMuramBase)->low | ((uint64_t)(&physicalMuramBase)->high << 32));
+ }
+
+ for (i = 0; i<FM_MAX_NUM_OF_PORTS; i++)
+ p_FmPcd->netEnvs[i].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ if (p_FmPcdParams->useHostCommand)
+ {
+ t_FmHcParams hcParams;
+
+ memset(&hcParams, 0, sizeof(hcParams));
+ hcParams.h_Fm = p_FmPcd->h_Fm;
+ hcParams.h_FmPcd = (t_Handle)p_FmPcd;
+ memcpy((uint8_t*)&hcParams.params, (uint8_t*)&p_FmPcdParams->hc, sizeof(t_FmPcdHcParams));
+ p_FmPcd->h_Hc = FmHcConfigAndInit(&hcParams);
+ if (!p_FmPcd->h_Hc)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD HC"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No Host Command defined for a guest partition."));
+
+ if (p_FmPcdParams->kgSupport)
+ {
+ p_FmPcd->p_FmPcdKg = (t_FmPcdKg *)KgConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Keygen"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ if (p_FmPcdParams->plcrSupport)
+ {
+ p_FmPcd->p_FmPcdPlcr = (t_FmPcdPlcr *)PlcrConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Policer"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ if (p_FmPcdParams->prsSupport)
+ {
+ p_FmPcd->p_FmPcdPrs = (t_FmPcdPrs *)PrsConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Parser"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ p_FmPcd->h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPcd->h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD spinlock"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ INIT_LIST(&p_FmPcd->freeLocksLst);
+ INIT_LIST(&p_FmPcd->acquiredLocksLst);
+
+ p_FmPcd->numOfEnabledGuestPartitionsPcds = 0;
+
+ p_FmPcd->f_Exception = p_FmPcdParams->f_Exception;
+ p_FmPcd->f_FmPcdIndexedException = p_FmPcdParams->f_ExceptionId;
+ p_FmPcd->h_App = p_FmPcdParams->h_App;
+
+ p_FmPcd->p_CcShadow = NULL;
+ p_FmPcd->ccShadowSize = 0;
+ p_FmPcd->ccShadowAlign = 0;
+
+ p_FmPcd->h_ShadowSpinlock = XX_InitSpinlock();
+ if (!p_FmPcd->h_ShadowSpinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD shadow spinlock"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+
+ return p_FmPcd;
+}
+
+t_Handle FM_PCD_GetHcDevH(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd;
+
+ return (p_FmPcd) ? FmGcGetHcPortDevH(p_FmPcd->h_Hc) : NULL;
+}
+
+t_Error FM_PCD_Init(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg msg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_FmPcd->h_Fm, &p_FmPcd->fmRevInfo);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ memset(p_FmPcd->fmPcdIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdIpcHandlerModuleName, "FM_PCD_%d_%d", FmGetId(p_FmPcd->h_Fm), NCSW_MASTER_ID) != 10)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm), p_FmPcd->guestId) != (p_FmPcd->guestId<10 ? 10:11))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ p_FmPcd->h_IpcSession = XX_IpcInitSession(p_FmPcd->fmPcdIpcHandlerModuleName, p_FmPcd->fmPcdModuleName);
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+ uint8_t isMasterAlive = 0;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_PCD_MASTER_IS_ALIVE;
+ msg.msgBody[0] = p_FmPcd->guestId;
+ blockingFlag = TRUE;
+
+ do
+ {
+ replyLength = sizeof(uint32_t) + sizeof(isMasterAlive);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(p_FmPcd->guestId),
+ (uint8_t*)&reply,
+ &replyLength,
+ IpcMsgCompletionCB,
+ h_FmPcd)) != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ while (blockingFlag) ;
+ if (replyLength != (sizeof(uint32_t) + sizeof(isMasterAlive)))
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ isMasterAlive = *(uint8_t*)(reply.replyBody);
+ } while (!isMasterAlive);
+ }
+ }
+
+ CHECK_INIT_PARAMETERS(p_FmPcd, CheckFmPcdParameters);
+
+ if (p_FmPcd->p_FmPcdKg)
+ {
+ err = KgInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ {
+ err = PlcrInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->p_FmPcdPrs)
+ {
+ err = PrsInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ /* register to inter-core messaging mechanism */
+ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm),NCSW_MASTER_ID) != 10)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ err = XX_IpcRegisterMsgHandler(p_FmPcd->fmPcdModuleName, IpcMsgHandlerCB, p_FmPcd, FM_PCD_MAX_REPLY_SIZE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* IPv6 Frame-Id used for fragmentation */
+ p_FmPcd->ipv6FrameIdAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, 4, 4));
+ if (!p_FmPcd->ipv6FrameIdAddr)
+ {
+ FM_PCD_Free(p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for IPv6 Frame-Id"));
+ }
+ IOMemSet32(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr), 0, 4);
+
+ XX_Free(p_FmPcd->p_FmPcdDriverParam);
+ p_FmPcd->p_FmPcdDriverParam = NULL;
+
+ FmRegisterPcd(p_FmPcd->h_Fm, p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_Free(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd =(t_FmPcd *)h_FmPcd;
+ t_Error err = E_OK;
+
+ if (p_FmPcd->ipv6FrameIdAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr));
+
+ if (p_FmPcd->enabled)
+ FM_PCD_Disable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdDriverParam)
+ {
+ XX_Free(p_FmPcd->p_FmPcdDriverParam);
+ p_FmPcd->p_FmPcdDriverParam = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdKg)
+ {
+ if ((err = KgFree(p_FmPcd)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ XX_Free(p_FmPcd->p_FmPcdKg);
+ p_FmPcd->p_FmPcdKg = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ {
+ if ((err = PlcrFree(p_FmPcd)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ XX_Free(p_FmPcd->p_FmPcdPlcr);
+ p_FmPcd->p_FmPcdPlcr = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdPrs)
+ {
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ PrsFree(p_FmPcd);
+ XX_Free(p_FmPcd->p_FmPcdPrs);
+ p_FmPcd->p_FmPcdPrs = NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ FmHcFree(p_FmPcd->h_Hc);
+ p_FmPcd->h_Hc = NULL;
+ }
+
+ XX_IpcUnregisterMsgHandler(p_FmPcd->fmPcdModuleName);
+
+ FmUnregisterPcd(p_FmPcd->h_Fm);
+
+ ReleaseFreeLocksLst(p_FmPcd);
+
+ if (p_FmPcd->h_Spinlock)
+ XX_FreeSpinlock(p_FmPcd->h_Spinlock);
+
+ if (p_FmPcd->h_ShadowSpinlock)
+ XX_FreeSpinlock(p_FmPcd->h_ShadowSpinlock);
+
+ XX_Free(p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigException - guest mode!"));
+
+ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_FmPcd->exceptions |= bitMask;
+ else
+ p_FmPcd->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ return FmHcSetFramesDataMemory(p_FmPcd->h_Hc, memId);
+}
+
+t_Error FM_PCD_Enable(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->enabled)
+ return E_OK;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ uint8_t enabled;
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_MASTER_IS_ENABLED;
+ replyLength = sizeof(uint32_t) + sizeof(enabled);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(enabled))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ p_FmPcd->enabled = (bool)!!(*(uint8_t*)(reply.replyBody));
+ if (!p_FmPcd->enabled)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-PCD master should be enabled first!"));
+
+ return E_OK;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ if (p_FmPcd->p_FmPcdKg)
+ KgEnable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ PlcrEnable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPrs)
+ PrsEnable(p_FmPcd);
+
+ p_FmPcd->enabled = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_Disable(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+
+ if (!p_FmPcd->enabled)
+ return E_OK;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_GUEST_DISABLE;
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ if (reply.error == E_OK)
+ p_FmPcd->enabled = FALSE;
+
+ return (t_Error)(reply.error);
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ if (p_FmPcd->numOfEnabledGuestPartitionsPcds != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("Trying to disable a master partition PCD while"
+ "guest partitions are still enabled!"));
+
+ if (p_FmPcd->p_FmPcdKg)
+ KgDisable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ PlcrDisable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPrs)
+ PrsDisable(p_FmPcd);
+
+ p_FmPcd->enabled = FALSE;
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags, specialUnits = 0;
+ uint8_t bitId = 0;
+ uint8_t i, j, k;
+ uint8_t netEnvCurrId;
+ uint8_t ipsecAhUnit = 0,ipsecEspUnit = 0;
+ bool ipsecAhExists = FALSE, ipsecEspExists = FALSE, shim1Selected = FALSE;
+ uint8_t hdrNum;
+ t_FmPcdNetEnvParams *p_modifiedNetEnvParams;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_STATE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_NetEnvParams, E_NULL_POINTER, NULL);
+
+ intFlags = FmPcdLock(p_FmPcd);
+
+ /* find a new netEnv */
+ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
+ if (!p_FmPcd->netEnvs[i].used)
+ break;
+
+ if (i== FM_MAX_NUM_OF_PORTS)
+ {
+ REPORT_ERROR(MAJOR, E_FULL,("No more than %d netEnv's allowed.", FM_MAX_NUM_OF_PORTS));
+ FmPcdUnlock(p_FmPcd, intFlags);
+ return NULL;
+ }
+
+ p_FmPcd->netEnvs[i].used = TRUE;
+ FmPcdUnlock(p_FmPcd, intFlags);
+
+ /* As anyone doesn't have handle of this netEnv yet, no need
+ to protect it with spinlocks */
+
+ p_modifiedNetEnvParams = (t_FmPcdNetEnvParams *) XX_Malloc(sizeof(t_FmPcdNetEnvParams));
+ if (!p_modifiedNetEnvParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FmPcdNetEnvParams"));
+ return NULL;
+ }
+
+ memcpy(p_modifiedNetEnvParams, p_NetEnvParams, sizeof(t_FmPcdNetEnvParams));
+ p_NetEnvParams = p_modifiedNetEnvParams;
+
+ netEnvCurrId = (uint8_t)i;
+
+ /* clear from previous use */
+ memset(&p_FmPcd->netEnvs[netEnvCurrId].units, 0, FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS * sizeof(t_FmPcdIntDistinctionUnit));
+ memset(&p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs, 0, FM_PCD_MAX_NUM_OF_ALIAS_HDRS * sizeof(t_FmPcdNetEnvAliases));
+ memcpy(&p_FmPcd->netEnvs[netEnvCurrId].units, p_NetEnvParams->units, p_NetEnvParams->numOfDistinctionUnits*sizeof(t_FmPcdIntDistinctionUnit));
+
+ p_FmPcd->netEnvs[netEnvCurrId].netEnvId = netEnvCurrId;
+ p_FmPcd->netEnvs[netEnvCurrId].h_FmPcd = p_FmPcd;
+
+ p_FmPcd->netEnvs[netEnvCurrId].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ /* check that header with opt is not interchanged with the same header */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ /* if an option exists, check that other headers are not the same header
+ without option */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt)
+ {
+ for (j = 0; (j < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr != HEADER_TYPE_NONE); j++)
+ {
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr == p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr) &&
+ !p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].opt)
+ {
+ REPORT_ERROR(MINOR, E_FULL,
+ ("Illegal unit - header with opt may not be interchangeable with the same header without opt"));
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* Specific headers checking */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ /* Some headers pairs may not be defined on different units as the parser
+ doesn't distinguish */
+ /* IPSEC_AH and IPSEC_SPI can't be 2 units, */
+ /* check that header with opt is not interchanged with the same header */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_AH)
+ {
+ if (ipsecEspExists && (ipsecEspUnit != i))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units"));
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ else
+ {
+ ipsecAhUnit = i;
+ ipsecAhExists = TRUE;
+ }
+ }
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_ESP)
+ {
+ if (ipsecAhExists && (ipsecAhUnit != i))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units"));
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ else
+ {
+ ipsecEspUnit = i;
+ ipsecEspExists = TRUE;
+ }
+ }
+ /* ENCAP_ESP */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_ENCAP_ESP)
+ {
+ /* IPSec UDP encapsulation is currently set to use SHIM1 */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_ENCAP_ESP;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM1;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM1;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+ }
+#ifdef FM_CAPWAP_SUPPORT
+ /* UDP_LITE */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_LITE)
+ {
+ /* IPSec UDP encapsulation is currently set to use SHIM1 */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_LITE;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_UDP;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_UDP;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ /* IP FRAG */
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv4) &&
+ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV4_FRAG_1))
+ {
+ /* If IPv4+Frag, we need to set 2 units - SHIM 2 and IPv4. We first set SHIM2, and than check if
+ * IPv4 exists. If so we don't need to set an extra unit
+ * We consider as "having IPv4" any IPv4 without interchangable headers
+ * but including any options. */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv4;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV4_FRAG_1;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+
+ /* check if IPv4 header exists by itself */
+ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv4, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv4;
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0;
+ }
+ }
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv6) &&
+ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV6_FRAG_1))
+ {
+ /* If IPv6+Frag, we need to set 2 units - SHIM 2 and IPv6. We first set SHIM2, and than check if
+ * IPv4 exists. If so we don't need to set an extra unit
+ * We consider as "having IPv6" any IPv6 without interchangable headers
+ * but including any options. */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv6;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV6_FRAG_1;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+
+ /* check if IPv6 header exists by itself */
+ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv6, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv6;
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0;
+ }
+ }
+ }
+ }
+
+ /* if private header (shim), check that no other headers specified */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[1].hdr != HEADER_TYPE_NONE)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header may not be interchanged with other headers"));
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < p_NetEnvParams->numOfDistinctionUnits; i++)
+ {
+ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ switch (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)
+ {
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ if (shim1Selected)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header cannot be selected with UDP_IPSEC_ESP"));
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ shim1Selected = TRUE;
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000001;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000002;
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested SHIM not supported"));
+ }
+ else
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = (uint32_t)(0x80000000 >> bitId++);
+
+ if (IS_SPECIAL_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ p_FmPcd->netEnvs[netEnvCurrId].macsecVector = p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i];
+ }
+ }
+
+ /* define a set of hardware parser LCV's according to the defined netenv */
+
+ /* set an array of LCV's for each header in the netEnv */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ /* private headers have no LCV in the hard parser */
+ if (!IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ GET_PRS_HDR_NUM(hdrNum, p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr);
+ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM))
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+ XX_Free(p_modifiedNetEnvParams);
+ return NULL;
+ }
+ p_FmPcd->netEnvs[netEnvCurrId].lcvs[hdrNum] |= p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i];
+ }
+ }
+ }
+ XX_Free(p_modifiedNetEnvParams);
+
+ p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Pcd NetEnv spinlock"));
+ return NULL;
+ }
+ return &p_FmPcd->netEnvs[netEnvCurrId];
+}
+
+t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv)
+{
+ t_FmPcdNetEnv *p_NetEnv = (t_FmPcdNetEnv*)h_NetEnv;
+ t_FmPcd *p_FmPcd = p_NetEnv->h_FmPcd;
+ uint32_t intFlags;
+ uint8_t netEnvId = p_NetEnv->netEnvId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ /* check that no port is bound to this netEnv */
+ if (p_FmPcd->netEnvs[netEnvId].owners)
+ {
+ RETURN_ERROR(MINOR, E_INVALID_STATE,
+ ("Trying to delete a netEnv that has ports/schemes/trees/clsPlanGrps bound to"));
+ }
+
+ intFlags = FmPcdLock(p_FmPcd);
+
+ p_FmPcd->netEnvs[netEnvId].used = FALSE;
+ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ memset(p_FmPcd->netEnvs[netEnvId].units, 0, sizeof(t_FmPcdIntDistinctionUnit)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ memset(p_FmPcd->netEnvs[netEnvId].unitsVectors, 0, sizeof(uint32_t)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ memset(p_FmPcd->netEnvs[netEnvId].lcvs, 0, sizeof(uint32_t)*FM_PCD_PRS_NUM_OF_HDRS);
+
+ if (p_FmPcd->netEnvs[netEnvId].h_Spinlock)
+ XX_FreeSpinlock(p_FmPcd->netEnvs[netEnvId].h_Spinlock);
+
+ FmPcdUnlock(p_FmPcd, intFlags);
+ return E_OK;
+}
+
+void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN(h_FmPcd, E_INVALID_STATE);
+
+ FmHcTxConf(p_FmPcd->h_Hc, p_Fd);
+}
+
+t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmCtrlCodeRevisionInfo revInfo;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_STATE);
+
+ if ((err = FM_GetFmanCtrlCodeRevision(p_FmPcd->h_Fm, &revInfo)) != E_OK)
+ {
+ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision."));
+ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER;
+ }
+ if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package"));
+
+ p_FmPcd->advancedOffloadSupport = TRUE;
+
+ return E_OK;
+}
+
+uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t outCounter = 0;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
+
+ switch (counter)
+ {
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ if (!p_FmPcd->p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("KeyGen is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+ return 0;
+ }
+ break;
+
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Policer is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in \"guest-mode\" without neither IPC nor mapped register!"));
+ return 0;
+ }
+
+ /* check that counters are enabled */
+ if (p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs &&
+ !(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs ||
+ ((p_FmPcd->guestId != NCSW_MASTER_ID) && p_FmPcd->h_IpcSession));
+ break;
+
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ if (!p_FmPcd->p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Parser is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+ return 0;
+ }
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ return 0;
+ }
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_PCD_GET_COUNTER;
+ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(uint32_t),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t));
+ return outCounter;
+ }
+
+ switch (counter)
+ {
+ /* Parser statistics */
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds);
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs);
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs);
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs);
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs);
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres);
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres);
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres);
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres);
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs);
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs);
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs);
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs);
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ return GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc);
+
+ /* Policer statistics */
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt);
+
+ default:
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ return 0;
+ }
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->p_FmPcdKg)
+ err |= FM_PCD_KgDumpRegs(h_FmPcd);
+ if (p_FmPcd->p_FmPcdPlcr)
+ err |= FM_PCD_PlcrDumpRegs(h_FmPcd);
+ if (p_FmPcd->p_FmPcdPrs)
+ err |= FM_PCD_PrsDumpRegs(h_FmPcd);
+
+ return err;
+}
+
+t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_STATE);
+
+ return FmHcDumpRegs(p_FmPcd->h_Hc);
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t bitMask = 0, tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetException - guest mode!"));
+
+ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception);
+
+ if (bitMask)
+ {
+ if (enable)
+ p_FmPcd->exceptions |= bitMask;
+ else
+ p_FmPcd->exceptions &= ~bitMask;
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working"));
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - parser is not working"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception"));
+
+ }
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer);
+ if (enable)
+ tmpReg |= FM_EX_KG_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_EX_KG_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg);
+ break;
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer);
+ if (enable)
+ tmpReg |= FM_EX_KG_KEYSIZE_OVERFLOW;
+ else
+ tmpReg &= ~FM_EX_KG_KEYSIZE_OVERFLOW;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg);
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer);
+ if (enable)
+ tmpReg |= FM_PCD_PRS_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PRS_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer, tmpReg);
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever);
+ if (enable)
+ tmpReg |= FM_PCD_PRS_SINGLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PRS_SINGLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PLCR_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ else
+ tmpReg &= ~FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ else
+ tmpReg &= ~FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ else
+ tmpReg &= ~FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception"));
+ }
+ /* for ECC exceptions driver automatically enables ECC mechanism, if disabled.
+ Driver may disable them automatically, depending on driver's status */
+ if (enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+ if (!enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ FmDisableRamsEcc(p_FmPcd->h_Fm);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ForceIntr - guest mode!"));
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working"));
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt -parsrer is not working"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid interrupt requested"));
+
+ }
+ switch (exception)
+ {
+ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_DOUBLE_ECC);
+ break;
+ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW:
+ if (!(p_FmPcd->exceptions & FM_EX_KG_KEYSIZE_OVERFLOW))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_KEYSIZE_OVERFLOW);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_DOUBLE_ECC);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_INIT_ENTRY_ERROR);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced"));
+ }
+
+ return E_OK;
+}
+
+
+t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ModifyCounter - guest mode!"));
+
+ switch (counter)
+ {
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - KeyGen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - Policer is not working"));
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ }
+ switch (counter)
+ {
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs, value);
+ break;
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc,value);
+ break;
+
+ /*Policer counters*/
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt, value);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ }
+
+return E_OK;
+}
+
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h
new file mode 100644
index 0000000..b6b9b35
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_pcd.h
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#ifndef __FM_PCD_H
+#define __FM_PCD_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_common.h"
+#include "fsl_fman_prs.h"
+#include "fsl_fman_kg.h"
+
+#define __ERR_MODULE__ MODULE_FM_PCD
+
+
+/****************************/
+/* Defaults */
+/****************************/
+#define DEFAULT_plcrAutoRefresh FALSE
+#define DEFAULT_fmPcdKgErrorExceptions (FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW)
+#define DEFAULT_fmPcdPlcrErrorExceptions (FM_PCD_EX_PLCR_DOUBLE_ECC | FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)
+#define DEFAULT_fmPcdPlcrExceptions 0
+#define DEFAULT_fmPcdPrsErrorExceptions (FM_PCD_EX_PRS_DOUBLE_ECC)
+
+#define DEFAULT_fmPcdPrsExceptions FM_PCD_EX_PRS_SINGLE_ECC
+#define DEFAULT_numOfUsedProfilesPerWindow 16
+#define DEFAULT_numOfSharedPlcrProfiles 4
+
+/****************************/
+/* Network defines */
+/****************************/
+#define UDP_HEADER_SIZE 8
+
+#define ESP_SPI_OFFSET 0
+#define ESP_SPI_SIZE 4
+#define ESP_SEQ_NUM_OFFSET ESP_SPI_SIZE
+#define ESP_SEQ_NUM_SIZE 4
+
+/****************************/
+/* General defines */
+/****************************/
+#define ILLEGAL_CLS_PLAN 0xff
+#define ILLEGAL_NETENV 0xff
+
+#define FM_PCD_MAX_NUM_OF_ALIAS_HDRS 3
+
+/****************************/
+/* Error defines */
+/****************************/
+
+#define FM_PCD_EX_PLCR_DOUBLE_ECC 0x20000000
+#define FM_PCD_EX_PLCR_INIT_ENTRY_ERROR 0x10000000
+#define FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE 0x08000000
+#define FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE 0x04000000
+
+#define GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception) \
+switch (exception){ \
+ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_EX_KG_DOUBLE_ECC; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_PCD_EX_PLCR_DOUBLE_ECC; break; \
+ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: \
+ bitMask = FM_EX_KG_KEYSIZE_OVERFLOW; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: \
+ bitMask = FM_PCD_EX_PLCR_INIT_ENTRY_ERROR; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: \
+ bitMask = FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: \
+ bitMask = FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE; break; \
+ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_PCD_EX_PRS_DOUBLE_ECC; break; \
+ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: \
+ bitMask = FM_PCD_EX_PRS_SINGLE_ECC; break; \
+ default: bitMask = 0;break;}
+
+/***********************************************************************/
+/* Policer defines */
+/***********************************************************************/
+#define FM_PCD_PLCR_GCR_STEN 0x40000000
+#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000
+#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000
+#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000
+#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000
+
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+
+typedef _Packed struct {
+/* General Configuration and Status Registers */
+ volatile uint32_t fmpl_gcr; /* 0x000 FMPL_GCR - FM Policer General Configuration */
+ volatile uint32_t fmpl_gsr; /* 0x004 FMPL_GSR - FM Policer Global Status Register */
+ volatile uint32_t fmpl_evr; /* 0x008 FMPL_EVR - FM Policer Event Register */
+ volatile uint32_t fmpl_ier; /* 0x00C FMPL_IER - FM Policer Interrupt Enable Register */
+ volatile uint32_t fmpl_ifr; /* 0x010 FMPL_IFR - FM Policer Interrupt Force Register */
+ volatile uint32_t fmpl_eevr; /* 0x014 FMPL_EEVR - FM Policer Error Event Register */
+ volatile uint32_t fmpl_eier; /* 0x018 FMPL_EIER - FM Policer Error Interrupt Enable Register */
+ volatile uint32_t fmpl_eifr; /* 0x01C FMPL_EIFR - FM Policer Error Interrupt Force Register */
+/* Global Statistic Counters */
+ volatile uint32_t fmpl_rpcnt; /* 0x020 FMPL_RPC - FM Policer RED Packets Counter */
+ volatile uint32_t fmpl_ypcnt; /* 0x024 FMPL_YPC - FM Policer YELLOW Packets Counter */
+ volatile uint32_t fmpl_rrpcnt; /* 0x028 FMPL_RRPC - FM Policer Recolored RED Packet Counter */
+ volatile uint32_t fmpl_rypcnt; /* 0x02C FMPL_RYPC - FM Policer Recolored YELLOW Packet Counter */
+ volatile uint32_t fmpl_tpcnt; /* 0x030 FMPL_TPC - FM Policer Total Packet Counter */
+ volatile uint32_t fmpl_flmcnt; /* 0x034 FMPL_FLMC - FM Policer Frame Length Mismatch Counter */
+ volatile uint32_t fmpl_res0[21]; /* 0x038 - 0x08B Reserved */
+/* Profile RAM Access Registers */
+ volatile uint32_t fmpl_par; /* 0x08C FMPL_PAR - FM Policer Profile Action Register*/
+ t_FmPcdPlcrProfileRegs profileRegs;
+/* Error Capture Registers */
+ volatile uint32_t fmpl_serc; /* 0x100 FMPL_SERC - FM Policer Soft Error Capture */
+ volatile uint32_t fmpl_upcr; /* 0x104 FMPL_UPCR - FM Policer Uninitialized Profile Capture Register */
+ volatile uint32_t fmpl_res2; /* 0x108 Reserved */
+/* Debug Registers */
+ volatile uint32_t fmpl_res3[61]; /* 0x10C-0x200 Reserved Debug*/
+/* Profile Selection Mapping Registers Per Port-ID (n=1-11, 16) */
+ volatile uint32_t fmpl_dpmr; /* 0x200 FMPL_DPMR - FM Policer Default Mapping Register */
+ volatile uint32_t fmpl_pmr[63]; /*+default 0x204-0x2FF FMPL_PMR1 - FMPL_PMR63, - FM Policer Profile Mapping Registers.
+ (for port-ID 1-11, only for supported Port-ID registers) */
+} _PackedType t_FmPcdPlcrRegs;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+
+typedef struct {
+ bool known;
+ uint8_t id;
+} t_FmPcdKgSchemesExtractsEntry;
+
+typedef struct {
+ t_FmPcdKgSchemesExtractsEntry extractsArray[FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY];
+} t_FmPcdKgSchemesExtracts;
+
+typedef struct {
+ t_Handle h_Manip;
+ bool keepRes;
+ e_FmPcdEngine nextEngine;
+ uint8_t parseCode;
+} t_FmPcdInfoForManip;
+
+/**************************************************************************//**
+ @Description A structure of parameters to communicate
+ between the port and PCD regarding the KG scheme.
+*//***************************************************************************/
+typedef struct {
+ uint8_t netEnvId; /* in */
+ uint8_t numOfDistinctionUnits; /* in */
+ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* in */
+ uint32_t vector; /* out */
+} t_NetEnvParams;
+
+typedef struct {
+ bool allocated;
+ uint8_t ownerId; /* guestId for KG in multi-partition only.
+ portId for PLCR in any environment */
+} t_FmPcdAllocMng;
+
+typedef struct {
+ volatile bool lock;
+ bool used;
+ uint8_t owners;
+ uint8_t netEnvId;
+ uint8_t guestId;
+ uint8_t baseEntry;
+ uint16_t sizeOfGrp;
+ protocolOpt_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+} t_FmPcdKgClsPlanGrp;
+
+typedef struct {
+ t_Handle h_FmPcd;
+ uint8_t schemeId;
+ t_FmPcdLock *p_Lock;
+ bool valid;
+ uint8_t netEnvId;
+ uint8_t owners;
+ uint32_t matchVector;
+ uint32_t ccUnits;
+ bool nextRelativePlcrProfile;
+ uint16_t relativeProfileId;
+ uint16_t numOfProfiles;
+ t_FmPcdKgKeyOrder orderedArray;
+ e_FmPcdEngine nextEngine;
+ e_FmPcdDoneAction doneAction;
+ uint8_t pointedOwners;
+ uint32_t requiredAction;
+ bool extractedOrs;
+ uint8_t bitOffsetInPlcrProfile;
+ bool directPlcr;
+#if (DPAA_VERSION >= 11)
+ bool vspe;
+#endif
+} t_FmPcdKgScheme;
+
+typedef _Packed union {
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_pe_regs portRegs;
+ struct fman_kg_cp_regs clsPlanRegs;
+} _PackedType u_FmPcdKgIndirectAccessRegs;
+
+typedef struct {
+ struct fman_kg_regs *p_FmPcdKgRegs;
+ uint32_t schemeExceptionsBitMask;
+ uint8_t numOfSchemes;
+ t_Handle h_HwSpinlock;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmPcdKgScheme schemes[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmPcdKgClsPlanGrp clsPlanGrps[FM_MAX_NUM_OF_PORTS];
+ uint8_t emptyClsPlanGrpId;
+ t_FmPcdAllocMng schemesMng[FM_PCD_KG_NUM_OF_SCHEMES]; /* only for MASTER ! */
+ t_FmPcdAllocMng clsPlanBlocksMng[FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP];
+ u_FmPcdKgIndirectAccessRegs *p_IndirectAccessRegs;
+} t_FmPcdKg;
+
+typedef struct {
+ uint16_t profilesBase;
+ uint16_t numOfProfiles;
+ t_Handle h_FmPort;
+} t_FmPcdPlcrMapParam;
+
+typedef struct {
+ uint16_t absoluteProfileId;
+ t_Handle h_FmPcd;
+ bool valid;
+ t_FmPcdLock *p_Lock;
+ t_FmPcdAllocMng profilesMng;
+ uint8_t pointedOwners;
+ uint32_t requiredAction;
+ e_FmPcdEngine nextEngineOnGreen; /**< Green next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Green next engine params */
+
+ e_FmPcdEngine nextEngineOnYellow; /**< Yellow next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Yellow next engine params */
+
+ e_FmPcdEngine nextEngineOnRed; /**< Red next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Red next engine params */
+} t_FmPcdPlcrProfile;
+
+typedef struct {
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+ uint16_t partPlcrProfilesBase;
+ uint16_t partNumOfPlcrProfiles;
+ t_FmPcdPlcrProfile profiles[FM_PCD_PLCR_NUM_ENTRIES];
+ uint16_t numOfSharedProfiles;
+ uint16_t sharedProfilesIds[FM_PCD_PLCR_NUM_ENTRIES];
+ t_FmPcdPlcrMapParam portsMapping[FM_MAX_NUM_OF_PORTS];
+ t_Handle h_HwSpinlock;
+ t_Handle h_SwSpinlock;
+} t_FmPcdPlcr;
+
+typedef struct {
+ uint32_t *p_SwPrsCode;
+ uint32_t *p_CurrSwPrs;
+ uint8_t currLabel;
+ struct fman_prs_regs *p_FmPcdPrsRegs;
+ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS];
+ uint32_t fmPcdPrsPortIdStatistics;
+} t_FmPcdPrs;
+
+typedef struct {
+ struct {
+ e_NetHeaderType hdr;
+ protocolOpt_t opt; /* only one option !! */
+ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS];
+} t_FmPcdIntDistinctionUnit;
+
+typedef struct {
+ e_NetHeaderType hdr;
+ protocolOpt_t opt; /* only one option !! */
+ e_NetHeaderType aliasHdr;
+} t_FmPcdNetEnvAliases;
+
+typedef struct {
+ uint8_t netEnvId;
+ t_Handle h_FmPcd;
+ t_Handle h_Spinlock;
+ bool used;
+ uint8_t owners;
+ uint8_t clsPlanGrpId;
+ t_FmPcdIntDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ uint32_t unitsVectors[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint32_t macsecVector;
+ t_FmPcdNetEnvAliases aliasHdrs[FM_PCD_MAX_NUM_OF_ALIAS_HDRS];
+} t_FmPcdNetEnv;
+
+typedef struct {
+ struct fman_prs_cfg dfltCfg;
+ bool plcrAutoRefresh;
+ uint16_t prsMaxParseCycleLimit;
+} t_FmPcdDriverParam;
+
+typedef struct {
+ t_Handle h_Fm;
+ t_Handle h_FmMuram;
+ t_FmRevisionInfo fmRevInfo;
+
+ uint64_t physicalMuramBase;
+
+ t_Handle h_Spinlock;
+ t_List freeLocksLst;
+ t_List acquiredLocksLst;
+
+ t_Handle h_IpcSession; /* relevant for guest only */
+ bool enabled;
+ uint8_t guestId; /**< Guest Partition Id */
+ uint8_t numOfEnabledGuestPartitionsPcds;
+ char fmPcdModuleName[MODULE_NAME_SIZE];
+ char fmPcdIpcHandlerModuleName[MODULE_NAME_SIZE]; /* relevant for guest only - this is the master's name */
+ t_FmPcdNetEnv netEnvs[FM_MAX_NUM_OF_PORTS];
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdPlcr *p_FmPcdPlcr;
+ t_FmPcdPrs *p_FmPcdPrs;
+
+ void *p_CcShadow; /**< CC MURAM shadow */
+ uint32_t ccShadowSize;
+ uint32_t ccShadowAlign;
+ volatile bool shadowLock;
+ t_Handle h_ShadowSpinlock;
+
+ t_Handle h_Hc;
+
+ uint32_t exceptions;
+ t_FmPcdExceptionCallback *f_Exception;
+ t_FmPcdIdExceptionCallback *f_FmPcdIndexedException;
+ t_Handle h_App;
+ uintptr_t ipv6FrameIdAddr;
+ bool advancedOffloadSupport;
+
+ t_FmPcdDriverParam *p_FmPcdDriverParam;
+} t_FmPcd;
+
+#if (DPAA_VERSION >= 11)
+typedef uint8_t t_FmPcdFrmReplicUpdateType;
+#define FRM_REPLIC_UPDATE_COUNTER 0x01
+#define FRM_REPLIC_UPDATE_INFO 0x02
+#endif /* (DPAA_VERSION >= 11) */
+/***********************************************************************/
+/* PCD internal routines */
+/***********************************************************************/
+
+t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector);
+t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params);
+bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector);
+t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams);
+void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId);
+e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+uint8_t FmPcdNetEnvGetUnitIdForSingleHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangable, protocolOpt_t opt);
+
+t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId);
+t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip);
+bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip);
+
+t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams);
+t_Error KgInit(t_FmPcd *p_FmPcd);
+t_Error KgFree(t_FmPcd *p_FmPcd);
+void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set);
+bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId);
+void KgEnable(t_FmPcd *p_FmPcd);
+void KgDisable(t_FmPcd *p_FmPcd);
+t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First);
+void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base);
+
+/* only for MULTI partittion */
+t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds);
+t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds);
+/* only for SINGLE partittion */
+t_Error KgBindPortToSchemes(t_Handle h_FmPcd , uint8_t hardwarePortId, uint32_t spReg);
+
+t_FmPcdLock *FmPcdAcquireLock(t_Handle h_FmPcd);
+void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock);
+
+t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams);
+t_Error PlcrInit(t_FmPcd *p_FmPcd);
+t_Error PlcrFree(t_FmPcd *p_FmPcd);
+void PlcrEnable(t_FmPcd *p_FmPcd);
+void PlcrDisable(t_FmPcd *p_FmPcd);
+uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId);
+void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId);
+t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfProfiles,
+ uint16_t base);
+t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId);
+
+t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams);
+t_Error PrsInit(t_FmPcd *p_FmPcd);
+void PrsEnable(t_FmPcd *p_FmPcd);
+void PrsDisable(t_FmPcd *p_FmPcd);
+void PrsFree(t_FmPcd *p_FmPcd );
+t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include);
+
+t_Error FmPcdCcGetGrpParams(t_Handle treeId, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase);
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode);
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode);
+uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode);
+t_Error ValidateNextEngineParams(t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, e_FmPcdCcStatsMode supportedStatsMode);
+
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add);
+t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_InfoForManip, uint32_t *requiredAction);
+void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_Handle p_Ad,
+ t_Handle *p_AdNewPtr);
+void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew, uint32_t adTableOffset);
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add);
+t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode);
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FmPcdManipApplSpecificBuild(void);
+bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip);
+#endif /* FM_CAPWAP_SUPPORT */
+#if (DPAA_VERSION >= 11)
+void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup);
+void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, bool add);
+void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, void *p_Ad, t_Handle *h_AdNew);
+
+void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node,
+ t_Handle h_ReplicGroup,
+ t_List *p_AdTables,
+ uint32_t *p_NumOfAdTables);
+#endif /* (DPAA_VERSION >= 11) */
+
+void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock);
+void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock);
+t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock);
+t_List *FmPcdManipGetSpinlock(t_Handle h_Manip);
+t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip);
+
+typedef struct
+{
+ t_Handle h_StatsAd;
+ t_Handle h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_StatsFLRs;
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPcdCcStatsParams;
+
+void NextStepAd(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ t_FmPcd *p_FmPcd);
+void ReleaseLst(t_List *p_List);
+
+static __inline__ t_Handle FmPcdGetMuramHandle(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+ return p_FmPcd->h_FmMuram;
+}
+
+static __inline__ uint64_t FmPcdGetMuramPhysBase(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+ return p_FmPcd->physicalMuramBase;
+}
+
+static __inline__ uint32_t FmPcdLockSpinlock(t_FmPcdLock *p_Lock)
+{
+ ASSERT_COND(p_Lock);
+ return XX_LockIntrSpinlock(p_Lock->h_Spinlock);
+}
+
+static __inline__ void FmPcdUnlockSpinlock(t_FmPcdLock *p_Lock, uint32_t flags)
+{
+ ASSERT_COND(p_Lock);
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, flags);
+}
+
+static __inline__ bool FmPcdLockTryLock(t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_Lock);
+ intFlags = XX_LockIntrSpinlock(p_Lock->h_Spinlock);
+ if (p_Lock->flag)
+ {
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags);
+ return FALSE;
+ }
+ p_Lock->flag = TRUE;
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags);
+ return TRUE;
+}
+
+static __inline__ void FmPcdLockUnlock(t_FmPcdLock *p_Lock)
+{
+ ASSERT_COND(p_Lock);
+ p_Lock->flag = FALSE;
+}
+
+
+#endif /* __FM_PCD_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h
new file mode 100644
index 0000000..5184ce6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_pcd_ipc.h
+
+ @Description FM PCD Inter-Partition prototypes, structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_PCD_IPC_H
+#define __FM_PCD_IPC_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description Structure for getting a sw parser address according to a label
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+*//***************************************************************************/
+typedef _Packed struct t_FmPcdIpcSwPrsLable
+{
+ uint32_t enumHdr; /**< IN. The existance of this header will envoke
+ the sw parser code. */
+ uint8_t indexPerHdr; /**< IN. Normally 0, if more than one sw parser
+ attachments for the same header, use this
+
+ index to distinguish between them. */
+} _PackedType t_FmPcdIpcSwPrsLable;
+
+/**************************************************************************//**
+ @Description Structure for port-PCD communication.
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+ Some fields are optional (depending on configuration) and
+ will be analized by the port and FM modules accordingly.
+*//***************************************************************************/
+
+typedef struct t_FmPcdIpcKgSchemesParams
+{
+ uint8_t guestId;
+ uint8_t numOfSchemes;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+} _PackedType t_FmPcdIpcKgSchemesParams;
+
+typedef struct t_FmPcdIpcKgClsPlanParams
+{
+ uint8_t guestId;
+ uint16_t numOfClsPlanEntries;
+ uint8_t clsPlanBase;
+} _PackedType t_FmPcdIpcKgClsPlanParams;
+
+typedef _Packed struct t_FmPcdIpcPrsIncludePort
+{
+ uint8_t hardwarePortId;
+ bool include;
+} _PackedType t_FmPcdIpcPrsIncludePort;
+
+
+#define FM_PCD_MAX_REPLY_SIZE 16
+#define FM_PCD_MAX_MSG_SIZE 36
+#define FM_PCD_MAX_REPLY_BODY_SIZE 36
+
+typedef _Packed struct {
+ uint32_t msgId;
+ uint8_t msgBody[FM_PCD_MAX_MSG_SIZE];
+} _PackedType t_FmPcdIpcMsg;
+
+typedef _Packed struct t_FmPcdIpcReply {
+ uint32_t error;
+ uint8_t replyBody[FM_PCD_MAX_REPLY_BODY_SIZE];
+} _PackedType t_FmPcdIpcReply;
+
+typedef _Packed struct t_FmIpcResourceAllocParams {
+ uint8_t guestId;
+ uint16_t base;
+ uint16_t num;
+}_PackedType t_FmIpcResourceAllocParams;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_KG_SCHEMES
+
+ @Description Used by FM PCD front-end in order to allocate KG resources
+
+ @Param[in/out] t_FmPcdIpcKgAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_KG_SCHEMES 3
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_KG_SCHEMES
+
+ @Description Used by FM PCD front-end in order to Free KG resources
+
+ @Param[in/out] t_FmPcdIpcKgSchemesParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_KG_SCHEMES 4
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_PROFILES 5
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_PROFILES
+
+ @Description Used by FM PCD front-end in order to Free Policer profiles
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_PROFILES 6
+
+/**************************************************************************//**
+ @Function FM_PCD_SET_PORT_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+ for specific port
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_SET_PORT_PROFILES 7
+
+/**************************************************************************//**
+ @Function FM_PCD_CLEAR_PORT_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+ for specific port
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_CLEAR_PORT_PROFILES 8
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_PHYS_MURAM_BASE
+
+ @Description Used by FM PCD front-end in order to get MURAM base address
+
+ @Param[in/out] t_FmPcdIcPhysAddr Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_PHYS_MURAM_BASE 9
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_SW_PRS_OFFSET
+
+ @Description Used by FM front-end to get the SW parser offset of the start of
+ code relevant to a given label.
+
+ @Param[in/out] t_FmPcdIpcSwPrsLable Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_SW_PRS_OFFSET 10
+
+/**************************************************************************//**
+ @Function FM_PCD_MASTER_IS_ENABLED
+
+ @Description Used by FM front-end in order to verify
+ PCD enablement.
+
+ @Param[in] bool Pointer
+*//***************************************************************************/
+#define FM_PCD_MASTER_IS_ENABLED 15
+
+/**************************************************************************//**
+ @Function FM_PCD_GUEST_DISABLE
+
+ @Description Used by FM front-end to inform back-end when
+ front-end PCD is disabled
+
+ @Param[in] None
+*//***************************************************************************/
+#define FM_PCD_GUEST_DISABLE 16
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_KG_CLSPLAN
+
+ @Description Used by FM PCD front-end in order to Free KG classification plan entries
+
+ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_KG_CLSPLAN 22
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_KG_CLSPLAN
+
+ @Description Used by FM PCD front-end in order to allocate KG classification plan entries
+
+ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_KG_CLSPLAN 23
+
+/**************************************************************************//**
+ @Function FM_PCD_MASTER_IS_ALIVE
+
+ @Description Used by FM front-end to check that back-end exists
+
+ @Param[in] None
+*//***************************************************************************/
+#define FM_PCD_MASTER_IS_ALIVE 24
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_COUNTER
+
+ @Description Used by FM front-end to read PCD counters
+
+ @Param[in/out] t_FmPcdIpcGetCounter Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_COUNTER 25
+
+/**************************************************************************//**
+ @Function FM_PCD_PRS_INC_PORT_STATS
+
+ @Description Used by FM front-end to set/clear statistics for port
+
+ @Param[in/out] t_FmPcdIpcPrsIncludePort Pointer
+*//***************************************************************************/
+#define FM_PCD_PRS_INC_PORT_STATS 26
+
+#if (DPAA_VERSION >= 11)
+/* TODO - doc */
+#define FM_PCD_ALLOC_SP 27
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/** @} */ /* end of FM_PCD_IPC_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_PCD_IPC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c
new file mode 100644
index 0000000..ded7960
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c
@@ -0,0 +1,1927 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_plcr.c
+
+ @Description FM PCD POLICER...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_pcd_ipc.h"
+#include "fm_plcr.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static uint32_t PlcrProfileLock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags)
+{
+ ASSERT_COND(h_Profile);
+ FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags);
+}
+
+static bool PlcrProfileFlagTryLock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static void PlcrProfileFlagUnlock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock);
+}
+
+static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags);
+}
+
+static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock);
+}
+
+static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags);
+}
+
+static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint16_t i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE);
+
+ for (i=0;i<p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles;i++)
+ if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId)
+ return TRUE;
+ return FALSE;
+}
+
+static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction)
+{
+ uint32_t nia;
+ uint16_t absoluteProfileId;
+ uint8_t relativeSchemeId, physicalSchemeId;
+
+ nia = FM_PCD_PLCR_NIA_VALID;
+
+ switch (nextEngine)
+ {
+ case e_FM_PCD_DONE :
+ switch (p_NextEngineParams->action)
+ {
+ case e_FM_PCD_DROP_FRAME :
+ nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ break;
+ case e_FM_PCD_ENQ_FRAME:
+ nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case e_FM_PCD_KG:
+ physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme."));
+ if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct."));
+ nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId;
+ break;
+ case e_FM_PCD_PLCR:
+ absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId;
+ if (!IsProfileShared(p_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile "));
+ nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ *nextAction = nia;
+
+ return E_OK;
+}
+
+static uint32_t CalcFPP(uint32_t fpp)
+{
+ if (fpp > 15)
+ return 15 - (0x1f - fpp);
+ else
+ return 16 + fpp;
+}
+
+static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode,
+ uint32_t rate,
+ uint64_t tsuInTenthNano,
+ uint32_t fppShift,
+ uint64_t *p_Integer,
+ uint64_t *p_Fraction)
+{
+ uint64_t tmp, div;
+
+ if (rateMode == e_FM_PCD_PLCR_BYTE_MODE)
+ {
+ /* now we calculate the initial integer for the bigger rate */
+ /* from Kbps to Bytes/TSU */
+ tmp = (uint64_t)rate;
+ tmp *= 1000; /* kb --> b */
+ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */
+
+ div = 1000000000; /* nano */
+ div *= 10; /* 10 nano */
+ div *= 8; /* bit to byte */
+ }
+ else
+ {
+ /* now we calculate the initial integer for the bigger rate */
+ /* from Kbps to Bytes/TSU */
+ tmp = (uint64_t)rate;
+ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */
+
+ div = 1000000000; /* nano */
+ div *= 10; /* 10 nano */
+ }
+ *p_Integer = (tmp<<fppShift)/div;
+
+ /* for calculating the fraction, we will recalculate cir and deduct the integer.
+ * For precision, we will multiply by 2^16. we do not divid back, since we write
+ * this value as fraction - see spec.
+ */
+ *p_Fraction = (((tmp<<fppShift)<<16) - ((*p_Integer<<16)*div))/div;
+}
+
+/* .......... */
+
+static void CalcRates(t_Handle h_FmPcd,
+ t_FmPcdPlcrNonPassthroughAlgParams *p_NonPassthroughAlgParam,
+ uint32_t *cir,
+ uint32_t *cbs,
+ uint32_t *pir_eir,
+ uint32_t *pbs_ebs,
+ uint32_t *fpp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint64_t integer, fraction;
+ uint32_t temp, tsuInTenthNanos, bitFor1Micro;
+ uint8_t fppShift=0;
+
+ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); /* TimeStamp per nano seconds units */
+ /* we want the tsu to count 10 nano for better precision normally tsu is 3.9 nano, now we will get 39 */
+ tsuInTenthNanos = (uint32_t)(1000*10/(1<<bitFor1Micro));
+
+ /* we choose the faster rate to calibrate fpp */
+ /* The meaning of this step:
+ * when fppShift is 0 it means all TS bits are treated as integer and TSU is the TS LSB count.
+ * In this configuration we calculate the integer and fraction that represent the higher infoRate
+ * When this is done, we can tell where we have "spare" unused bits and optimize the division of TS
+ * into "integer" and "fraction" where the logic is - as many bits as possible for integer at
+ * high rate, as many bits as possible for fraction at low rate.
+ */
+ if (p_NonPassthroughAlgParam->comittedInfoRate > p_NonPassthroughAlgParam->peakOrAccessiveInfoRate)
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, 0, &integer, &fraction);
+ else
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, 0, &integer, &fraction);
+
+ /* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and
+ * the LSB bits are for the fraction */
+ temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF);
+ /* temp is effected by the rate. For low rates it may be as low as 0, and then we'll
+ * take max FP = 31.
+ * For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is
+ * limited by the 10G physical port.
+ */
+ if (temp != 0)
+ {
+ /* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16
+ * bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits.
+ * The logic is to have as many bits for integer in the higher rates, but if we have "0"s
+ * in the integer part of the cir/pir register, than these bits are wasted. So we want
+ * to use these bits for the fraction. in this way we will have for fraction - the number
+ * of "0" bits and the rest - for integer.
+ * In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS
+ * one bit to the left - preserving the relationship and achieving more bits
+ * for integer in the TS.
+ */
+
+ /* count zeroes left of the higher used bit (in order to shift the value such that
+ * unused bits may be used for fraction).
+ */
+ while ((temp & 0x80000000) == 0)
+ {
+ temp = temp << 1;
+ fppShift++;
+ }
+ if (fppShift > 15)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small"));
+ return;
+ }
+ }
+ else
+ {
+ temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */
+ if (!temp)
+ /* integer and fraction are 0, we set FP to its max val */
+ fppShift = 31;
+ else
+ {
+ /* integer was 0 but fraction is not. FP is 16 for the fraction,
+ * + all left zeroes of the fraction. */
+ fppShift=16;
+ /* count zeroes left of the higher used bit (in order to shift the value such that
+ * unused bits may be used for fraction).
+ */
+ while ((temp & 0x8000) == 0)
+ {
+ temp = temp << 1;
+ fppShift++;
+ }
+ }
+ }
+
+ /*
+ * This means that the FM TS register will now be used so that 'fppShift' bits are for
+ * fraction and the rest for integer */
+ /* now we re-calculate cir and pir_eir with the calculated FP */
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);
+ *cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);
+ *pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));
+
+ *cbs = p_NonPassthroughAlgParam->comittedBurstSize;
+ *pbs_ebs = p_NonPassthroughAlgParam->peakOrAccessiveBurstSize;
+
+ /* convert FP as it should be written to reg.
+ * 0-15 --> 16-31
+ * 16-31 --> 0-15
+ */
+ *fpp = CalcFPP(fppShift);
+}
+
+static void WritePar(t_FmPcd *p_FmPcd, uint32_t par)
+{
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par);
+
+ while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ;
+}
+
+static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd,
+ t_FmPcdPlcrProfileParams *p_ProfileParams,
+ t_FmPcdPlcrProfileRegs *p_PlcrRegs)
+{
+ t_Error err = E_OK;
+ uint32_t pemode, gnia, ynia, rnia;
+
+ ASSERT_COND(p_FmPcd);
+
+/* Set G, Y, R Nia */
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+/* Mode fmpl_pemode */
+ pemode = FM_PCD_PLCR_PEMODE_PI;
+
+ switch (p_ProfileParams->algSelection)
+ {
+ case e_FM_PCD_PLCR_PASS_THROUGH:
+ p_PlcrRegs->fmpl_pecir = 0;
+ p_PlcrRegs->fmpl_pecbs = 0;
+ p_PlcrRegs->fmpl_pepepir_eir = 0;
+ p_PlcrRegs->fmpl_pepbs_ebs = 0;
+ p_PlcrRegs->fmpl_pelts = 0;
+ p_PlcrRegs->fmpl_pects = 0;
+ p_PlcrRegs->fmpl_pepts_ets = 0;
+ pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK;
+ switch (p_ProfileParams->colorMode)
+ {
+ case e_FM_PCD_PLCR_COLOR_BLIND:
+ pemode |= FM_PCD_PLCR_PEMODE_CBLND;
+ switch (p_ProfileParams->color.dfltColor)
+ {
+ case e_FM_PCD_PLCR_GREEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK;
+ break;
+ case e_FM_PCD_PLCR_YELLOW:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y;
+ break;
+ case e_FM_PCD_PLCR_RED:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_R;
+ break;
+ case e_FM_PCD_PLCR_OVERRIDE:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ break;
+ case e_FM_PCD_PLCR_COLOR_AWARE:
+ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+
+ case e_FM_PCD_PLCR_RFC_2698:
+ /* Select algorithm MODE[ALG] = "01" */
+ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698;
+ if (p_ProfileParams->nonPassthroughAlgParams.comittedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrAccessiveInfoRate)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than comittedInfoRate."));
+ goto cont_rfc;
+ case e_FM_PCD_PLCR_RFC_4115:
+ /* Select algorithm MODE[ALG] = "10" */
+ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115;
+cont_rfc:
+ /* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */
+ switch (p_ProfileParams->colorMode)
+ {
+ case e_FM_PCD_PLCR_COLOR_BLIND:
+ pemode |= FM_PCD_PLCR_PEMODE_CBLND;
+ break;
+ case e_FM_PCD_PLCR_COLOR_AWARE:
+ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;
+ /*In color aware more select override color interpretation (MODE[OVCLR]) */
+ switch (p_ProfileParams->color.override)
+ {
+ case e_FM_PCD_PLCR_GREEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK;
+ break;
+ case e_FM_PCD_PLCR_YELLOW:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y;
+ break;
+ case e_FM_PCD_PLCR_RED:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R;
+ break;
+ case e_FM_PCD_PLCR_OVERRIDE:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ /* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */
+ switch (p_ProfileParams->nonPassthroughAlgParams.rateMode)
+ {
+ case e_FM_PCD_PLCR_BYTE_MODE :
+ pemode &= ~FM_PCD_PLCR_PEMODE_PKT;
+ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection)
+ {
+ case e_FM_PCD_PLCR_L2_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L2;
+ break;
+ case e_FM_PCD_PLCR_L3_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L3;
+ break;
+ case e_FM_PCD_PLCR_L4_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L4;
+ break;
+ case e_FM_PCD_PLCR_FULL_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection)
+ {
+ case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS;
+ break;
+ case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_RBFLS;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case e_FM_PCD_PLCR_PACKET_MODE :
+ pemode |= FM_PCD_PLCR_PEMODE_PKT;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ /* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET
+ mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE
+ mode with high traffic rates move the fixed point to the right to increase integer accuracy. */
+
+ /* Configure Traffic Parameters*/
+ {
+ uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0;
+
+ CalcRates(p_FmPcd, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp);
+
+ /* Set Committed Information Rate (CIR) */
+ p_PlcrRegs->fmpl_pecir = cir;
+ /* Set Committed Burst Size (CBS). */
+ p_PlcrRegs->fmpl_pecbs = cbs;
+ /* Set Peak Information Rate (PIR_EIR used as PIR) */
+ p_PlcrRegs->fmpl_pepepir_eir = pir_eir;
+ /* Set Peak Burst Size (PBS_EBS used as PBS) */
+ p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs;
+
+ /* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */
+ /* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */
+ p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF;
+ /* Committed Rate Token Bucket Size (CTS) */
+ p_PlcrRegs->fmpl_pects = 0xFFFFFFFF;
+
+ /* Set the FPP based on calculation */
+ pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT);
+ }
+ break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ p_PlcrRegs->fmpl_pemode = pemode;
+
+ p_PlcrRegs->fmpl_pegnia = gnia;
+ p_PlcrRegs->fmpl_peynia = ynia;
+ p_PlcrRegs->fmpl_pernia = rnia;
+
+ /* Zero Counters */
+ p_PlcrRegs->fmpl_pegpc = 0;
+ p_PlcrRegs->fmpl_peypc = 0;
+ p_PlcrRegs->fmpl_perpc = 0;
+ p_PlcrRegs->fmpl_perypc = 0;
+ p_PlcrRegs->fmpl_perrpc = 0;
+
+ return E_OK;
+}
+
+static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)
+{
+ uint32_t profilesFound;
+ uint16_t i, k=0;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));
+
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+ /* Find numOfProfiles free profiles (may be spread) */
+ profilesFound = 0;
+ for (i=0;i<FM_PCD_PLCR_NUM_ENTRIES; i++)
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ profilesIds[k] = i;
+ k++;
+ if (profilesFound == numOfProfiles)
+ break;
+ }
+
+ if (profilesFound != numOfProfiles)
+ {
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG);
+ }
+
+ for (i = 0;i<k;i++)
+ {
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE;
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0;
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+
+static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)
+{
+ uint16_t i;
+
+ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);
+
+ ASSERT_COND(numOfProfiles);
+
+ for (i=0; i < numOfProfiles; i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated);
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE;
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId;
+ }
+}
+
+/*********************************************/
+/*............Policer Exception..............*/
+/*********************************************/
+static void EventsCB(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, mask, force;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr);
+ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr);
+ if (force & event)
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event);
+
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event);
+
+ if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE);
+ if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE);
+}
+
+/* ..... */
+
+static void ErrorExceptionsCB(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, force, captureReg, mask;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr);
+ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr);
+ if (force & event)
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event);
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event);
+
+ if (event & FM_PCD_PLCR_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC);
+ if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR)
+ {
+ captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr);
+ /*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP);
+ p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK);
+ p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ;
+ p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/
+ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP);
+ }
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdPlcr *p_FmPcdPlcr;
+ uint16_t i=0;
+
+ UNUSED(p_FmPcd);
+ UNUSED(p_FmPcdParams);
+
+ p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr));
+ if (!p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr));
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm));
+ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh;
+ p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions);
+ }
+
+ p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles;
+
+ p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase;
+ p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles;
+ /* for backward compatabilty. if no policer profile, will set automatically to the max */
+ if ((p_FmPcd->guestId == NCSW_MASTER_ID) &&
+ (p_FmPcdPlcr->partNumOfPlcrProfiles == 0))
+ p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES;
+
+ for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; i++)
+ p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+
+ return p_FmPcdPlcr;
+}
+
+t_Error PlcrInit(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ t_Error err = E_OK;
+ uint32_t tmpReg32 = 0;
+ uint16_t base;
+
+ if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!"));
+
+ p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcdPlcr->h_HwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock"));
+
+ p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcdPlcr->h_SwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock"));
+
+ base = PlcrAllocProfilesForPartition(p_FmPcd,
+ p_FmPcdPlcr->partPlcrProfilesBase,
+ p_FmPcdPlcr->partNumOfPlcrProfiles,
+ p_FmPcd->guestId);
+ if (base == (uint16_t)ILLEGAL_BASE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ if (p_FmPcdPlcr->numOfSharedProfiles)
+ {
+ err = AllocSharedProfiles(p_FmPcd,
+ p_FmPcdPlcr->numOfSharedProfiles,
+ p_FmPcdPlcr->sharedProfilesIds);
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+ }
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ return E_OK;
+
+ /**********************FMPL_GCR******************/
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_PLCR_GCR_STEN;
+ if (p_Param->plcrAutoRefresh)
+ tmpReg32 |= FM_PCD_PLCR_GCR_DAR;
+ tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32);
+ /**********************FMPL_GCR******************/
+
+ /**********************FMPL_EEVR******************/
+ WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR));
+ /**********************FMPL_EEVR******************/
+ /**********************FMPL_EIER******************/
+ tmpReg32 = 0;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC)
+ {
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+ tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC;
+ }
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)
+ tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32);
+ /**********************FMPL_EIER******************/
+
+ /**********************FMPL_EVR******************/
+ WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE));
+ /**********************FMPL_EVR******************/
+ /**********************FMPL_IER******************/
+ tmpReg32 = 0;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE)
+ tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE)
+ tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32);
+ /**********************FMPL_IER******************/
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_PLCR,
+ 0,
+ e_FM_INTR_TYPE_ERR,
+ ErrorExceptionsCB,
+ p_FmPcd);
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_PLCR,
+ 0,
+ e_FM_INTR_TYPE_NORMAL,
+ EventsCB,
+ p_FmPcd);
+
+ /* driver initializes one DFLT profile at the last entry*/
+ /**********************FMPL_DPMR******************/
+ tmpReg32 = 0;
+ WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32);
+ p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE;
+
+ return E_OK;
+}
+
+t_Error PlcrFree(t_FmPcd *p_FmPcd)
+{
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR);
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL);
+
+ if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles)
+ FreeSharedProfiles(p_FmPcd,
+ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles,
+ p_FmPcd->p_FmPcdPlcr->sharedProfilesIds);
+
+ if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles)
+ PlcrFreeProfilesForPartition(p_FmPcd,
+ p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase,
+ p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles,
+ p_FmPcd->guestId);
+
+ if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock);
+
+ if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock);
+
+ return E_OK;
+}
+
+void PlcrEnable(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN);
+}
+
+void PlcrDisable(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN);
+}
+
+uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)
+{
+ uint32_t intFlags;
+ uint16_t profilesFound = 0;
+ int i = 0;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr);
+
+ if (!numOfProfiles)
+ return 0;
+
+ if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) ||
+ (base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES))
+ return (uint16_t)ILLEGAL_BASE;
+
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_FmPcd->guestId;
+ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;
+ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;
+ msg.msgId = FM_PCD_ALLOC_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint16_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if ((err != E_OK) ||
+ (replyLength != (sizeof(uint32_t) + sizeof(uint16_t))))
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ else
+ memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t));
+ if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));
+ return (uint16_t)ILLEGAL_BASE;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ for (i=base; i<(base+numOfProfiles); i++)
+ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE)
+ profilesFound++;
+ else
+ break;
+
+ if (profilesFound == numOfProfiles)
+ for (i=base; i<(base+numOfProfiles); i++)
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+
+ return base;
+}
+
+void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)
+{
+ int i = 0;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr);
+
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_FmPcd->guestId;
+ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;
+ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;
+ msg.msgId = FM_PCD_FREE_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));
+ return;
+ }
+
+ for (i=base; i<(base+numOfProfiles); i++)
+ {
+ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId)
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+ else
+ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition"));
+ }
+}
+
+t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfProfiles,
+ uint16_t base)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ uint32_t log2Num, tmpReg32;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_Regs &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = hardwarePortId;
+ ipcAllocParams.num = numOfProfiles;
+ ipcAllocParams.base = base;
+ msg.msgId = FM_PCD_SET_PORT_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Regs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("The requesting port has already an allocated profiles window."));
+
+ /**********************FMPL_PMRx******************/
+ LOG2((uint64_t)numOfProfiles, log2Num);
+ tmpReg32 = base;
+ tmpReg32 |= log2Num << 16;
+ tmpReg32 |= FM_PCD_PLCR_PMR_V;
+ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32);
+
+ return E_OK;
+}
+
+t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_Regs &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = hardwarePortId;
+ msg.msgId = FM_PCD_CLEAR_PORT_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Regs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0);
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ uint32_t profilesFound;
+ uint32_t intFlags;
+ uint16_t i, first, swPortIndex = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ ASSERT_COND(hardwarePortId);
+
+ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));
+
+ if (!POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2."));
+
+ first = 0;
+ profilesFound = 0;
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+
+ for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; )
+ {
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ i++;
+ if (profilesFound == numOfProfiles)
+ break;
+ }
+ else
+ {
+ profilesFound = 0;
+ /* advance i to the next aligned address */
+ i = first = (uint16_t)(first + numOfProfiles);
+ }
+ }
+
+ if (profilesFound == numOfProfiles)
+ {
+ for (i=first; i<first + numOfProfiles; i++)
+ {
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE;
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId;
+ }
+ }
+ else
+ {
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MINOR, E_FULL, ("No profiles."));
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first);
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles;
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first;
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ uint32_t intFlags;
+ uint16_t i, swPortIndex = 0;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId);
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+ for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;
+ i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase +
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles);
+ i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated);
+
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE;
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId;
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0;
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0;
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ uint32_t tmpReg32, intFlags;
+ t_Error err;
+
+ /* Calling function locked all PCD modules, so no need to lock here */
+
+ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range"));
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid"));
+
+ /*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction);
+
+ FmPcdPlcrUpatePointedOwner(p_FmPcd, profileIndx, TRUE);
+ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);
+
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ return err;
+ }
+
+ /* lock the HW because once we read the registers we don't want them to be changed
+ * by another access. (We can copy to a tmp location and release the lock!) */
+
+ intFlags = PlcrHwLock(p_FmPcdPlcr);
+ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));
+
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].pointedOwners ||
+ !(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) ||
+ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) ||
+ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE"));
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;
+ WritePar(p_FmPcd, tmpReg32);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;
+ WritePar(p_FmPcd, tmpReg32);
+
+ }
+ }
+ }
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+
+ FmPcdPlcrUpatePointedOwner(p_FmPcd, profileIndx, TRUE);
+ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);
+
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+
+ return E_OK;
+}
+
+void FmPcdPlcrUpatePointedOwner(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool add)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ if (add)
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners++;
+ else
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners--;
+}
+
+uint32_t FmPcdPlcrGetPointedOwners(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].pointedOwners;
+}
+
+uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction;
+}
+
+bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+
+ ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES);
+
+ return p_FmPcdPlcr->profiles[absoluteProfileId].valid;
+}
+
+void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags;
+
+ ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE;
+ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);
+}
+
+void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE;
+ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);
+}
+
+uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile)
+{
+ return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId;
+}
+
+t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,
+ e_FmPcdProfileTypeSelection profileType,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ uint8_t i;
+
+ switch (profileType)
+ {
+ case e_FM_PCD_PLCR_PORT_PRIVATE:
+ /* get port PCD id from port handle */
+ for (i=0;i<FM_MAX_NUM_OF_PORTS;i++)
+ if (p_FmPcd->p_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort)
+ break;
+ if (i == FM_MAX_NUM_OF_PORTS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle."));
+
+ if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles"));
+ if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));
+ *p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile);
+ break;
+ case e_FM_PCD_PLCR_SHARED:
+ if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));
+ *p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type"));
+ }
+
+ return E_OK;
+}
+
+uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;
+}
+
+uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles;
+
+}
+uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT));
+}
+
+uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |
+ FM_PCD_PLCR_PAR_PWSEL_MASK);
+}
+
+bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg)
+{
+
+ if (profileModeReg & FM_PCD_PLCR_PEMODE_PI)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ FM_PCD_PLCR_PAR_R |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |
+ FM_PCD_PLCR_PAR_PWSEL_MASK);
+}
+
+uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter)
+{
+ switch (counter)
+ {
+ case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER):
+ return FM_PCD_PLCR_PAR_PWSEL_PEGPC;
+ case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER):
+ return FM_PCD_PLCR_PAR_PWSEL_PEYPC;
+ case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERPC;
+ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERYPC;
+ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERRPC;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ return 0;
+ }
+}
+
+uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red)
+{
+
+ uint32_t tmpReg32 = 0;
+
+ if (green)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;
+ if (yellow)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;
+ if (red)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;
+
+ return tmpReg32;
+}
+
+void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/**************************************************/
+/*............Policer API.........................*/
+/**************************************************/
+
+t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!"));
+
+ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t tmpReg32;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!"));
+
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr);
+ if (enable)
+ tmpReg32 |= FM_PCD_PLCR_GCR_STEN;
+ else
+ tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN;
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32);
+ return E_OK;
+}
+
+/* ... */
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gsr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_evr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ier);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ifr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eevr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eier);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eifr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ypcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rrpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rypcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_tpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_flmcnt);
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_serc);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_upcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_dpmr);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr, ("fmpl_pmr"));
+ DUMP_SUBSTRUCT_ARRAY(i, 63)
+ {
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr[i], sizeof(uint32_t));
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd,
+ t_FmPcdPlcrProfileParams *p_ProfileParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+ t_FmPcdPlcrProfileRegs plcrProfileReg;
+ uint32_t intFlags;
+ uint16_t absoluteProfileId;
+ t_Error err = E_OK;
+ uint32_t tmpReg32;
+ t_FmPcdPlcrProfile *p_Profile;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+
+ if (p_ProfileParams->modify)
+ {
+ p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile;
+ p_FmPcd = p_Profile->h_FmPcd;
+ absoluteProfileId = p_Profile->absoluteProfileId;
+ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return NULL;
+ }
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);
+
+ /* Try lock profile using flag */
+ if (!PlcrProfileFlagTryLock(p_Profile))
+ {
+ DBG(TRACE, ("Profile Try Lock - BUSY"));
+ /* Signal to caller BUSY condition */
+ p_ProfileParams->id.h_Profile = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);
+
+ /* SMP: needs to be protected only if another core now changes the windows */
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd,
+ p_ProfileParams->id.newParams.profileType,
+ p_ProfileParams->id.newParams.h_FmPort,
+ p_ProfileParams->id.newParams.relativeProfileId,
+ &absoluteProfileId);
+
+ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return NULL;
+ }
+
+ if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used"));
+ return NULL;
+ }
+
+ /* initialize profile struct */
+ p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId];
+ p_Profile->h_FmPcd = p_FmPcd;
+ p_Profile->absoluteProfileId = absoluteProfileId;
+
+ p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_Profile->p_Lock)
+ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!"));
+ }
+
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL);
+
+ p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen;
+ memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow;
+ memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed;
+ memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs));
+
+ /* build the policer profile registers */
+ err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ if (p_ProfileParams->modify)
+ /* unlock */
+ PlcrProfileFlagUnlock(p_Profile);
+ if (!p_ProfileParams->modify &&
+ p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+ return NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg);
+ if (p_ProfileParams->modify)
+ PlcrProfileFlagUnlock(p_Profile);
+ if (err)
+ {
+ /* release the allocated scheme lock */
+ if (!p_ProfileParams->modify &&
+ p_Profile->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ return NULL;
+ }
+ if (!p_ProfileParams->modify)
+ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);
+ return (t_Handle)p_Profile;
+ }
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL);
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc);
+
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId);
+ WritePar(p_FmPcd, tmpReg32);
+
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ if (!p_ProfileParams->modify)
+ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);
+ else
+ PlcrProfileFlagUnlock(p_Profile);
+
+ return (t_Handle)p_Profile;
+}
+
+t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t tmpReg32, intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx);
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile);
+ if (p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ return err;
+ }
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI);
+
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx);
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ if (p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ return E_OK;
+}
+
+/***************************************************/
+/*............Policer Profile Counter..............*/
+/***************************************************/
+uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t intFlags, counterVal = 0;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter);
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return 0;
+ }
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));
+
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc));
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ break;
+ }
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return counterVal;
+}
+
+t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t tmpReg32, intFlags;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+
+ p_FmPcd = p_Profile->h_FmPcd;
+ profileIndx = p_Profile->absoluteProfileId;
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value);
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE);
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value);
+ break;
+ default:
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ /* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM =
+ * Profile Number, PWSEL=0xFFFF (select all words).
+ */
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter);
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdPlcrProfileRegs *p_ProfilesRegs;
+ uint16_t profileIndx;
+ uint32_t tmpReg, intFlags;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer-profile regs"));
+
+ p_ProfilesRegs = &p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs;
+
+ tmpReg = FmPcdPlcrBuildReadPlcrActionReg((uint16_t)profileIndx);
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WritePar(p_FmPcd, tmpReg);
+
+ DUMP_TITLE(p_ProfilesRegs, ("Profile %d regs", profileIndx));
+
+ DUMP_VAR(p_ProfilesRegs, fmpl_pemode);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pegnia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_peynia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pernia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pecir);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pecbs);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepepir_eir);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepbs_ebs);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pelts);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pects);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepts_ets);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pegpc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_peypc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perpc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perypc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perrpc);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h
new file mode 100644
index 0000000..2bb8b96
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_plcr.h
+
+ @Description FM Policer private header
+*//***************************************************************************/
+#ifndef __FM_PLCR_H
+#define __FM_PLCR_H
+
+#include "std_ext.h"
+
+
+/***********************************************************************/
+/* Policer defines */
+/***********************************************************************/
+
+#define FM_PCD_PLCR_PAR_GO 0x80000000
+#define FM_PCD_PLCR_PAR_PWSEL_MASK 0x0000FFFF
+#define FM_PCD_PLCR_PAR_R 0x40000000
+
+/* shifts */
+#define FM_PCD_PLCR_PAR_PNUM_SHIFT 16
+
+/* masks */
+#define FM_PCD_PLCR_PEMODE_PI 0x80000000
+#define FM_PCD_PLCR_PEMODE_CBLND 0x40000000
+#define FM_PCD_PLCR_PEMODE_ALG_MASK 0x30000000
+#define FM_PCD_PLCR_PEMODE_ALG_RFC2698 0x10000000
+#define FM_PCD_PLCR_PEMODE_ALG_RFC4115 0x20000000
+#define FM_PCD_PLCR_PEMODE_DEFC_MASK 0x0C000000
+#define FM_PCD_PLCR_PEMODE_DEFC_Y 0x04000000
+#define FM_PCD_PLCR_PEMODE_DEFC_R 0x08000000
+#define FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE 0x0C000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_MASK 0x03000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_Y 0x01000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_R 0x02000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_G_NC 0x03000000
+#define FM_PCD_PLCR_PEMODE_PKT 0x00800000
+#define FM_PCD_PLCR_PEMODE_FPP_MASK 0x001F0000
+#define FM_PCD_PLCR_PEMODE_FPP_SHIFT 16
+#define FM_PCD_PLCR_PEMODE_FLS_MASK 0x0000F000
+#define FM_PCD_PLCR_PEMODE_FLS_L2 0x00003000
+#define FM_PCD_PLCR_PEMODE_FLS_L3 0x0000B000
+#define FM_PCD_PLCR_PEMODE_FLS_L4 0x0000E000
+#define FM_PCD_PLCR_PEMODE_FLS_FULL 0x0000F000
+#define FM_PCD_PLCR_PEMODE_RBFLS 0x00000800
+#define FM_PCD_PLCR_PEMODE_TRA 0x00000004
+#define FM_PCD_PLCR_PEMODE_TRB 0x00000002
+#define FM_PCD_PLCR_PEMODE_TRC 0x00000001
+#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000
+#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000
+#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000
+#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000
+
+#define FM_PCD_PLCR_NIA_VALID 0x80000000
+
+#define FM_PCD_PLCR_GCR_EN 0x80000000
+#define FM_PCD_PLCR_GCR_STEN 0x40000000
+#define FM_PCD_PLCR_GCR_DAR 0x20000000
+#define FM_PCD_PLCR_GCR_DEFNIA 0x00FFFFFF
+#define FM_PCD_PLCR_NIA_ABS 0x00000100
+
+#define FM_PCD_PLCR_GSR_BSY 0x80000000
+#define FM_PCD_PLCR_GSR_DQS 0x60000000
+#define FM_PCD_PLCR_GSR_RPB 0x20000000
+#define FM_PCD_PLCR_GSR_FQS 0x0C000000
+#define FM_PCD_PLCR_GSR_LPALG 0x0000C000
+#define FM_PCD_PLCR_GSR_LPCA 0x00003000
+#define FM_PCD_PLCR_GSR_LPNUM 0x000000FF
+
+#define FM_PCD_PLCR_EVR_PSIC 0x80000000
+#define FM_PCD_PLCR_EVR_AAC 0x40000000
+
+#define FM_PCD_PLCR_PAR_PSI 0x20000000
+#define FM_PCD_PLCR_PAR_PNUM 0x00FF0000
+/* PWSEL Selctive select options */
+#define FM_PCD_PLCR_PAR_PWSEL_PEMODE 0x00008000 /* 0 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEGNIA 0x00004000 /* 1 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEYNIA 0x00002000 /* 2 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERNIA 0x00001000 /* 3 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECIR 0x00000800 /* 4 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECBS 0x00000400 /* 5 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPIR_EIR 0x00000200 /* 6 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPBS_EBS 0x00000100 /* 7 */
+#define FM_PCD_PLCR_PAR_PWSEL_PELTS 0x00000080 /* 8 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECTS 0x00000040 /* 9 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPTS_ETS 0x00000020 /* 10 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEGPC 0x00000010 /* 11 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEYPC 0x00000008 /* 12 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERPC 0x00000004 /* 13 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERYPC 0x00000002 /* 14 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERRPC 0x00000001 /* 15 */
+
+#define FM_PCD_PLCR_PAR_PMR_BRN_1TO1 0x0000 /* - Full bit replacement. {PBNUM[0:N-1]
+ 1-> 2^N specific locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_2TO2 0x1 /* - {PBNUM[0:N-2],PNUM[N-1]}.
+ 2-> 2^(N-1) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_4TO4 0x2 /* - {PBNUM[0:N-3],PNUM[N-2:N-1]}.
+ 4-> 2^(N-2) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_8TO8 0x3 /* - {PBNUM[0:N-4],PNUM[N-3:N-1]}.
+ 8->2^(N-3) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_16TO16 0x4 /* - {PBNUM[0:N-5],PNUM[N-4:N-1]}.
+ 16-> 2^(N-4) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_32TO32 0x5 /* {PBNUM[0:N-6],PNUM[N-5:N-1]}.
+ 32-> 2^(N-5) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_64TO64 0x6 /* {PBNUM[0:N-7],PNUM[N-6:N-1]}.
+ 64-> 2^(N-6) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_128TO128 0x7 /* {PBNUM[0:N-8],PNUM[N-7:N-1]}.
+ 128-> 2^(N-7) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_256TO256 0x8 /* - No bit replacement for N=8. {PNUM[N-8:N-1]}.
+ When N=8 this option maps all 256 profiles by the DISPATCH bus into one group. */
+
+#define FM_PCD_PLCR_PMR_V 0x80000000
+#define PLCR_ERR_ECC_CAP 0x80000000
+#define PLCR_ERR_ECC_TYPE_DOUBLE 0x40000000
+#define PLCR_ERR_ECC_PNUM_MASK 0x00000FF0
+#define PLCR_ERR_ECC_OFFSET_MASK 0x0000000F
+
+#define PLCR_ERR_UNINIT_CAP 0x80000000
+#define PLCR_ERR_UNINIT_NUM_MASK 0x000000FF
+#define PLCR_ERR_UNINIT_PID_MASK 0x003f0000
+#define PLCR_ERR_UNINIT_ABSOLUTE_MASK 0x00008000
+
+/* shifts */
+#define PLCR_ERR_ECC_PNUM_SHIFT 4
+#define PLCR_ERR_UNINIT_PID_SHIFT 16
+
+#define FM_PCD_PLCR_PMR_BRN_SHIFT 16
+
+#define PLCR_PORT_WINDOW_SIZE(hardwarePortId)
+
+
+#endif /* __FM_PLCR_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c
new file mode 100644
index 0000000..e198afd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_pcd.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_pcd_ipc.h"
+#include "fm_prs.h"
+#include "fsl_fman_prs.h"
+
+
+static void PcdPrsErrorException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ ev_mask = fman_prs_get_err_ev_mask(PrsRegs);
+
+ event = fman_prs_get_err_event(PrsRegs, ev_mask);
+
+ fman_prs_ack_err_event(PrsRegs, event);
+
+ DBG(TRACE, ("parser error - 0x%08x\n",event));
+
+ if(event & FM_PCD_PRS_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC);
+}
+
+static void PcdPrsException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ ev_mask = fman_prs_get_expt_ev_mask(PrsRegs);
+ event = fman_prs_get_expt_event(PrsRegs, ev_mask);
+
+ ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC);
+
+ DBG(TRACE, ("parser event - 0x%08x\n",event));
+
+ fman_prs_ack_expt_event(PrsRegs, event);
+
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
+}
+
+t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdPrs *p_FmPcdPrs;
+ uintptr_t baseAddr;
+
+ UNUSED(p_FmPcd);
+ UNUSED(p_FmPcdParams);
+
+ p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs));
+ if (!p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs));
+ fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg);
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm);
+ p_FmPcdPrs->p_SwPrsCode = (uint32_t *)UINT_TO_PTR(baseAddr);
+ p_FmPcdPrs->p_FmPcdPrsRegs = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET);
+ }
+
+ p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat;
+ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim;
+ p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions;
+
+ return p_FmPcdPrs;
+}
+
+t_Error PrsInit(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam;
+ uint32_t *p_TmpCode;
+ uint32_t *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode,
+ FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE);
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+#ifdef FM_CAPWAP_SUPPORT
+ uint8_t swPrsPatch[] = SW_PRS_UDP_LITE_PATCH;
+#else
+ uint8_t swPrsPatch[] = SW_PRS_IP_FRAG_PATCH;
+#endif /* FM_CAPWAP_SUPPORT */
+ uint32_t i;
+
+ ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE));
+
+ /* nothing to do in guest-partition */
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ return E_OK;
+
+ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t));
+ if (!p_TmpCode)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
+ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4));
+ memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch));
+
+ fman_prs_init(PrsRegs, &p_Param->dfltCfg);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd);
+
+ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ /* load sw parser Ip-Frag patch */
+ for (i=0; i<DIV_CEIL(sizeof(swPrsPatch),4); i++)
+ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]);
+
+ XX_FreeSmart(p_TmpCode);
+
+ return E_OK;
+}
+
+void PrsFree(t_FmPcd *p_FmPcd)
+{
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR);
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL);
+}
+
+void PrsEnable(t_FmPcd *p_FmPcd)
+{
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ fman_prs_enable(PrsRegs);
+}
+
+void PrsDisable(t_FmPcd *p_FmPcd)
+{
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ fman_prs_disable(PrsRegs);
+}
+
+t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include)
+{
+ struct fman_prs_regs *PrsRegs;
+ uint32_t bitMask = 0;
+ uint8_t prsPortId;
+
+ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId);
+ GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId);
+
+ if (include)
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask;
+ else
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask;
+
+ fman_prs_set_stst_port_msk(PrsRegs,
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics);
+
+ return E_OK;
+}
+
+t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcPrsIncludePort prsIncludePortParams;
+ t_FmPcdIpcMsg msg;
+
+ prsIncludePortParams.hardwarePortId = hardwarePortId;
+ prsIncludePortParams.include = include;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_PRS_INC_PORT_STATS;
+ memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(prsIncludePortParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include);
+}
+
+uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdPrsLabelParams *p_Label;
+ int i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0);
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_Error err = E_OK;
+ t_FmPcdIpcSwPrsLable labelParams;
+ t_FmPcdIpcMsg msg;
+ uint32_t prsOffset = 0;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ labelParams.enumHdr = (uint32_t)hdr;
+ labelParams.indexPerHdr = indexPerHdr;
+ msg.msgId = FM_PCD_GET_SW_PRS_OFFSET;
+ memcpy(msg.msgBody, &labelParams, sizeof(labelParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(labelParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t));
+ return prsOffset;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS);
+
+ for (i=0; i<p_FmPcd->p_FmPcdPrs->currLabel; i++)
+ {
+ p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i];
+
+ if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr))
+ return p_Label->instructionOffset;
+ }
+
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found"));
+ return (uint32_t)ILLEGAL_BASE;
+}
+
+void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_prs_regs *PrsRegs;
+
+ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+
+ if(p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!"));
+ return;
+ }
+
+ fman_prs_set_stst(PrsRegs, enable);
+}
+
+t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t *p_LoadTarget;
+ uint32_t *p_TmpCode;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!"));
+
+ if (!p_SwPrs->override)
+ {
+ if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code"));
+ }
+ else
+ p_FmPcd->p_FmPcdPrs->currLabel = 0;
+
+ if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE"));
+
+ if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed "));
+
+ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t));
+ if (!p_TmpCode)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
+ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4));
+ memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size);
+
+ /* save sw parser labels */
+ memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel],
+ p_SwPrs->labelsTable,
+ p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams));
+ p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels;
+
+ /* load sw parser code */
+ p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4;
+ for(i=0; i<DIV_CEIL(p_SwPrs->size,4); i++)
+ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]);
+ p_FmPcd->p_FmPcdPrs->p_CurrSwPrs =
+ p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4);
+
+ /* copy data parameters */
+ for (i=0;i<FM_PCD_PRS_NUM_OF_HDRS;i++)
+ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]);
+
+ /* Clear last 4 bytes */
+ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0);
+
+ XX_FreeSmart(p_TmpCode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ if(p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!"));
+
+ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value;
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs, ("FM-PCD parser regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpclim);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpimac);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,pmeec);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pevr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pever);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perer);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_ppsc);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pds);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_hxscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_fcscs);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h
new file mode 100644
index 0000000..3e5974c5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_prs.h
+
+ @Description FM Parser private header
+*//***************************************************************************/
+#ifndef __FM_PRS_H
+#define __FM_PRS_H
+
+#include "std_ext.h"
+
+
+/***********************************************************************/
+/* SW parser IP_FRAG patch */
+/***********************************************************************/
+
+
+#ifdef FM_CAPWAP_SUPPORT
+#define SW_PRS_UDP_LITE_PATCH \
+{\
+ 0x31,0x92,0x50,0x29,0x00,0x88,0x08,0x16,0x00,0x00, \
+ 0x00,0x01,0x00,0x05,0x00,0x81,0x1C,0x0B,0x00,0x01, \
+ 0x1B,0xFF, \
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION == 10)
+/* Version: 106.1.9 */
+#define SW_PRS_IP_FRAG_PATCH \
+{ \
+ 0x31,0x52,0x00,0xDA,0x0A,0x00,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x43,0x0A,0x00,0x00,0x00,0x01,0x1B,0xFE, \
+ 0x00,0x00,0x99,0x00,0x53,0x13,0x00,0x00,0x00,0x00, \
+ 0x9F,0x98,0x53,0x13,0x00,0x00,0x1B,0x23,0x33,0xF1, \
+ 0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \
+ 0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x01, \
+ 0x32,0xC1,0x32,0xF0,0x00,0x4A,0x00,0x80,0x1F,0xFF, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x06,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x2F,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x95,0x00,0x00, \
+ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \
+ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x45,0x00,0x00, \
+ 0x30,0x7E,0x43,0x45,0x00,0x3C,0x1B,0x5D,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \
+ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x1B,0x3E,0x30,0x7E,0x53,0x79, \
+ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \
+ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \
+ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \
+ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \
+ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0x90,0x00,0x00, \
+ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \
+ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \
+ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xCF,0x00,0x00, \
+ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \
+ 0x28,0x43,0x30,0x7E,0x43,0xBF,0x00,0x2C,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \
+ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \
+ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \
+ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \
+ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \
+ 0x1B,0x9C,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x32,0xC1,0x32,0xF0,0x00,0x4A, \
+ 0x00,0x80,0x1F,0xFF,0x00,0x01,0x1B,0xFE, \
+}
+
+#else
+/* version: 106.3.13 */
+#define SW_PRS_IP_FRAG_PATCH \
+{ \
+ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x52,0xF6,0x08,0x4B,0x31,0x53,0x00,0xFB, \
+ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \
+ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x0A,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x00,0x00,0x99,0x00,0x53,0x09, \
+ 0x00,0x00,0x00,0x00,0x9F,0x98,0x53,0x09,0x00,0x00, \
+ 0x1B,0x24,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \
+ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \
+ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \
+ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x53,0x3C,0x04,0x4B,0x31,0x53,0x00,0xFB, \
+ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \
+ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x06,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x46,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0xAC,0x00,0x00, \
+ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \
+ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x5C,0x00,0x00, \
+ 0x30,0x7E,0x43,0x5C,0x00,0x3C,0x1B,0x74,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \
+ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x1B,0x55,0x30,0x7E,0x53,0x90, \
+ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \
+ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \
+ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \
+ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \
+ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0xA7,0x00,0x00, \
+ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \
+ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \
+ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xF1,0x00,0x00, \
+ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \
+ 0x28,0x43,0x30,0x7E,0x43,0xD6,0x00,0x2C,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \
+ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \
+ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \
+ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \
+ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \
+ 0x1B,0xB3,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \
+ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \
+ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \
+}
+#endif /* (DPAA_VERSION == 10) */
+
+/****************************/
+/* Parser defines */
+/****************************/
+#define FM_PCD_PRS_SW_TAIL_SIZE 4 /**< Number of bytes that must be cleared at
+ the end of the SW parser area */
+
+/* masks */
+#define PRS_ERR_CAP 0x80000000
+#define PRS_ERR_TYPE_DOUBLE 0x40000000
+#define PRS_ERR_SINGLE_ECC_CNT_MASK 0x00FF0000
+#define PRS_ERR_ADDR_MASK 0x000001FF
+
+/* others */
+#define PRS_MAX_CYCLE_LIMIT 8191
+#define PRS_SW_DATA 0x00000800
+#define PRS_REGS_OFFSET 0x00000840
+
+#define GET_FM_PCD_PRS_PORT_ID(prsPortId,hardwarePortId) \
+ prsPortId = (uint8_t)(hardwarePortId & 0x0f)
+
+#define GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId) \
+ bitMask = 0x80000000>>prsPortId
+
+
+#endif /* __FM_PRS_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c
new file mode 100644
index 0000000..ae72b25
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c
@@ -0,0 +1,993 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_replic.c
+
+ @Description FM frame replicator
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_common.h"
+#include "fm_hc.h"
+#include "fm_replic.h"
+#include "fm_cc.h"
+#include "list_ext.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+static uint8_t GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint32_t memberIndex,
+ bool isAddOperation)
+{
+ uint8_t memberPosition;
+ uint32_t lastMemberIndex;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ /* the last member index is different between add and remove operation -
+ in case of remove - this is exactly the last member index
+ in case of add - this is the last member index + 1 - e.g.
+ if we have 4 members, the index of the actual last member is 3(because the
+ index starts from 0) therefore in order to add a new member as the last
+ member we shall use memberIndex = 4 and not 3
+ */
+ if (isAddOperation)
+ lastMemberIndex = p_ReplicGroup->numOfEntries;
+ else
+ lastMemberIndex = p_ReplicGroup->numOfEntries-1;
+
+ /* last */
+ if (memberIndex == lastMemberIndex)
+ memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX;
+ else
+ {
+ /* first */
+ if (memberIndex == 0)
+ memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX;
+ else
+ {
+ /* middle */
+ ASSERT_COND(memberIndex < lastMemberIndex);
+ memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX;
+ }
+ }
+ return memberPosition;
+}
+
+static t_Error MemberCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNextEngineParams *p_MemberParams)
+{
+ t_Error err;
+
+
+ if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) &&
+ (p_MemberParams->nextEngine != e_FM_PCD_KG) &&
+ (p_MemberParams->nextEngine != e_FM_PCD_PLCR))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer"));
+
+ /* check the regular parameters of the next engine */
+ err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("member next engine parameters"));
+
+ return E_OK;
+}
+
+static t_Error CheckParams(t_Handle h_FmPcd,
+ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
+{
+ int i;
+ t_Error err;
+
+ /* check that max num of entries is at least 2 */
+ if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES))
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
+
+ /* check that number of entries is greater than zero */
+ if (!p_ReplicGroupParam->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero"));
+
+ /* check that max num of entries is equal or greater than number of entries */
+ if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries"));
+
+ for (i=0; i<p_ReplicGroupParam->numOfEntries; i++)
+ {
+ err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("member check parameters"));
+ }
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ t_FmPcdFrmReplicMember *p_ReplicMember = NULL;
+ t_List *p_Next;
+
+ if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList))
+ {
+ p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList);
+ p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node);
+ ASSERT_COND(p_ReplicMember);
+ LIST_DelAndInit(p_Next);
+ }
+ return p_ReplicMember;
+}
+
+static void PutAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_ReplicMember)
+{
+ LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList);
+}
+
+static void AddMemberToList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ t_List *p_ListHead)
+{
+ LIST_Add(&p_CurrentMember->node, p_ListHead);
+
+ p_ReplicGroup->numOfEntries++;
+}
+
+static void RemoveMemberFromList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember)
+{
+ ASSERT_COND(p_ReplicGroup->numOfEntries);
+ LIST_DelAndInit(&p_CurrentMember->node);
+ p_ReplicGroup->numOfEntries--;
+}
+
+static void LinkSourceToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_AdOfTypeContLookup *p_SourceTd,
+ t_FmPcdFrmReplicMember *p_ReplicMember)
+{
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_SourceTd);
+ ASSERT_COND(p_ReplicMember);
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+
+ /* Link the first member in the group to the source TD */
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+
+ WRITE_UINT32(p_SourceTd->matchTblPtr,
+ (uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) -
+ p_FmPcd->physicalMuramBase));
+}
+
+static void LinkMemberToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ t_FmPcdFrmReplicMember *p_NextMember)
+{
+ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd;
+ t_AdOfTypeResult *p_NextReplicAd = NULL;
+ t_FmPcd *p_FmPcd;
+ uint32_t offset = 0;
+
+ /* Check if the next member exists or it's NULL (- means that this is the last member) */
+ if (p_NextMember)
+ {
+ p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd;
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase));
+ offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT);
+ }
+
+ /* link the current AD to point to the AD of the next member */
+ WRITE_UINT32(p_CurrReplicAd->res, offset);
+}
+
+static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ void *p_OldDescriptor,
+ void *p_NewDescriptor)
+{
+ t_Handle h_Hc;
+ t_Error err;
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(p_OldDescriptor);
+ ASSERT_COND(p_NewDescriptor);
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ h_Hc = FmPcdGetHcHandle(p_FmPcd);
+ if (!h_Hc)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command"));
+
+ err = FmHcPcdCcDoDynamicChange(h_Hc,
+ (uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase),
+ (uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Dynamic change host command"));
+
+ return E_OK;
+}
+
+static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last)
+{
+ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd;
+ uint32_t tmp;
+
+ tmp = GET_UINT32(p_CurrReplicAd->plcrProfile);
+ if (last)
+ /* clear the NL bit in case it's the last member in the group*/
+ WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT));
+ else
+ /* set the NL bit in case it's not the last member in the group */
+ WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT));
+
+ /* set FR bit in the action descriptor */
+ tmp = GET_UINT32(p_CurrReplicAd->nia);
+ WRITE_UINT32(p_CurrReplicAd->nia,
+ (tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE ));
+}
+
+static void BuildSourceTd(void *p_Ad)
+{
+ t_AdOfTypeContLookup *p_SourceTd;
+
+ ASSERT_COND(p_Ad);
+
+ p_SourceTd = (t_AdOfTypeContLookup *)p_Ad;
+
+ IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* initialize the source table descriptor */
+ WRITE_UINT32(p_SourceTd->ccAdBase, FM_PCD_AD_CONT_LOOKUP_TYPE);
+ WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE);
+}
+
+static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_NextMember,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ bool sourceDescriptor,
+ bool last)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdFrmReplicMember shadowMember;
+ t_Error err;
+
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ ASSERT_COND(p_FmPcd->p_CcShadow);
+
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ return ERROR_CODE(E_BUSY);
+
+ if (sourceDescriptor)
+ {
+ BuildSourceTd(p_FmPcd->p_CcShadow);
+ LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember);
+
+ /* Modify the source table descriptor according to the prepared shadow descriptor */
+ err = ModifyDescriptor(p_ReplicGroup,
+ p_ReplicGroup->p_SourceTd,
+ p_FmPcd->p_CcShadow/* new prepared source td */);
+
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor"));
+
+ }
+ else
+ {
+ IO2IOCpy32(p_FmPcd->p_CcShadow,
+ p_CurrentMember->p_MemberAd,
+ FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* update the last bit in the shadow ad */
+ FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last);
+
+ shadowMember.p_MemberAd = p_FmPcd->p_CcShadow;
+
+ /* update the next FR member index */
+ LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember);
+
+ /* Modify the next member according to the prepared shadow descriptor */
+ err = ModifyDescriptor(p_ReplicGroup,
+ p_CurrentMember->p_MemberAd,
+ p_FmPcd->p_CcShadow);
+
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor"));
+ }
+
+
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint16_t memberIndex)
+{
+ int i=0;
+ t_List *p_Pos;
+ t_FmPcdFrmReplicMember *p_Member = NULL;
+
+ LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList)
+ {
+ if (i == memberIndex)
+ {
+ p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node);
+ return p_Member;
+ }
+ i++;
+ }
+ return p_Member;
+}
+
+static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ t_FmPcdFrmReplicMember *p_CurrentMember;
+ t_Handle h_Muram;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* Initialize an internal structure of a member to add to the available members list */
+ p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember));
+ if (!p_CurrentMember)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member"));
+
+ memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember));
+
+ /* Allocate the member AD */
+ p_CurrentMember->p_MemberAd =
+ (t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ if (!p_CurrentMember->p_MemberAd)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table"));
+
+ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Add the new member to the available members list */
+ LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList));
+
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdCcNextEngineParams *p_MemberParams,
+ bool last)
+{
+ t_FmPcdFrmReplicMember *p_CurrentMember = NULL;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ /* Get an available member from the internal members list */
+ p_CurrentMember = GetAvailableMember(p_ReplicGroup);
+ if (!p_CurrentMember)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member"));
+ return NULL;
+ }
+ p_CurrentMember->h_Manip = NULL;
+
+ /* clear the Ad of the new member */
+ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ INIT_LIST(&p_CurrentMember->node);
+
+ /* Initialize the Ad of the member */
+ NextStepAd(p_CurrentMember->p_MemberAd,
+ NULL,
+ p_MemberParams,
+ p_ReplicGroup->h_FmPcd);
+
+ /* save Manip handle (for free needs) */
+ if (p_MemberParams->h_Manip)
+ p_CurrentMember->h_Manip = p_MemberParams->h_Manip;
+
+ /* Initialize the relevant frame replicator fields in the AD */
+ FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last);
+
+ return p_CurrentMember;
+}
+
+static void FreeMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_Member)
+{
+ /* Note: Can't free the member AD just returns the member to the available
+ member list - therefore only memset the AD */
+
+ /* zero the AD */
+ IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+
+ /* return the member to the available members list */
+ PutAvailableMember(p_ReplicGroup, p_Member);
+}
+
+static t_Error RemoveMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint16_t memberIndex)
+{
+ t_FmPcd *p_FmPcd = NULL;
+ t_FmPcdFrmReplicMember *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL;
+ t_Error err;
+ uint8_t memberPosition;
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ /* determine the member position in the group */
+ memberPosition = GetMemberPosition(p_ReplicGroup,
+ memberIndex,
+ FALSE/*remove operation*/);
+
+ switch (memberPosition)
+ {
+ case FRM_REPLIC_FIRST_MEMBER_INDEX:
+ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
+ ASSERT_COND(p_NextMember);
+
+ /* update the source td itself by using a host command */
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ p_NextMember,
+ NULL,
+ TRUE/*sourceDescriptor*/,
+ FALSE/*last*/);
+ break;
+
+ case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
+ ASSERT_COND(p_NextMember);
+
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ p_NextMember,
+ p_PreviousMember,
+ FALSE/*sourceDescriptor*/,
+ FALSE/*last*/);
+
+ break;
+
+ case FRM_REPLIC_LAST_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ NULL,
+ p_PreviousMember,
+ FALSE/*sourceDescriptor*/,
+ TRUE/*last*/);
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member"));
+ }
+
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_CurrentMember->h_Manip)
+ {
+ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
+ p_CurrentMember->h_Manip = NULL;
+ }
+
+ /* remove the member from the driver internal members list */
+ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
+
+ /* return the member to the available members list */
+ FreeMember(p_ReplicGroup, p_CurrentMember);
+
+ return E_OK;
+}
+
+static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ int i, j;
+ t_Handle h_Muram;
+ t_FmPcdFrmReplicMember *p_Member, *p_CurrentMember;
+
+ if (p_ReplicGroup)
+ {
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* free the source table descriptor */
+ if (p_ReplicGroup->p_SourceTd)
+ {
+ FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd);
+ p_ReplicGroup->p_SourceTd = NULL;
+ }
+
+ /* Remove all members from the members linked list (hw and sw) and
+ return the members to the available members list */
+ if (p_ReplicGroup->numOfEntries)
+ {
+ j = p_ReplicGroup->numOfEntries-1;
+
+ /* manually removal of the member because there are no owners of
+ this group */
+ for (i=j; i>=0; i--)
+ {
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/);
+ ASSERT_COND(p_CurrentMember);
+
+ if (p_CurrentMember->h_Manip)
+ {
+ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
+ p_CurrentMember->h_Manip = NULL;
+ }
+
+ /* remove the member from the internal driver members list */
+ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
+
+ /* return the member to the available members list */
+ FreeMember(p_ReplicGroup, p_CurrentMember);
+ }
+ }
+
+ /* Free members AD */
+ for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
+ {
+ p_Member = GetAvailableMember(p_ReplicGroup);
+ ASSERT_COND(p_Member);
+ if (p_Member->p_MemberAd)
+ {
+ FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd);
+ p_Member->p_MemberAd = NULL;
+ }
+ XX_Free(p_Member);
+ }
+
+ /* release the group lock */
+ if (p_ReplicGroup->p_Lock)
+ FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock);
+
+ /* free the replicator group */
+ XX_Free(p_ReplicGroup);
+ p_ReplicGroup = NULL;
+ }
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+/* NOTE: the inter-module routines are locked by cc in case of using them */
+void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ ASSERT_COND(p_ReplicGroup);
+
+ return (p_ReplicGroup->p_SourceTd);
+}
+
+void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup,
+ void *p_Ad,
+ t_Handle *h_AdNew)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult*)p_Ad;
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_ReplicGroup);
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+
+ /* build a bypass ad */
+ WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE |
+ (uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase));
+
+ *h_AdNew = NULL;
+}
+
+void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup,
+ bool add)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ ASSERT_COND(p_ReplicGroup);
+
+ /* update the group owner counter */
+ if (add)
+ p_ReplicGroup->owners++;
+ else
+ {
+ ASSERT_COND(p_ReplicGroup->owners);
+ p_ReplicGroup->owners--;
+ }
+}
+
+t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ ASSERT_COND(h_ReplicGroup);
+
+ if (FmPcdLockTryLock(p_ReplicGroup->p_Lock))
+ return E_OK;
+
+ return ERROR_CODE(E_BUSY);
+}
+
+void FrmReplicGroupUnlock(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ ASSERT_COND(h_ReplicGroup);
+
+ FmPcdLockUnlock(p_ReplicGroup->p_Lock);
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd,
+ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup;
+ t_FmPcdFrmReplicMember *p_CurrentMember, *p_NextMember = NULL;
+ int i;
+ t_Error err;
+ bool last = FALSE;
+ t_Handle h_Muram;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL);
+
+ if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
+ return NULL;
+ }
+
+ err = CheckParams(h_FmPcd, p_ReplicGroupParam);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, (NO_MSG));
+ return NULL;
+ }
+
+ p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup));
+ if (!p_ReplicGroup)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup));
+
+ /* initialize lists for internal driver use */
+ INIT_LIST(&p_ReplicGroup->availableMembersList);
+ INIT_LIST(&p_ReplicGroup->membersList);
+
+ p_ReplicGroup->h_FmPcd = h_FmPcd;
+
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* initialize the group lock */
+ p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd);
+ if (!p_ReplicGroup->p_Lock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* Allocate the frame replicator source table descriptor */
+ p_ReplicGroup->p_SourceTd =
+ (t_Handle)FM_MURAM_AllocMem(h_Muram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_ReplicGroup->p_SourceTd)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* update the shadow size - required for the host commands */
+ err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, ("Update CC shadow"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ p_ReplicGroup->maxNumOfEntries = p_ReplicGroupParam->maxNumOfEntries;
+
+ /* Allocate the maximal number of members ADs and Statistics AD for the group
+ It prevents allocation of Muram in run-time */
+ for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
+ {
+ err = AllocMember(p_ReplicGroup);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, ("allocate a new member"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+ }
+
+ /* Initialize the members linked lists:
+ (hw - the one that is used by the FMan controller and
+ sw - the one that is managed by the driver internally) */
+ for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--)
+ {
+ /* check if this is the last member in the group */
+ if (i == (p_ReplicGroupParam->numOfEntries-1))
+ last = TRUE;
+ else
+ last = FALSE;
+
+ /* Initialize a new member */
+ p_CurrentMember = InitMember(p_ReplicGroup,
+ &(p_ReplicGroupParam->nextEngineParams[i]),
+ last);
+ if (!p_CurrentMember)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* Build the members group - link two consecutive members in the hw linked list */
+ LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember);
+
+ /* update the driver internal members list to be compatible to the hw members linked list */
+ AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList);
+
+ p_NextMember = p_CurrentMember;
+ }
+
+ /* initialize the source table descriptor */
+ BuildSourceTd(p_ReplicGroup->p_SourceTd);
+
+ /* link the source table descriptor to point to the first member in the group */
+ LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember);
+
+ return p_ReplicGroup;
+}
+
+t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+
+ if (p_ReplicGroup->owners)
+ RETURN_ERROR(MAJOR,
+ E_INVALID_STATE,
+ ("the group has owners and can't be deleted"));
+
+ DeleteGroup(p_ReplicGroup);
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* API Run-time Frame replicator Control unit functions */
+/*****************************************************************************/
+t_Error FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup,
+ uint16_t memberIndex,
+ t_FmPcdCcNextEngineParams *p_MemberParams)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
+ t_FmPcdFrmReplicMember *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL;
+ t_Error err;
+ uint8_t memberPosition;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE);
+
+ /* group lock */
+ err = FrmReplicGroupTryLock(p_ReplicGroup);
+ if (err)
+ {
+ if (GET_ERROR_TYPE(err) == E_BUSY)
+ return ERROR_CODE(E_BUSY);
+ else
+ RETURN_ERROR(MAJOR, err, ("try lock in Add member"));
+ }
+
+ if (memberIndex > p_ReplicGroup->numOfEntries)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("memberIndex is greater than the members in the list"));
+ }
+
+ if (memberIndex >= p_ReplicGroup->maxNumOfEntries)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group"));
+ }
+
+ if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfEntries with new entry can not be larger than %d\n",
+ FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
+ }
+
+ err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams);
+ if (err)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, err, ("member check parameters in add operation"));
+ }
+ /* determine the member position in the group */
+ memberPosition = GetMemberPosition(p_ReplicGroup,
+ memberIndex,
+ TRUE/* add operation */);
+
+ /* Initialize a new member */
+ p_NewMember = InitMember(p_ReplicGroup,
+ p_MemberParams,
+ (memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE));
+ if (!p_NewMember)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
+ }
+
+ switch (memberPosition)
+ {
+ case FRM_REPLIC_FIRST_MEMBER_INDEX:
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
+
+ /* update the internal group source TD */
+ LinkSourceToMember(p_ReplicGroup,
+ p_ReplicGroup->p_SourceTd,
+ p_NewMember);
+
+ /* add member to the internal sw member list */
+ AddMemberToList(p_ReplicGroup,
+ p_NewMember,
+ &p_ReplicGroup->membersList);
+ break;
+
+ case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
+ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
+
+ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
+ break;
+
+ case FRM_REPLIC_LAST_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
+ FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/);
+
+ /* add the new member to the internal sw member list */
+ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
+ break;
+
+ default:
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member"));
+
+ }
+
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup,
+ uint16_t memberIndex)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+
+ /* lock */
+ err = FrmReplicGroupTryLock(p_ReplicGroup);
+ if (err)
+ {
+ if (GET_ERROR_TYPE(err) == E_BUSY)
+ return ERROR_CODE(E_BUSY);
+ else
+ RETURN_ERROR(MAJOR, err, ("try lock in Remove member"));
+ }
+
+ if (memberIndex >= p_ReplicGroup->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove"));
+
+ /* Design decision: group must contain at least one member
+ No possibility to remove the last member from the group */
+ if (p_ReplicGroup->numOfEntries == 1)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group."));
+
+ err = RemoveMember(p_ReplicGroup, memberIndex);
+
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+/*********************** End of API routines ************************/
+
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h
new file mode 100644
index 0000000..3cfd67e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_replic.h
+
+ @Description FM frame replicator
+*//***************************************************************************/
+#ifndef __FM_REPLIC_H
+#define __FM_REPLIC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+
+
+#define FRM_REPLIC_SOURCE_TD_OPCODE 0x75
+#define NEXT_FRM_REPLIC_ADDR_SHIFT 4
+#define NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT 16
+#define FRM_REPLIC_FR_BIT 0x08000000
+#define FRM_REPLIC_NL_BIT 0x10000000
+#define FRM_REPLIC_INVALID_MEMBER_INDEX 0xffff
+#define FRM_REPLIC_FIRST_MEMBER_INDEX 0
+
+#define FRM_REPLIC_MIDDLE_MEMBER_INDEX 1
+#define FRM_REPLIC_LAST_MEMBER_INDEX 2
+
+#define SOURCE_TD_ITSELF_OPTION 0x01
+#define SOURCE_TD_COPY_OPTION 0x02
+#define SOURCE_TD_ITSELF_AND_COPY_OPTION SOURCE_TD_ITSELF_OPTION | SOURCE_TD_COPY_OPTION
+#define SOURCE_TD_NONE 0x04
+
+/*typedef enum e_SourceTdOption
+{
+ e_SOURCE_TD_NONE = 0,
+ e_SOURCE_TD_ITSELF_OPTION = 1,
+ e_SOURCE_TD_COPY_OPTION = 2,
+ e_SOURCE_TD_ITSELF_AND_COPY_OPTION = e_SOURCE_TD_ITSELF_OPTION | e_SOURCE_TD_COPY_OPTION
+} e_SourceTdOption;
+*/
+
+typedef _Packed struct
+{
+ volatile uint32_t type;
+ volatile uint32_t frGroupPointer;
+ volatile uint32_t operationCode;
+ volatile uint32_t reserved;
+} _PackedType t_FrmReplicGroupSourceAd;
+
+typedef struct t_FmPcdFrmReplicMember
+{
+ void *p_MemberAd; /**< pointer to the member AD */
+ void *p_StatisticsAd;/**< pointer to the statistics AD of the member */
+ t_Handle h_Manip; /**< manip handle - need for free routines */
+ t_List node;
+} t_FmPcdFrmReplicMember;
+
+typedef struct t_FmPcdFrmReplicGroup
+{
+ t_Handle h_FmPcd;
+#ifdef UNDER_CONSTRUCTION_STATISTICS_SUPPORT
+ e_FmPcdCcStatsMode statisticsMode;
+#endif /* UNDER_CONSTRUCTION_STATISTICS_SUPPORT */
+
+ uint8_t maxNumOfEntries;/**< maximal number of members in the group */
+ uint8_t numOfEntries; /**< actual number of members in the group */
+ uint16_t owners; /**< how many keys share this frame replicator group */
+ void *p_SourceTd; /**< pointer to the frame replicator source table descriptor */
+ t_List membersList; /**< the members list - should reflect the order of the members as in the hw linked list*/
+ t_List availableMembersList;/**< list of all the available members in the group */
+ t_FmPcdLock *p_Lock;
+} t_FmPcdFrmReplicGroup;
+
+
+#endif /* __FM_REPLIC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c
new file mode 100644
index 0000000..6e77c9386
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include "fsl_fman_kg.h"
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+
+static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write)
+{
+ uint32_t rw;
+
+ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hwport_id |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id)
+{
+ uint32_t ar;
+
+ fman_kg_write_sp(regs, 0xffffffff, 0);
+
+ ar = build_ar_bind_scheme(hwport_id, TRUE);
+ fman_kg_write_ar_wait(regs, ar);
+}
+
+static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write)
+{
+ uint32_t rw;
+
+ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hwport_id |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
+}
+
+static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id)
+{
+ uint32_t ar;
+
+ fman_kg_write_cpp(regs, 0);
+
+ ar = build_ar_bind_cls_plan(hwport_id, TRUE);
+ fman_kg_write_ar_wait(regs, ar);
+}
+
+static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src,
+ bool no_validation,
+ uint8_t *offset)
+{
+ int code;
+
+ switch (src) {
+ case E_FMAN_KG_GEN_EXTRACT_ETH:
+ code = no_validation ? 0x73 : 0x3;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_ETYPE:
+ code = no_validation ? 0x77 : 0x7;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SNAP:
+ code = no_validation ? 0x74 : 0x4;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1:
+ code = no_validation ? 0x75 : 0x5;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N:
+ code = no_validation ? 0x76 : 0x6;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_PPPoE:
+ code = no_validation ? 0x78 : 0x8;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_1:
+ code = no_validation ? 0x79 : 0x9;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_2:
+ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_3:
+ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_N:
+ code = no_validation ? 0x7a : 0xa;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv4_1:
+ code = no_validation ? 0x7b : 0xb;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv6_1:
+ code = no_validation ? 0x7b : 0x1b;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv4_2:
+ code = no_validation ? 0x7c : 0xc;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv6_2:
+ code = no_validation ? 0x7c : 0x1c;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MINENCAP:
+ code = no_validation ? 0x7c : 0x2c;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IP_PID:
+ code = no_validation ? 0x72 : 0x2;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_GRE:
+ code = no_validation ? 0x7d : 0xd;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_TCP:
+ code = no_validation ? 0x7e : 0xe;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_UDP:
+ code = no_validation ? 0x7e : 0x1e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SCTP:
+ code = no_validation ? 0x7e : 0x3e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_DCCP:
+ code = no_validation ? 0x7e : 0x4e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH:
+ code = no_validation ? 0x7e : 0x2e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP:
+ code = no_validation ? 0x7e : 0x6e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SHIM_1:
+ code = 0x70;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SHIM_2:
+ code = 0x71;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT:
+ code = 0x10;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START:
+ code = 0x40;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT:
+ code = 0x20;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE:
+ code = 0x7f;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_FQID:
+ code = 0x20;
+ *offset += 0x20;
+ break;
+
+ default:
+ code = FM_KG_SCH_GEN_HT_INVALID;
+ }
+
+ return (uint8_t)code;
+}
+
+static uint32_t build_ar_scheme(uint8_t scheme,
+ uint8_t hwport_id,
+ bool update_counter,
+ bool write)
+{
+ uint32_t rw;
+
+ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ hwport_id |
+ ((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) |
+ (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));
+}
+
+static uint32_t build_ar_cls_plan(uint8_t grp,
+ uint8_t entries_mask,
+ uint8_t hwport_id,
+ bool write)
+{
+ uint32_t rw;
+
+ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ hwport_id |
+ ((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) |
+ ((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT));
+}
+
+int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar)
+{
+ iowrite32be(fmkg_ar, &regs->fmkg_ar);
+ /* Wait for GO to be idle and read error */
+ while ((fmkg_ar = ioread32be(&regs->fmkg_ar)) & FM_KG_KGAR_GO) ;
+ if (fmkg_ar & FM_PCD_KG_KGAR_ERR)
+ return -EINVAL;
+ return 0;
+}
+
+void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add)
+{
+
+ struct fman_kg_pe_regs *kgpe_regs;
+ uint32_t tmp;
+
+ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+ tmp = ioread32be(&kgpe_regs->fmkg_pe_sp);
+
+ if (add)
+ tmp |= sp;
+ else /* clear */
+ tmp &= ~sp;
+
+ iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp);
+
+}
+
+void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp)
+{
+ struct fman_kg_pe_regs *kgpe_regs;
+
+ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp);
+}
+
+void fman_kg_get_event(struct fman_kg_regs *regs,
+ uint32_t *event,
+ uint32_t *scheme_idx)
+{
+ uint32_t mask, force;
+
+ *event = ioread32be(&regs->fmkg_eer);
+ mask = ioread32be(&regs->fmkg_eeer);
+ *scheme_idx = ioread32be(&regs->fmkg_seer);
+ *scheme_idx &= ioread32be(&regs->fmkg_seeer);
+
+ *event &= mask;
+
+ /* clear the forced events */
+ force = ioread32be(&regs->fmkg_feer);
+ if (force & *event)
+ iowrite32be(force & ~*event ,&regs->fmkg_feer);
+
+ iowrite32be(*event, &regs->fmkg_eer);
+ iowrite32be(*scheme_idx, &regs->fmkg_seer);
+}
+
+
+void fman_kg_init(struct fman_kg_regs *regs,
+ uint32_t exceptions,
+ uint32_t dflt_nia)
+{
+ uint32_t tmp;
+ int i;
+
+ iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,
+ &regs->fmkg_eer);
+
+ tmp = 0;
+ if (exceptions & FM_EX_KG_DOUBLE_ECC)
+ tmp |= FM_EX_KG_DOUBLE_ECC;
+
+ if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)
+ tmp |= FM_EX_KG_KEYSIZE_OVERFLOW;
+
+ iowrite32be(tmp, &regs->fmkg_eeer);
+ iowrite32be(0, &regs->fmkg_fdor);
+ iowrite32be(0, &regs->fmkg_gdv0r);
+ iowrite32be(0, &regs->fmkg_gdv1r);
+ iowrite32be(dflt_nia, &regs->fmkg_gcr);
+
+ /* Clear binding between ports to schemes and classification plans
+ * so that all ports are not bound to any scheme/classification plan */
+ for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {
+ clear_pe_all_scheme(regs, (uint8_t)i);
+ clear_pe_all_cls_plan(regs, (uint8_t)i);
+ }
+}
+
+void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs)
+{
+ /* enable and enable all scheme interrupts */
+ iowrite32be(0xFFFFFFFF, &regs->fmkg_seer);
+ iowrite32be(0xFFFFFFFF, &regs->fmkg_seeer);
+}
+
+void fman_kg_enable(struct fman_kg_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->fmkg_gcr) | FM_KG_KGGCR_EN,
+ &regs->fmkg_gcr);
+}
+
+void fman_kg_disable(struct fman_kg_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->fmkg_gcr) & ~FM_KG_KGGCR_EN,
+ &regs->fmkg_gcr);
+}
+
+void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset)
+{
+ iowrite32be(offset, &regs->fmkg_fdor);
+}
+
+void fman_kg_set_dflt_val(struct fman_kg_regs *regs,
+ uint8_t def_id,
+ uint32_t val)
+{
+ if(def_id == 0)
+ iowrite32be(val, &regs->fmkg_gdv0r);
+ else
+ iowrite32be(val, &regs->fmkg_gdv1r);
+}
+
+
+void fman_kg_set_exception(struct fman_kg_regs *regs,
+ uint32_t exception,
+ bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmkg_eeer);
+
+ if (enable) {
+ tmp |= exception;
+ } else {
+ tmp &= ~exception;
+ }
+
+ iowrite32be(tmp, &regs->fmkg_eeer);
+}
+
+void fman_kg_get_exception(struct fman_kg_regs *regs,
+ uint32_t *events,
+ uint32_t *scheme_ids,
+ bool clear)
+{
+ uint32_t mask;
+
+ *events = ioread32be(&regs->fmkg_eer);
+ mask = ioread32be(&regs->fmkg_eeer);
+ *events &= mask;
+
+ *scheme_ids = 0;
+
+ if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) {
+ *scheme_ids = ioread32be(&regs->fmkg_seer);
+ mask = ioread32be(&regs->fmkg_seeer);
+ *scheme_ids &= mask;
+ }
+
+ if (clear) {
+ iowrite32be(*scheme_ids, &regs->fmkg_seer);
+ iowrite32be(*events, &regs->fmkg_eer);
+ }
+}
+
+void fman_kg_get_capture(struct fman_kg_regs *regs,
+ struct fman_kg_ex_ecc_attr *ecc_attr,
+ bool clear)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmkg_serc);
+
+ if (tmp & KG_FMKG_SERC_CAP) {
+ /* Captured data is valid */
+ ecc_attr->valid = TRUE;
+ ecc_attr->double_ecc =
+ (bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE);
+ ecc_attr->single_ecc_count =
+ (uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >>
+ KG_FMKG_SERC_CNT_SHIFT);
+ ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK);
+
+ if (clear)
+ iowrite32be(KG_FMKG_SERC_CAP, &regs->fmkg_serc);
+ } else {
+ /* No ECC error is captured */
+ ecc_attr->valid = FALSE;
+ }
+}
+
+int fman_kg_build_scheme(struct fman_kg_scheme_params *params,
+ struct fman_kg_scheme_regs *scheme_regs)
+{
+ struct fman_kg_extract_params *extract_params;
+ struct fman_kg_gen_extract_params *gen_params;
+ uint32_t tmp_reg, i, select, mask, fqb;
+ uint8_t offset, shift, ht;
+
+ /* Zero out all registers so no need to care about unused ones */
+ memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));
+
+ /* Mode register */
+ tmp_reg = fm_kg_build_nia(params->next_engine,
+ params->next_engine_action);
+ if (tmp_reg == KG_NIA_INVALID) {
+ return -EINVAL;
+ }
+
+ if (params->next_engine == E_FMAN_PCD_PLCR) {
+ tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR;
+ }
+ else if (params->next_engine == E_FMAN_PCD_CC) {
+ tmp_reg |= (uint32_t)params->cc_params.base_offset <<
+ FMAN_KG_SCH_MODE_CCOBASE_SHIFT;
+ }
+
+ tmp_reg |= FMAN_KG_SCH_MODE_EN;
+ scheme_regs->kgse_mode = tmp_reg;
+
+ /* Match vector */
+ scheme_regs->kgse_mv = params->match_vector;
+
+ extract_params = &params->extract_params;
+
+ /* Scheme default values registers */
+ scheme_regs->kgse_dv0 = extract_params->def_scheme_0;
+ scheme_regs->kgse_dv1 = extract_params->def_scheme_1;
+
+ /* Extract Known Fields Command register */
+ scheme_regs->kgse_ekfc = extract_params->known_fields;
+
+ /* Entry Extract Known Default Value register */
+ tmp_reg = 0;
+ tmp_reg |= extract_params->known_fields_def.mac_addr <<
+ FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.vlan_tci <<
+ FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.etype <<
+ FMAN_KG_SCH_DEF_ETYPE_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ppp_sid <<
+ FMAN_KG_SCH_DEF_PPP_SID_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ppp_pid <<
+ FMAN_KG_SCH_DEF_PPP_PID_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.mpls <<
+ FMAN_KG_SCH_DEF_MPLS_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ip_addr <<
+ FMAN_KG_SCH_DEF_IP_ADDR_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ptype <<
+ FMAN_KG_SCH_DEF_PTYPE_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ip_tos_tc <<
+ FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ipv6_fl <<
+ FMAN_KG_SCH_DEF_IPv6_FL_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ipsec_spi <<
+ FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.l4_port <<
+ FMAN_KG_SCH_DEF_L4_PORT_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.tcp_flg <<
+ FMAN_KG_SCH_DEF_TCP_FLG_SHIFT;
+
+ scheme_regs->kgse_ekdv = tmp_reg;
+
+ /* Generic extract registers */
+ if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < extract_params->gen_extract_num; i++) {
+ gen_params = extract_params->gen_extract + i;
+
+ tmp_reg = FMAN_KG_SCH_GEN_VALID;
+ tmp_reg |= (uint32_t)gen_params->def_val <<
+ FMAN_KG_SCH_GEN_DEF_SHIFT;
+
+ if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) {
+ if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) ||
+ (gen_params->extract == 0)) {
+ return -EINVAL;
+ }
+ } else {
+ tmp_reg |= FMAN_KG_SCH_GEN_OR;
+ }
+
+ tmp_reg |= (uint32_t)gen_params->extract <<
+ FMAN_KG_SCH_GEN_SIZE_SHIFT;
+ tmp_reg |= (uint32_t)gen_params->mask <<
+ FMAN_KG_SCH_GEN_MASK_SHIFT;
+
+ offset = gen_params->offset;
+ ht = get_gen_ht_code(gen_params->src,
+ gen_params->no_validation,
+ &offset);
+ tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT;
+ tmp_reg |= offset;
+
+ scheme_regs->kgse_gec[i] = tmp_reg;
+ }
+
+ /* Masks registers */
+ if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) {
+ return -EINVAL;
+ }
+
+ select = 0;
+ mask = 0;
+ fqb = 0;
+ for (i = 0; i < extract_params->masks_num; i++) {
+ /* MCSx fields */
+ KG_GET_MASK_SEL_SHIFT(shift, i);
+ if (extract_params->masks[i].is_known) {
+ /* Mask known field */
+ select |= extract_params->masks[i].field_or_gen_idx <<
+ shift;
+ } else {
+ /* Mask generic extract */
+ select |= (extract_params->masks[i].field_or_gen_idx +
+ FM_KG_MASK_SEL_GEN_BASE) << shift;
+ }
+
+ /* MOx fields - spread between se_bmch and se_fqb registers */
+ KG_GET_MASK_OFFSET_SHIFT(shift, i);
+ if (i < 2) {
+ select |= (uint32_t)extract_params->masks[i].offset <<
+ shift;
+ } else {
+ fqb |= (uint32_t)extract_params->masks[i].offset <<
+ shift;
+ }
+
+ /* BMx fields */
+ KG_GET_MASK_SHIFT(shift, i);
+ mask |= (uint32_t)extract_params->masks[i].mask << shift;
+ }
+
+ /* Finish with rest of BMx fileds -
+ * don't mask bits for unused masks by setting
+ * corresponding BMx field = 0xFF */
+ for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) {
+ KG_GET_MASK_SHIFT(shift, i);
+ mask |= 0xFF << shift;
+ }
+
+ scheme_regs->kgse_bmch = select;
+ scheme_regs->kgse_bmcl = mask;
+
+ /* Finish with FQB register initialization.
+ * Check fqid is 24-bit value. */
+ if (params->base_fqid & ~0x00FFFFFF) {
+ return -EINVAL;
+ }
+
+ fqb |= params->base_fqid;
+ scheme_regs->kgse_fqb = fqb;
+
+ /* Hash Configuration register */
+ tmp_reg = 0;
+ if (params->hash_params.use_hash) {
+ /* Check hash mask is 24-bit value */
+ if (params->hash_params.mask & ~0x00FFFFFF) {
+ return -EINVAL;
+ }
+
+ /* Hash function produces 64-bit value, 24 bits of that
+ * are used to generate fq_id and policer profile.
+ * Thus, maximal shift is 40 bits to allow 24 bits out of 64.
+ */
+ if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) {
+ return -EINVAL;
+ }
+
+ tmp_reg |= params->hash_params.mask;
+ tmp_reg |= (uint32_t)params->hash_params.shift_r <<
+ FMAN_KG_SCH_HASH_HSHIFT_SHIFT;
+
+ if (params->hash_params.sym) {
+ tmp_reg |= FMAN_KG_SCH_HASH_SYM;
+ }
+
+ }
+
+ if (params->bypass_fqid_gen) {
+ tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN;
+ }
+
+ scheme_regs->kgse_hc = tmp_reg;
+
+ /* Policer Profile register */
+ if (params->policer_params.bypass_pp_gen) {
+ tmp_reg = FMAN_KG_SCH_PP_NO_GEN;
+ } else {
+ /* Lower 8 bits of 24-bits extracted from hash result
+ * are used for policer profile generation.
+ * That leaves maximum shift value = 23. */
+ if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) {
+ return -EINVAL;
+ }
+
+ tmp_reg = params->policer_params.base;
+ tmp_reg |= ((uint32_t)params->policer_params.shift <<
+ FMAN_KG_SCH_PP_SH_SHIFT) &
+ FMAN_KG_SCH_PP_SH_MASK;
+ tmp_reg |= ((uint32_t)params->policer_params.shift <<
+ FMAN_KG_SCH_PP_SL_SHIFT) &
+ FMAN_KG_SCH_PP_SL_MASK;
+ tmp_reg |= (uint32_t)params->policer_params.mask <<
+ FMAN_KG_SCH_PP_MASK_SHIFT;
+ }
+
+ scheme_regs->kgse_ppc = tmp_reg;
+
+ /* Coarse Classification Bit Select register */
+ if (params->next_engine == E_FMAN_PCD_CC) {
+ scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel;
+ }
+
+ /* Packets Counter register */
+ if (params->update_counter) {
+ scheme_regs->kgse_spc = params->counter_value;
+ }
+
+ return 0;
+}
+
+int fman_kg_write_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ struct fman_kg_scheme_regs *scheme_regs,
+ bool update_counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err, i;
+
+ /* Write indirect scheme registers */
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode);
+ iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc);
+ iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv);
+ iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch);
+ iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl);
+ iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb);
+ iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc);
+ iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc);
+ iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc);
+ iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0);
+ iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1);
+ iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs);
+ iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv);
+
+ for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]);
+
+ /* Write AR (Action register) */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_delete_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err, i;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ /* Clear all registers including enable bit in mode register */
+ for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) {
+ iowrite32be(0, ((uint32_t *)kgse_regs + i));
+ }
+
+ /* Write AR (Action register) */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_get_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t *counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+
+ if (err != 0)
+ return err;
+
+ *counter = ioread32be(&kgse_regs->kgse_spc);
+
+ return 0;
+}
+
+int fman_kg_set_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
+
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ if (err != 0)
+ return err;
+
+ /* Keygen indirect access memory contains all scheme_id registers
+ * by now. Change only counter value. */
+ iowrite32be(counter, &kgse_regs->kgse_spc);
+
+ /* Write back scheme registers */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+
+ return err;
+}
+
+uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs)
+{
+ return ioread32be(&regs->fmkg_tpc);
+}
+
+int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params,
+ struct fman_kg_cp_regs *cls_plan_regs)
+{
+ uint8_t entries_set, entry_bit;
+ int i;
+
+ /* Zero out all group's register */
+ memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs));
+
+ /* Go over all classification entries in params->entries_mask and
+ * configure the corresponding cpe register */
+ entries_set = params->entries_mask;
+ for (i = 0; entries_set; i++) {
+ entry_bit = (uint8_t)(0x80 >> i);
+ if ((entry_bit & entries_set) == 0)
+ continue;
+ entries_set ^= entry_bit;
+ cls_plan_regs->kgcpe[i] = params->mask_vector[i];
+ }
+
+ return 0;
+}
+
+int fman_kg_write_cls_plan(struct fman_kg_regs *regs,
+ uint8_t grp_id,
+ uint8_t entries_mask,
+ uint8_t hwport_id,
+ struct fman_kg_cp_regs *cls_plan_regs)
+{
+ struct fman_kg_cp_regs *kgcpe_regs;
+ uint32_t tmp_reg;
+ int i, err;
+
+ /* Check group index is valid and the group isn't empty */
+ if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM)
+ return -EINVAL;
+
+ /* Write indirect classification plan registers */
+ kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]);
+
+ for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) {
+ iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]);
+ }
+
+ tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_write_bind_schemes(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t schemes)
+{
+ struct fman_kg_pe_regs *kg_pe_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp);
+
+ tmp_reg = build_ar_bind_scheme(hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_build_bind_cls_plans(uint8_t grp_base,
+ uint8_t grp_mask,
+ uint32_t *bind_cls_plans)
+{
+ /* Check grp_base and grp_mask are 5-bits values */
+ if ((grp_base & ~0x0000001F) || (grp_mask & !0x0000001F))
+ return -EINVAL;
+
+ *bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base);
+ return 0;
+}
+
+
+int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t bind_cls_plans)
+{
+ struct fman_kg_pe_regs *kg_pe_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp);
+
+ tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c
new file mode 100644
index 0000000..caa1d28
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include "fsl_fman_prs.h"
+
+uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->fmpr_perr) & ev_mask;
+}
+
+uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs)
+{
+ return ioread32be(&regs->fmpr_perer);
+}
+
+void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event)
+{
+ iowrite32be(event, &regs->fmpr_perr);
+}
+
+uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->fmpr_pevr) & ev_mask;
+}
+
+uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs)
+{
+ return ioread32be(&regs->fmpr_pever);
+}
+
+void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event)
+{
+ iowrite32be(event, &regs->fmpr_pevr);
+}
+
+void fman_prs_defconfig(struct fman_prs_cfg *cfg)
+{
+ cfg->port_id_stat = 0;
+ cfg->max_prs_cyc_lim = DEFAULT_MAX_PRS_CYC_LIM;
+ cfg->prs_exceptions = 0x03000000;
+}
+
+int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg)
+{
+ uint32_t tmp;
+
+ iowrite32be(cfg->max_prs_cyc_lim, &regs->fmpr_rpclim);
+ iowrite32be((FM_PCD_PRS_SINGLE_ECC | FM_PCD_PRS_PORT_IDLE_STS),
+ &regs->fmpr_pevr);
+
+ if (cfg->prs_exceptions & FM_PCD_EX_PRS_SINGLE_ECC)
+ iowrite32be(FM_PCD_PRS_SINGLE_ECC, &regs->fmpr_pever);
+ else
+ iowrite32be(0, &regs->fmpr_pever);
+
+ iowrite32be(FM_PCD_PRS_DOUBLE_ECC, &regs->fmpr_perr);
+
+ tmp = 0;
+ if (cfg->prs_exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)
+ tmp |= FM_PCD_PRS_DOUBLE_ECC;
+ iowrite32be(tmp, &regs->fmpr_perer);
+
+ iowrite32be(cfg->port_id_stat, &regs->fmpr_ppsc);
+
+ return 0;
+}
+
+void fman_prs_enable(struct fman_prs_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmpr_rpimac) | FM_PCD_PRS_RPIMAC_EN;
+ iowrite32be(tmp, &regs->fmpr_rpimac);
+}
+
+void fman_prs_disable(struct fman_prs_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmpr_rpimac) & ~FM_PCD_PRS_RPIMAC_EN;
+ iowrite32be(tmp, &regs->fmpr_rpimac);
+}
+
+void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk)
+{
+ iowrite32be(pid_msk, &regs->fmpr_ppsc);
+}
+
+void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable)
+{
+ if (enable)
+ iowrite32be(FM_PCD_PRS_PPSC_ALL_PORTS, &regs->fmpr_ppsc);
+ else
+ iowrite32be(0, &regs->fmpr_ppsc);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile
new file mode 100644
index 0000000..f8dbc8a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Pcd.o
+
+fsl-ncsw-Pcd-objs := fm_port.o fm_port_im.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c
new file mode 100644
index 0000000..07cec14
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c
@@ -0,0 +1,5724 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_port.c
+
+ @Description FM driver routines implementation.
+*//***************************************************************************/
+#include "error_ext.h"
+#include "std_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_port.h"
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static t_Error CheckInitParameters(t_FmPort *p_FmPort)
+{
+ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
+ t_Error ans = E_OK;
+ uint32_t unusedMask;
+
+ if (p_FmPort->imEn)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)
+ if (p_FmPort->fifoDeqPipelineDepth > 2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for IM 10G can't be larger than 2"));
+
+ if ((ans = FmPortImCheckInitParameters(p_FmPort)) != E_OK)
+ return ERROR_CODE(ans);
+ }
+ else
+ {
+ /****************************************/
+ /* Rx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ /* external buffer pools */
+ if (!p_Params->extBufPools.numOfPoolsUsed)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.numOfPoolsUsed=0. At least one buffer pool must be defined"));
+
+ if (FmSpCheckBufPoolsParams(&p_Params->extBufPools, p_Params->p_BackupBmPools, &p_Params->bufPoolDepletion)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* Check that part of IC that needs copying is small enough to enter start margin */
+ if (p_Params->intContext.size && (p_Params->intContext.size + p_Params->intContext.extBufOffset > p_Params->bufMargins.startMargins))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size is larger than start margins"));
+
+ if (p_Params->liodnOffset & ~FM_LIODN_OFFSET_MASK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+
+#ifdef FM_NO_BACKUP_POOLS
+ if ((p_FmPort->fmRevInfo.majorRev != 4) && (p_FmPort->fmRevInfo.majorRev < 6))
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("BackupBmPools"));
+#endif /* FM_NO_BACKUP_POOLS */
+ }
+
+ /****************************************/
+ /* Non Rx ports */
+ /****************************************/
+ else
+ {
+ if (p_Params->deqSubPortal >= FM_MAX_NUM_OF_SUB_PORTALS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" deqSubPortal has to be in the range of 0 - %d", FM_MAX_NUM_OF_SUB_PORTALS));
+
+ /* to protect HW internal-context from overwrite */
+ if ((p_Params->intContext.size) && (p_Params->intContext.intContextOffset < MIN_TX_INT_OFFSET))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("non-Rx intContext.intContextOffset can't be smaller than %d", MIN_TX_INT_OFFSET));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)
+ /* in O/H DEFAULT_notSupported indicates that it is not suppported and should not be checked */
+ || (p_FmPort->fifoDeqPipelineDepth != DEFAULT_notSupported))
+ {
+ /* Check that not larger than 8 */
+ if ((!p_FmPort->fifoDeqPipelineDepth) ||( p_FmPort->fifoDeqPipelineDepth > MAX_FIFO_PIPELINE_DEPTH))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth can't be larger than %d", MAX_FIFO_PIPELINE_DEPTH));
+ }
+ }
+
+ /****************************************/
+ /* Rx Or Offline Parsing */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+
+ if (!p_Params->dfltFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
+#if defined(FM_CAPWAP_SUPPORT) && defined(FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004)
+ if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace % 16)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufferPrefixContent.manipExtraSpace has to be devidable by 16"));
+#endif /* defined(FM_CAPWAP_SUPPORT) && ... */
+ }
+
+ /****************************************/
+ /* All ports */
+ /****************************************/
+ /* common BMI registers values */
+ /* Check that Queue Id is not larger than 2^24, and is not 0 */
+ if ((p_Params->errFqid & ~0x00FFFFFF) || !p_Params->errFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("errFqid must be between 1 and 2^24-1"));
+ if (p_Params->dfltFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
+ }
+
+ /****************************************/
+ /* Rx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ /* Check that divisible by 256 and not larger than 256 */
+ if (p_Params->rxFifoPriElevationLevel % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if (!p_Params->rxFifoPriElevationLevel || (p_Params->rxFifoPriElevationLevel > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
+ if (p_Params->rxFifoThreshold % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be divisible by %d", BMI_FIFO_UNITS));
+ if (!p_Params->rxFifoThreshold ||(p_Params->rxFifoThreshold > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
+
+ /* Check that not larger than 16 */
+ if (p_Params->cutBytesFromEnd > FRAME_END_DATA_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
+
+ if (FmSpCheckBufMargins(&p_Params->bufMargins)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* extra FIFO size (allowed only to Rx ports) */
+ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.extra % BMI_FIFO_UNITS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.extra has to be divisible by %d", BMI_FIFO_UNITS));
+
+ if (p_Params->bufPoolDepletion.poolsGrpModeEnable &&
+ !p_Params->bufPoolDepletion.numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can not be 0 when poolsGrpModeEnable=TRUE"));
+#ifdef FM_CSI_CFED_LIMIT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ /* Check that not larger than 16 */
+ if (p_Params->cutBytesFromEnd + p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore + cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
+ }
+#endif /* FM_CSI_CFED_LIMIT */
+ }
+
+ /****************************************/
+ /* Non Rx ports */
+ /****************************************/
+ /* extra FIFO size (allowed only to Rx ports) */
+ else if (p_FmPort->fifoBufs.extra)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No fifoBufs.extra for non Rx ports"));
+
+
+ /****************************************/
+ /* Tx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ {
+ /* Check that divisible by 256 and not larger than 256 */
+ if (p_Params->txFifoMinFillLevel % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if (p_Params->txFifoMinFillLevel > (BMI_MAX_FIFO_SIZE - 256))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be in the range of 0 - %d", BMI_MAX_FIFO_SIZE));
+ if (p_Params->txFifoLowComfLevel % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if (!p_Params->txFifoLowComfLevel || (p_Params->txFifoLowComfLevel > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_TX)
+ if (p_FmPort->fifoDeqPipelineDepth > 2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for 1G can't be larger than 2"));
+ }
+ /****************************************/
+ /* Non Tx Ports */
+ /****************************************/
+ /* If discard override was selected , no frames may be discarded. */
+ else if (p_Params->frmDiscardOverride && p_Params->errorsToDiscard)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("errorsToDiscard is not empty, but frmDiscardOverride selected (all discarded frames to be enqueued to error queue)."));
+
+ /****************************************/
+ /* Rx and Offline parsing */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ unusedMask = BMI_STATUS_OP_MASK_UNUSED;
+ else
+ unusedMask = BMI_STATUS_RX_MASK_UNUSED;
+
+ /* Check that no common bits with BMI_STATUS_MASK_UNUSED */
+ if (p_Params->errorsToDiscard & unusedMask)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("errorsToDiscard contains undefined bits"));
+ }
+
+ /****************************************/
+ /* Offline Ports */
+ /****************************************/
+#ifdef FM_OP_OPEN_DMA_MIN_LIMIT
+ if ((p_FmPort->fmRevInfo.majorRev >= 6) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ p_Params->setNumOfOpenDmas &&
+ (p_FmPort->openDmas.num < MIN_NUM_OF_OP_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Offline port, openDmas.num can't be smaller than %d", MIN_NUM_OF_OP_DMAS));
+#endif /* FM_OP_OPEN_DMA_MIN_LIMIT */
+
+ /****************************************/
+ /* Offline & HC Ports */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ {
+#ifndef FM_FRAME_END_PARAMS_FOR_OP
+ if ((p_FmPort->fmRevInfo.majorRev < 6) &&
+ (p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore != DEFAULT_notSupported))
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("cheksumLastBytesIgnore is available for Rx & Tx ports only"));
+#endif /* !FM_FRAME_END_PARAMS_FOR_OP */
+
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if ((!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6))) &&
+ (p_FmPort->fifoDeqPipelineDepth != DEFAULT_notSupported))
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("fifoDeqPipelineDepth is available for Tx ports only"));
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+ }
+ /****************************************/
+ /* All ports */
+ /****************************************/
+
+ /* Check that not larger than 16 */
+ if ((p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE) && ((p_Params->cheksumLastBytesIgnore != DEFAULT_notSupported)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore can't be larger than %d", FRAME_END_DATA_SIZE));
+
+ if (FmSpCheckIntContextParams(&p_Params->intContext)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* common BMI registers values */
+ if (p_Params->setNumOfTasks && ((!p_FmPort->tasks.num) || (p_FmPort->tasks.num > MAX_NUM_OF_TASKS)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.num can't be larger than %d", MAX_NUM_OF_TASKS));
+ if (p_Params->setNumOfTasks && (p_FmPort->tasks.extra > MAX_NUM_OF_EXTRA_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
+ if (p_Params->setNumOfOpenDmas && ((!p_FmPort->openDmas.num) || (p_FmPort->openDmas.num > MAX_NUM_OF_DMAS)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.num can't be larger than %d", MAX_NUM_OF_DMAS));
+ if (p_Params->setNumOfOpenDmas && (p_FmPort->openDmas.extra > MAX_NUM_OF_EXTRA_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
+ if (p_Params->setSizeOfFifo && (!p_FmPort->fifoBufs.num || (p_FmPort->fifoBufs.num > BMI_MAX_FIFO_SIZE)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
+ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.num % BMI_FIFO_UNITS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be divisible by %d", BMI_FIFO_UNITS));
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ if (p_FmPort->p_FmPortDriverParam->deqPrefetchOption != DEFAULT_notSupported)
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("deqPrefetchOption"));
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ return E_OK;
+}
+
+static t_Error VerifySizeOfFifo(t_FmPort *p_FmPort)
+{
+ uint32_t minFifoSizeRequired = 0;
+
+ /*************************/
+ /* TX PORTS */
+ /*************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ {
+ minFifoSizeRequired = (uint32_t)DIV_CEIL(p_FmPort->maxFrameLength, BMI_FIFO_UNITS);
+ if (p_FmPort->imEn)
+ minFifoSizeRequired += 3*BMI_FIFO_UNITS;
+ else
+ minFifoSizeRequired += (p_FmPort->fifoDeqPipelineDepth+3)*BMI_FIFO_UNITS;
+
+ /* add some margin for back to back capability to improve performance
+ * allows the hardware to pipeline new frame dma while the previous
+ * frame not yet transmitted). */
+ if (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)
+ minFifoSizeRequired += 3*BMI_FIFO_UNITS;
+ else
+ minFifoSizeRequired += 2*BMI_FIFO_UNITS;
+ }
+
+ /*************************/
+ /* RX IM PORTS */
+ /*************************/
+ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) &&
+ p_FmPort->imEn)
+ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) +
+ (4*BMI_FIFO_UNITS));
+
+ /*************************/
+ /* RX non-IM PORTS */
+ /*************************/
+ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) &&
+ !p_FmPort->imEn)
+ {
+#ifdef FM_FIFO_ALLOCATION_ALG
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ if (p_FmPort->rxPoolsParams.numOfPools == 1)
+ minFifoSizeRequired = 8*BMI_FIFO_UNITS;
+ else
+ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->rxPoolsParams.secondLargestBufSize, BMI_FIFO_UNITS) +
+ (7*BMI_FIFO_UNITS));
+ }
+ else
+#endif /* FM_FIFO_ALLOCATION_ALG */
+ minFifoSizeRequired = (uint32_t)(DIV_CEIL(p_FmPort->rxPoolsParams.largestBufSize, BMI_FIFO_UNITS) +
+ (7*BMI_FIFO_UNITS));
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)
+ minFifoSizeRequired += 12*BMI_FIFO_UNITS;
+ else
+ minFifoSizeRequired += 3*BMI_FIFO_UNITS;
+ }
+
+ /* For O/H ports, check fifo size and update if necessary */
+ else if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ minFifoSizeRequired = (uint32_t)((p_FmPort->tasks.num + 4)*BMI_FIFO_UNITS);
+
+ /* for all ports - verify size */
+ if (minFifoSizeRequired && (p_FmPort->fifoBufs.num < minFifoSizeRequired))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("User defined FIFO size should be enlarged to %d",
+ minFifoSizeRequired));
+
+ /* check if pool size is not too big */
+ /* This is a definition problem in which if the fifo for the RX port
+ is lower than the largest pool size the hardware will allocate scatter gather
+ buffers even though the frame size can fit in a single buffer. */
+ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ && !p_FmPort->imEn)
+ {
+ if (p_FmPort->rxPoolsParams.largestBufSize > p_FmPort->fifoBufs.num)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Frame larger than port Fifo size (%u) will be split to more "\
+ "than a single buffer (S/G) even if shorter than largest buffer size (%u)",
+ p_FmPort->fifoBufs.num, p_FmPort->rxPoolsParams.largestBufSize));
+ }
+
+ return E_OK;
+}
+
+static void FmPortDriverParamFree(t_FmPort *p_FmPort)
+{
+ if (p_FmPort->p_FmPortDriverParam)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ p_FmPort->p_FmPortDriverParam = NULL;
+ }
+}
+
+static t_Error SetExtBufferPools(t_FmPort *p_FmPort)
+{
+ t_FmExtPools *p_ExtBufPools = &p_FmPort->p_FmPortDriverParam->extBufPools;
+ t_FmBufPoolDepletion *p_BufPoolDepletion = &p_FmPort->p_FmPortDriverParam->bufPoolDepletion;
+ volatile uint32_t *p_ExtBufRegs;
+ volatile uint32_t *p_BufPoolDepletionReg;
+ bool rxPort;
+ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS];
+ uint8_t numOfPools;
+ int i=0, j=0;
+ uint32_t tmpReg, vector;
+
+ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
+ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
+ memcpy(&p_FmPort->extBufPools, p_ExtBufPools, sizeof(t_FmExtPools));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi;
+ p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rmpd;
+ rxPort = TRUE;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi;
+ p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ompd;
+ rxPort = FALSE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for port type"));
+ }
+
+ FmSpSetBufPoolsInAscOrderOfBufSizes(p_ExtBufPools, orderedArray, sizesArray);
+
+ /* build the register value */
+ for (i=0;i<p_ExtBufPools->numOfPoolsUsed;i++)
+ {
+ tmpReg = BMI_EXT_BUF_POOL_VALID | BMI_EXT_BUF_POOL_EN_COUNTER;
+ tmpReg |= ((uint32_t)orderedArray[i] << BMI_EXT_BUF_POOL_ID_SHIFT);
+ tmpReg |= sizesArray[orderedArray[i]];
+ /* functionality available only for some deriviatives (limited by config) */
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ for (j=0;j<p_FmPort->p_FmPortDriverParam->p_BackupBmPools->numOfBackupPools;j++)
+ if (orderedArray[i] == p_FmPort->p_FmPortDriverParam->p_BackupBmPools->poolIds[j])
+ {
+ tmpReg |= BMI_EXT_BUF_POOL_BACKUP;
+ break;
+ }
+ WRITE_UINT32(*(p_ExtBufRegs+i), tmpReg);
+ }
+
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ XX_Free(p_FmPort->p_FmPortDriverParam->p_BackupBmPools);
+
+ numOfPools = (uint8_t)(rxPort ? FM_PORT_MAX_NUM_OF_EXT_POOLS:FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS);
+
+ /* clear unused pools */
+ for (i=p_ExtBufPools->numOfPoolsUsed;i<numOfPools;i++)
+ WRITE_UINT32(*(p_ExtBufRegs+i), 0);
+
+ /* save pools parameters for later use */
+ p_FmPort->rxPoolsParams.numOfPools = p_ExtBufPools->numOfPoolsUsed;
+ p_FmPort->rxPoolsParams.largestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-1]];
+ p_FmPort->rxPoolsParams.secondLargestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-2]];
+
+ /* FMBM_RMPD reg. - pool depletion */
+ tmpReg = 0;
+ if (p_BufPoolDepletion->poolsGrpModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ vector = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_BufPoolDepletion->poolsToConsider[i])
+ {
+ for (j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
+ {
+ if (i == orderedArray[j])
+ {
+ vector |= 0x80000000 >> j;
+ break;
+ }
+ }
+ }
+ }
+ /* configure num of pools and vector for number of pools mode */
+ tmpReg |= (((uint32_t)p_BufPoolDepletion->numOfPools - 1) << BMI_POOL_DEP_NUM_OF_POOLS_SHIFT);
+ tmpReg |= vector;
+ }
+
+ if (p_BufPoolDepletion->singlePoolModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ vector = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_BufPoolDepletion->poolsToConsiderForSingleMode[i])
+ {
+ for (j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
+ {
+ if (i == orderedArray[j])
+ {
+ vector |= 0x00000080 >> j;
+ break;
+ }
+ }
+ }
+ }
+ tmpReg |= vector;
+ }
+
+#if (DPAA_VERSION >= 11)
+ /* fill QbbPEV */
+ if (p_BufPoolDepletion->poolsGrpModeEnable ||
+ p_BufPoolDepletion->singlePoolModeEnable)
+ {
+ vector = 0;
+ for (i=0; i<FM_MAX_NUM_OF_PFC_PRIORITIES; i++)
+ {
+ if (p_BufPoolDepletion->pfcPrioritiesEn[i] == TRUE)
+ {
+ vector |= 0x00008000 >> i;
+ }
+ }
+ tmpReg |= vector;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ WRITE_UINT32(*p_BufPoolDepletionReg, tmpReg);
+
+ return E_OK;
+}
+
+static t_Error ClearPerfCnts(t_FmPort *p_FmPort)
+{
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL, 0);
+ return E_OK;
+}
+
+static t_Error BmiRxPortInit(t_FmPort *p_FmPort)
+{
+ t_FmPortRxBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs;
+ uint32_t tmpReg;
+ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
+ uint32_t errorsToEnq = 0;
+ t_FmPortPerformanceCnt performanceContersParams;
+ t_Error err;
+
+ /* check that port is not busy */
+ if (GET_UINT32(p_Regs->fmbm_rcfg) & BMI_PORT_CFG_EN)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("Port(%d,%d) is already enabled",p_FmPort->portType, p_FmPort->portId));
+
+ /* Set Config register */
+ tmpReg = 0;
+ if (p_FmPort->imEn)
+ tmpReg |= BMI_PORT_CFG_IM;
+ /* No discard - all error frames go to error queue */
+ else if (p_Params->frmDiscardOverride)
+ tmpReg |= BMI_PORT_CFG_FDOVR;
+
+ WRITE_UINT32(p_Regs->fmbm_rcfg, tmpReg);
+
+ /* Configure dma attributes */
+ tmpReg = 0;
+ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
+ if (p_Params->dmaWriteOptimize)
+ tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+
+ WRITE_UINT32(p_Regs->fmbm_rda, tmpReg);
+
+ /* Configure Rx Fifo params */
+ tmpReg = 0;
+ tmpReg |= ((p_Params->rxFifoPriElevationLevel/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_PRI_ELEVATION_SHIFT);
+ tmpReg |= ((p_Params->rxFifoThreshold/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_THRESHOLD_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_rfp, tmpReg);
+
+#ifdef FM_NO_RESTRICT_ON_ACCESS_RSRC
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ /* always allow access to the extra resources */
+ WRITE_UINT32(p_Regs->fmbm_reth, BMI_RX_FIFO_THRESHOLD_BC);
+#endif /* FM_NO_RESTRICT_ON_ACCESS_RSRC */
+
+ /* frame end parameters */
+ tmpReg = 0;
+ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_RX_FRAME_END_CS_IGNORE_SHIFT);
+ tmpReg |= ((uint32_t)p_Params->cutBytesFromEnd<< BMI_RX_FRAME_END_CUT_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_rfed, tmpReg);
+
+ /* IC parameters */
+ tmpReg = 0;
+ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_ricp, tmpReg);
+
+ if (!p_FmPort->imEn)
+ {
+ /* Call the external Buffer routine which also checks fifo
+ size and updates it if necessary */
+ /* define external buffer pools and pool depletion*/
+
+ /* check if the largest external buffer pool is large enough */
+ if ((p_Params->bufMargins.startMargins +
+ MIN_EXT_BUF_SIZE +
+ p_Params->bufMargins.endMargins) > p_FmPort->rxPoolsParams.largestBufSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("bufMargins.startMargins (%d) + minimum buf size (64) + "
+ "bufMargins.endMargins (%d) is larger than maximum external buffer size (%d)",
+ p_Params->bufMargins.startMargins,
+ p_Params->bufMargins.endMargins,
+ p_FmPort->rxPoolsParams.largestBufSize));
+
+ /* buffer margins */
+ tmpReg = 0;
+ tmpReg |= (((uint32_t)p_Params->bufMargins.startMargins) << BMI_EXT_BUF_MARG_START_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->bufMargins.endMargins) << BMI_EXT_BUF_MARG_END_SHIFT);
+#if (DPAA_VERSION >= 11)
+ if (p_Params->noScatherGather)
+ tmpReg |= BMI_SG_DISABLE;
+#endif
+ WRITE_UINT32(p_Regs->fmbm_rebm, tmpReg);
+ }
+
+ if (p_FmPort->internalBufferOffset)
+ {
+ tmpReg = (uint32_t)((p_FmPort->internalBufferOffset%OFFSET_UNITS) ?
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1) :
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS));
+ p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS);
+ WRITE_UINT32(p_Regs->fmbm_rim, tmpReg << BMI_IM_FOF_SHIFT);
+ }
+
+ /* NIA */
+ if (p_FmPort->imEn)
+ WRITE_UINT32(p_Regs->fmbm_rfne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_RX);
+ else
+ {
+ tmpReg = 0;
+ if (p_Params->forwardReuseIntContext)
+ tmpReg |= BMI_PORT_RFNE_FRWD_RPD;
+ /* L3/L4 checksum verify is enabled by default. */
+ /*tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C;*/
+ WRITE_UINT32(p_Regs->fmbm_rfne, tmpReg | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+ }
+ WRITE_UINT32(p_Regs->fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+
+ /* command attribute */
+ tmpReg = BMI_CMD_RX_MR_DEF;
+ if (!p_FmPort->imEn)
+ {
+ tmpReg |= BMI_CMD_ATTR_ORDER;
+ if (p_Params->syncReq)
+ tmpReg |= BMI_CMD_ATTR_SYNC;
+ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
+ }
+
+ WRITE_UINT32(p_Regs->fmbm_rfca, tmpReg);
+
+ /* default queues */
+ if (!p_FmPort->imEn)
+ {
+ WRITE_UINT32(p_Regs->fmbm_rfqid, p_Params->dfltFqid);
+ WRITE_UINT32(p_Regs->fmbm_refqid, p_Params->errFqid);
+ }
+
+ /* set counters */
+ WRITE_UINT32(p_Regs->fmbm_rstc, BMI_COUNTERS_EN);
+
+ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num;
+ performanceContersParams.queueCompVal = 1;
+ performanceContersParams.dmaCompVal =(uint8_t) p_FmPort->openDmas.num;
+ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num;
+ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ WRITE_UINT32(p_Regs->fmbm_rpc, BMI_COUNTERS_EN);
+
+ /* error/status mask - check that if discard OV is set, no
+ discard is required for specific errors.*/
+ WRITE_UINT32(p_Regs->fmbm_rfsdm, p_Params->errorsToDiscard);
+
+ errorsToEnq = (RX_ERRS_TO_ENQ & ~p_Params->errorsToDiscard);
+ WRITE_UINT32(p_Regs->fmbm_rfsem, errorsToEnq);
+
+ return E_OK;
+}
+
+static t_Error BmiTxPortInit(t_FmPort *p_FmPort)
+{
+ t_FmPortTxBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs;
+ uint32_t tmpReg;
+ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
+ /*uint32_t rateCountUnit;*/
+ t_FmPortPerformanceCnt performanceContersParams;
+
+ /* check that port is not busy */
+ if (GET_UINT32(p_Regs->fmbm_tcfg) & BMI_PORT_CFG_EN)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
+
+ tmpReg = 0;
+ if (p_FmPort->imEn)
+ tmpReg |= BMI_PORT_CFG_IM;
+
+ WRITE_UINT32(p_Regs->fmbm_tcfg, tmpReg);
+
+ /* Configure dma attributes */
+ tmpReg = 0;
+ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
+
+ WRITE_UINT32(p_Regs->fmbm_tda, tmpReg);
+
+ /* Configure Tx Fifo params */
+ tmpReg = 0;
+ tmpReg |= ((p_Params->txFifoMinFillLevel/BMI_FIFO_UNITS) << BMI_TX_FIFO_MIN_FILL_SHIFT);
+ tmpReg |= (((uint32_t)p_FmPort->fifoDeqPipelineDepth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT);
+ tmpReg |= ((p_Params->txFifoLowComfLevel/BMI_FIFO_UNITS - 1) << BMI_TX_LOW_COMF_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_tfp, tmpReg);
+
+ /* frame end parameters */
+ tmpReg = 0;
+ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_FRAME_END_CS_IGNORE_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_tfed, tmpReg);
+
+ if (!p_FmPort->imEn)
+ {
+ /* IC parameters */
+ tmpReg = 0;
+ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_ticp, tmpReg);
+ }
+
+ /* NIA */
+ if (p_FmPort->imEn)
+ {
+ WRITE_UINT32(p_Regs->fmbm_tfdne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX);
+ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX);
+#if (DPAA_VERSION >= 11)
+/* TODO - what should be the TFNE for FMan v3 IM? */
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ WRITE_UINT32(p_Regs->fmbm_tfdne, NIA_ENG_QMI_DEQ);
+ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+#if (DPAA_VERSION >= 11)
+ WRITE_UINT32(p_Regs->fmbm_tfne,
+ (!p_Params->dfltFqid ?
+ BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME :
+ NIA_BMI_AC_FETCH_ALL_FRAME));
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* The line bellow is a trick so the FM will not release the buffer
+ to BM nor will try to enq the frame to QM */
+ if (!p_Params->dfltFqid && p_Params->dontReleaseBuf)
+ {
+ /* override fmbm_tcfqid 0 with a false non-0 value. This will force FM to
+ * act according to tfene. Otherwise, if fmbm_tcfqid is 0 the FM will release
+ * buffers to BM regardless of fmbm_tfene
+ */
+ WRITE_UINT32(p_Regs->fmbm_tcfqid, 0xFFFFFF);
+ WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+#if (DPAA_VERSION >= 11)
+ WRITE_UINT32(p_Regs->fmbm_tfne,
+ (GET_UINT32(p_Regs->fmbm_tfne) & ~BMI_EBD_EN));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ }
+
+ /* command attribute */
+ tmpReg = BMI_CMD_TX_MR_DEF;
+ if (p_FmPort->imEn)
+ tmpReg |= BMI_CMD_MR_DEAS;
+ else
+ {
+ tmpReg |= BMI_CMD_ATTR_ORDER;
+ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
+ }
+ WRITE_UINT32(p_Regs->fmbm_tfca, tmpReg);
+
+ /* default queues */
+ if (!p_FmPort->imEn)
+ {
+ if (p_Params->dfltFqid || !p_Params->dontReleaseBuf)
+ WRITE_UINT32(p_Regs->fmbm_tcfqid, p_Params->dfltFqid);
+ WRITE_UINT32(p_Regs->fmbm_tfeqid, p_Params->errFqid);
+ }
+
+ /* statistics & performance counters */
+ WRITE_UINT32(p_Regs->fmbm_tstc, BMI_COUNTERS_EN);
+
+ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num;
+ performanceContersParams.queueCompVal = 1;
+ performanceContersParams.dmaCompVal = (uint8_t)p_FmPort->openDmas.num;
+ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num;
+ FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams);
+
+ WRITE_UINT32(p_Regs->fmbm_tpc, BMI_COUNTERS_EN);
+
+
+ return E_OK;
+}
+
+static t_Error BmiOhPortInit(t_FmPort *p_FmPort)
+{
+ t_FmPortOhBmiRegs *p_Regs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs;
+ uint32_t tmpReg, errorsToEnq = 0;
+ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
+ t_FmPortPerformanceCnt performanceContersParams;
+
+ /* check that port is not busy */
+ if (GET_UINT32(p_Regs->fmbm_ocfg) & BMI_PORT_CFG_EN)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
+
+ /* Configure dma attributes */
+ tmpReg = 0;
+ tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
+ tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
+ if (p_Params->dmaWriteOptimize)
+ tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+
+ WRITE_UINT32(p_Regs->fmbm_oda, tmpReg);
+
+ /* IC parameters */
+ tmpReg = 0;
+ tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
+ tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS) << BMI_IC_SIZE_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_oicp, tmpReg);
+
+ /* NIA */
+ WRITE_UINT32(p_Regs->fmbm_ofdne, NIA_ENG_QMI_DEQ);
+
+ if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ);
+ else
+ WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+
+ /* command attribute */
+ if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ tmpReg = BMI_CMD_MR_DEAS | BMI_CMD_MR_MA;
+ else
+ tmpReg = BMI_CMD_ATTR_ORDER | BMI_CMD_MR_DEAS | BMI_CMD_MR_MA;
+
+ if (p_Params->syncReq)
+ tmpReg |= BMI_CMD_ATTR_SYNC;
+ tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
+ WRITE_UINT32(p_Regs->fmbm_ofca, tmpReg);
+
+ /* No discard - all error frames go to error queue */
+ if (p_Params->frmDiscardOverride)
+ tmpReg = BMI_PORT_CFG_FDOVR;
+ else
+ tmpReg = 0;
+ WRITE_UINT32(p_Regs->fmbm_ocfg, tmpReg);
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+ WRITE_UINT32(p_Regs->fmbm_ofsdm, p_Params->errorsToDiscard);
+
+ errorsToEnq = (OP_ERRS_TO_ENQ & ~p_Params->errorsToDiscard);
+ WRITE_UINT32(p_Regs->fmbm_ofsem, errorsToEnq);
+
+ /* NIA */
+ WRITE_UINT32(p_Regs->fmbm_ofne, (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+
+#ifndef FM_NO_OP_OBSERVED_POOLS
+ /* Call the external Buffer routine which also checks fifo
+ size and updates it if necessary */
+ if ((p_FmPort->fmRevInfo.majorRev == 4) &&
+ p_Params->enBufPoolDepletion)
+ {
+ /* define external buffer pools */
+ t_Error err = SetExtBufferPools(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+#endif /* FM_NO_OP_OBSERVED_POOLS */
+ }
+ else
+ /* NIA */
+ WRITE_UINT32(p_Regs->fmbm_ofne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_HC);
+
+ /* default queues */
+ WRITE_UINT32(p_Regs->fmbm_ofqid, p_Params->dfltFqid);
+ WRITE_UINT32(p_Regs->fmbm_oefqid, p_Params->errFqid);
+
+ if (p_FmPort->internalBufferOffset)
+ {
+ tmpReg = (uint32_t)((p_FmPort->internalBufferOffset % OFFSET_UNITS) ?
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1):
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS));
+ p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS);
+ WRITE_UINT32(p_Regs->fmbm_oim, tmpReg << BMI_IM_FOF_SHIFT);
+ }
+ /* statistics & performance counters */
+ WRITE_UINT32(p_Regs->fmbm_ostc, BMI_COUNTERS_EN);
+
+ performanceContersParams.taskCompVal = (uint8_t)p_FmPort->tasks.num;
+ performanceContersParams.queueCompVal = 0;
+ performanceContersParams.dmaCompVal = (uint8_t)p_FmPort->openDmas.num;
+ performanceContersParams.fifoCompVal = p_FmPort->fifoBufs.num;
+ FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams);
+
+ WRITE_UINT32(p_Regs->fmbm_opc, BMI_COUNTERS_EN);
+#ifdef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if ((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6))
+ {
+ tmpReg = (((uint32_t)p_FmPort->fifoDeqPipelineDepth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT);
+ WRITE_UINT32(p_Regs->fmbm_ofp, tmpReg);
+ }
+#endif /* FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+
+#ifdef FM_FRAME_END_PARAMS_FOR_OP
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ /* frame end parameters */
+ tmpReg = 0;
+ tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_FRAME_END_CS_IGNORE_SHIFT);
+
+ WRITE_UINT32(p_Regs->fmbm_ofed, tmpReg);
+ }
+#endif /* FM_FRAME_END_PARAMS_FOR_OP */
+
+ return E_OK;
+}
+
+static t_Error QmiInit(t_FmPort *p_FmPort)
+{
+ t_FmPortDriverParam *p_Params = NULL;
+ uint32_t tmpReg;
+
+ p_Params = p_FmPort->p_FmPortDriverParam;
+
+ /* check that port is not busy */
+ if (((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) &&
+ (GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
+
+ /* enable & clear counters */
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, QMI_PORT_CFG_EN_COUNTERS);
+
+ /* The following is done for non-Rx ports only */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ {
+ /* define dequeue NIA */
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX);
+ /* define enqueue NIA */
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+ }
+ else /* for HC & OP */
+ {
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH);
+ /* define enqueue NIA */
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
+ }
+
+ /* configure dequeue */
+ tmpReg = 0;
+ if (p_Params->deqHighPriority)
+ tmpReg |= QMI_DEQ_CFG_PRI;
+
+ switch (p_Params->deqType)
+ {
+ case (e_FM_PORT_DEQ_TYPE1):
+ tmpReg |= QMI_DEQ_CFG_TYPE1;
+ break;
+ case (e_FM_PORT_DEQ_TYPE2):
+ tmpReg |= QMI_DEQ_CFG_TYPE2;
+ break;
+ case (e_FM_PORT_DEQ_TYPE3):
+ tmpReg |= QMI_DEQ_CFG_TYPE3;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue type"));
+ }
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_FmPort->fmRevInfo.majorRev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+ switch (p_Params->deqPrefetchOption)
+ {
+ case (e_FM_PORT_DEQ_NO_PREFETCH):
+ /* Do nothing - QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_1_FRAME = 0 */
+ break;
+ case (e_FM_PORT_DEQ_PARTIAL_PREFETCH):
+ tmpReg |= QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES;
+ break;
+ case (e_FM_PORT_DEQ_FULL_PREFETCH):
+ tmpReg |= QMI_DEQ_CFG_PREFETCH_NO_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue prefetch option"));
+ }
+
+ tmpReg |= p_Params->deqByteCnt;
+ tmpReg |= (uint32_t)p_Params->deqSubPortal << QMI_DEQ_CFG_SUBPORTAL_SHIFT;
+
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndc, tmpReg);
+ }
+ else /* rx port */
+ /* define enqueue NIA */
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
+
+ return E_OK;
+}
+
+static t_Error BmiRxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
+{
+ t_FmPortRxBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs;
+
+ /* check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ case (e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
+ /* performance counters - may be read when disabled */
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME):
+ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
+ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER):
+ if (!(GET_UINT32(p_BmiRegs->fmbm_rstc) & BMI_COUNTERS_EN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ *p_Ptr = &p_BmiRegs->fmbm_rccn;
+ break;
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_rtuc;
+ break;
+ case (e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_rrquc;
+ break;
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_rduc;
+ break;
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_rfuc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
+ *p_Ptr = &p_BmiRegs->fmbm_rpac;
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_rfrc;
+ break;
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_rfcd;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_rfbc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_rlfc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_rffc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ *p_Ptr = &p_BmiRegs->fmbm_rfldec;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ *p_Ptr = &p_BmiRegs->fmbm_rodc;
+ break;
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ *p_Ptr = &p_BmiRegs->fmbm_rbdc;
+ break;
+ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER):
+ *p_Ptr = &p_BmiRegs->fmbm_rpec;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
+ }
+
+ return E_OK;
+}
+
+static t_Error BmiTxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
+{
+ t_FmPortTxBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs;
+
+ /* check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ case (e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ /* performance counters - may be read when disabled */
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case (e_FM_PORT_COUNTERS_LENGTH_ERR):
+ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ if (!(GET_UINT32(p_BmiRegs->fmbm_tstc) & BMI_COUNTERS_EN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports"));
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ *p_Ptr = &p_BmiRegs->fmbm_tccn;
+ break;
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_ttuc;
+ break;
+ case (e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_ttcquc;
+ break;
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_tduc;
+ break;
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_tfuc;
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_tfrc;
+ break;
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_tfdc;
+ break;
+ case (e_FM_PORT_COUNTERS_LENGTH_ERR):
+ *p_Ptr = &p_BmiRegs->fmbm_tfledc;
+ break;
+ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ *p_Ptr = &p_BmiRegs->fmbm_tfufdc;
+ break;
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ *p_Ptr = &p_BmiRegs->fmbm_tbdc;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports"));
+ }
+
+ return E_OK;
+}
+
+static t_Error BmiOhPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
+{
+ t_FmPortOhBmiRegs *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs;
+
+ /* check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ /* performance counters - may be read when disabled */
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ case (e_FM_PORT_COUNTERS_WRED_DISCARD):
+ case (e_FM_PORT_COUNTERS_LENGTH_ERR):
+ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ if (!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): /* only valid for offline parsing */
+ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */
+ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND);
+ if (!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter(%d) is not available for O/H ports", counter));
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_CYCLE):
+ *p_Ptr = &p_BmiRegs->fmbm_occn;
+ break;
+ case (e_FM_PORT_COUNTERS_TASK_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_otuc;
+ break;
+ case (e_FM_PORT_COUNTERS_DMA_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_oduc;
+ break;
+ case (e_FM_PORT_COUNTERS_FIFO_UTIL):
+ *p_Ptr = &p_BmiRegs->fmbm_ofuc;
+ break;
+ case (e_FM_PORT_COUNTERS_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_ofrc;
+ break;
+ case (e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_ofdc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ *p_Ptr = &p_BmiRegs->fmbm_offc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ *p_Ptr = &p_BmiRegs->fmbm_ofldec;
+ break;
+ case (e_FM_PORT_COUNTERS_WRED_DISCARD):
+ *p_Ptr = &p_BmiRegs->fmbm_ofwdc;
+ break;
+ case (e_FM_PORT_COUNTERS_LENGTH_ERR):
+ *p_Ptr = &p_BmiRegs->fmbm_ofledc;
+ break;
+ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ *p_Ptr = &p_BmiRegs->fmbm_ofufdc;
+ break;
+ case (e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ *p_Ptr = &p_BmiRegs->fmbm_obdc;
+ break;
+ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ *p_Ptr = &p_BmiRegs->fmbm_oodc;
+ break;
+ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER):
+ *p_Ptr = &p_BmiRegs->fmbm_opec;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for O/H ports"));
+ }
+
+ return E_OK;
+}
+
+static t_Error AdditionalPrsParams(t_FmPort *p_FmPort, t_FmPcdPrsAdditionalHdrParams *p_HdrParams, uint32_t *p_SoftSeqAttachReg)
+{
+ uint8_t hdrNum, Ipv4HdrNum;
+ u_FmPcdHdrPrsOpts *p_prsOpts;
+ uint32_t tmpReg = *p_SoftSeqAttachReg, tmpPrsOffset;
+
+ if (IS_PRIVATE_HEADER(p_HdrParams->hdr) || IS_SPECIAL_HEADER(p_HdrParams->hdr))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("No additional parameters for private or special headers."));
+
+ if (p_HdrParams->errDisable)
+ tmpReg |= PRS_HDR_ERROR_DIS;
+
+ /* Set parser options */
+ if (p_HdrParams->usePrsOpts)
+ {
+ p_prsOpts = &p_HdrParams->prsOpts;
+ switch (p_HdrParams->hdr)
+ {
+ case (HEADER_TYPE_MPLS):
+ if (p_prsOpts->mplsPrsOptions.labelInterpretationEnable)
+ tmpReg |= PRS_HDR_MPLS_LBL_INTER_EN;
+ GET_PRS_HDR_NUM(hdrNum, p_prsOpts->mplsPrsOptions.nextParse);
+ if (hdrNum == ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ GET_PRS_HDR_NUM(Ipv4HdrNum, HEADER_TYPE_IPv4);
+ if (hdrNum < Ipv4HdrNum)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Header must be equal or higher than IPv4"));
+ tmpReg |= ((uint32_t)hdrNum * PRS_HDR_ENTRY_SIZE) << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
+ break;
+ case (HEADER_TYPE_PPPoE):
+ if (p_prsOpts->pppoePrsOptions.enableMTUCheck)
+ tmpReg |= PRS_HDR_PPPOE_MTU_CHECK_EN;
+ break;
+ case (HEADER_TYPE_IPv6):
+ if (p_prsOpts->ipv6PrsOptions.routingHdrEnable)
+ tmpReg |= PRS_HDR_IPV6_ROUTE_HDR_EN;
+ break;
+ case (HEADER_TYPE_TCP):
+ if (p_prsOpts->tcpPrsOptions.padIgnoreChecksum)
+ tmpReg |= PRS_HDR_TCP_PAD_REMOVAL;
+ else
+ tmpReg &= ~PRS_HDR_TCP_PAD_REMOVAL;
+ break;
+ case (HEADER_TYPE_UDP):
+ if (p_prsOpts->udpPrsOptions.padIgnoreChecksum)
+ tmpReg |= PRS_HDR_UDP_PAD_REMOVAL;
+ else
+ tmpReg &= ~PRS_HDR_UDP_PAD_REMOVAL;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header"));
+ }
+ }
+
+ /* set software parsing (address is devided in 2 since parser uses 2 byte access. */
+ if (p_HdrParams->swPrsEnable)
+ {
+ tmpPrsOffset = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, p_HdrParams->hdr, p_HdrParams->indexPerHdr);
+ if (tmpPrsOffset == ILLEGAL_BASE)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+ tmpReg |= (PRS_HDR_SW_PRS_EN | tmpPrsOffset);
+ }
+ *p_SoftSeqAttachReg = tmpReg;
+
+ return E_OK;
+}
+
+static uint32_t GetPortSchemeBindParams(t_Handle h_FmPort, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t walking1Mask = 0x80000000, tmp;
+ uint8_t idx = 0;
+
+ p_SchemeBind->netEnvId = p_FmPort->netEnvId;
+ p_SchemeBind->hardwarePortId = p_FmPort->hardwarePortId;
+ p_SchemeBind->useClsPlan = p_FmPort->useClsPlan;
+ p_SchemeBind->numOfSchemes = 0;
+ tmp = p_FmPort->schemesPerPortVector;
+ if (tmp)
+ {
+ while (tmp)
+ {
+ if (tmp & walking1Mask)
+ {
+ p_SchemeBind->schemesIds[p_SchemeBind->numOfSchemes] = idx;
+ p_SchemeBind->numOfSchemes++;
+ tmp &= ~walking1Mask;
+ }
+ walking1Mask >>= 1;
+ idx++;
+ }
+ }
+
+ return tmp;
+}
+
+static t_Error SetPcd(t_FmPort *p_FmPort, t_FmPortPcdParams *p_PcdParams)
+{
+ t_Error err = E_OK;
+ uint32_t tmpReg;
+ volatile uint32_t *p_BmiNia=NULL;
+ volatile uint32_t *p_BmiPrsNia=NULL;
+ volatile uint32_t *p_BmiPrsStartOffset=NULL;
+ volatile uint32_t *p_BmiInitPrsResult=NULL;
+ volatile uint32_t *p_BmiCcBase=NULL;
+ uint8_t hdrNum, L3HdrNum, greHdrNum;
+ int i;
+ bool isEmptyClsPlanGrp;
+ uint32_t tmpHxs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint16_t absoluteProfileId;
+ uint8_t physicalSchemeId;
+ uint32_t ccTreePhysOffset;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+
+ ASSERT_COND(p_FmPort);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ p_FmPort->netEnvId = FmPcdGetNetEnvId(p_PcdParams->h_NetEnv);
+
+ p_FmPort->pcdEngines = 0;
+
+ /* initialize p_FmPort->pcdEngines field in port's structure */
+ switch (p_PcdParams->pcdSupport)
+ {
+ case (e_FM_PORT_PCD_SUPPORT_NONE):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No PCD configuration required if e_FM_PORT_PCD_SUPPORT_NONE selected"));
+ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PLCR_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (e_FM_PORT_PCD_SUPPORT_CC_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid pcdSupport"));
+ }
+
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams > FM_PCD_PRS_NUM_OF_HDRS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Port parser numOfHdrsWithAdditionalParams may not exceed %d", FM_PCD_PRS_NUM_OF_HDRS));
+
+ /* check that parameters exist for each and only each defined engine */
+ if ((!!(p_FmPort->pcdEngines & FM_PCD_PRS) != !!p_PcdParams->p_PrsParams) ||
+ (!!(p_FmPort->pcdEngines & FM_PCD_KG) != !!p_PcdParams->p_KgParams) ||
+ (!!(p_FmPort->pcdEngines & FM_PCD_CC) != !!p_PcdParams->p_CcParams))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
+ p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[0];
+ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
+ p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[0];
+ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* set PCD port parameter */
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ err = FmPcdCcBindTree(p_FmPort->h_FmPcd,
+ p_PcdParams,
+ p_PcdParams->p_CcParams->h_CcTree,
+ &ccTreePhysOffset,
+ p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
+ p_FmPort->ccTreeId = p_PcdParams->p_CcParams->h_CcTree;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_KG)
+ {
+ if (p_PcdParams->p_KgParams->numOfSchemes == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For ports using Keygen, at least one scheme must be bound. "));
+
+ err = FmPcdKgSetOrBindToClsPlanGrp(p_FmPort->h_FmPcd,
+ p_FmPort->hardwarePortId,
+ p_FmPort->netEnvId,
+ p_FmPort->optArray,
+ &p_FmPort->clsPlanGrpId,
+ &isEmptyClsPlanGrp);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FmPcdKgSetOrBindToClsPlanGrp failed. "));
+
+ p_FmPort->useClsPlan = !isEmptyClsPlanGrp;
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PcdParams->p_KgParams->numOfSchemes;
+ schemeBind.useClsPlan = p_FmPort->useClsPlan;
+
+ /* for each scheme */
+ for (i=0; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ {
+ ASSERT_COND(p_PcdParams->p_KgParams->h_Schemes[i]);
+ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_Schemes[i]);
+ schemeBind.schemesIds[i] = physicalSchemeId;
+ /* build vector */
+ p_FmPort->schemesPerPortVector |= 1 << (31 - (uint32_t)physicalSchemeId);
+#if (DPAA_VERSION >= 11)
+ /*because of the state that VSPE is defined per port - all PCD path should be according to this requirement
+ if !VSPE - in port, for relevant scheme VSPE can not be set*/
+ if (!p_FmPort->vspe && FmPcdKgGetVspe((p_PcdParams->p_KgParams->h_Schemes[i])))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("VSPE is not at port level"));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /***************************/
+ /* configure NIA after BMI */
+ /***************************/
+ /* rfne may contain FDCS bits, so first we read them. */
+ p_FmPort->savedBmiNia = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+
+ /* If policer is used directly after BMI or PRS */
+ if ((p_FmPort->pcdEngines & FM_PCD_PLCR) &&
+ ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PLCR_ONLY) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR)))
+ {
+ if (!p_PcdParams->p_PlcrParams->h_Profile)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Profile should be initialized"));
+
+ absoluteProfileId = (uint16_t)FmPcdPlcrProfileGetAbsoluteId(p_PcdParams->p_PlcrParams->h_Profile);
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Private port profile not valid."));
+
+ tmpReg = (uint32_t)(absoluteProfileId | NIA_PLCR_ABSOLUTE);
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
+ /* update BMI HPNIA */
+ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_PLCR | tmpReg));
+ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
+ /* update BMI NIA */
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PLCR);
+ }
+
+#ifdef FM_CAPWAP_SUPPORT
+ /* if CC is used directly after BMI */
+ if ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_ONLY) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR))
+ {
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("e_FM_PORT_PCD_SUPPORT_CC_xx available for offline parsing ports only"));
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
+ /* check that prs start offset == RIM[FOF] */
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS)
+ {
+ ASSERT_COND(p_PcdParams->p_PrsParams);
+ /* if PRS is used it is always first */
+ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->firstPrsHdr);
+ if (hdrNum == ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PRS | (uint32_t)(hdrNum));
+ /* set after parser NIA */
+ tmpReg = 0;
+ switch (p_PcdParams->pcdSupport)
+ {
+ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
+ WRITE_UINT32(*p_BmiPrsNia, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd));
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
+ tmpReg = NIA_KG_CC_EN;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
+ if (p_PcdParams->p_KgParams->directScheme)
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_DirectScheme);
+ /* check that this scheme was bound to this port */
+ for (i=0 ; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ if (p_PcdParams->p_KgParams->h_DirectScheme == p_PcdParams->p_KgParams->h_Schemes[i])
+ break;
+ if (i == p_PcdParams->p_KgParams->numOfSchemes)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Direct scheme is not one of the port selected schemes."));
+ tmpReg |= (uint32_t)(NIA_KG_DIRECT | physicalSchemeId);
+ }
+ WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_KG | tmpReg);
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR):
+ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid PCD support"));
+ }
+
+ /* set start parsing offset */
+ WRITE_UINT32(*p_BmiPrsStartOffset, p_PcdParams->p_PrsParams->parsingOffset);
+
+ /************************************/
+ /* Parser port parameters */
+ /************************************/
+ /* stop before configuring */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
+ /* wait for parser to be in idle state */
+ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
+
+ /* set soft seq attachment register */
+ memset(tmpHxs, 0, FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t));
+
+ /* set protocol options */
+ for (i=0;p_FmPort->optArray[i];i++)
+ switch (p_FmPort->optArray[i])
+ {
+ case (ETH_BROADCAST):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_BC_SHIFT;
+ break;
+ case (ETH_MULTICAST):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_MC_SHIFT;
+ break;
+ case (VLAN_STACKED):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_VLAN)
+ tmpHxs[hdrNum] |= (i+1)<< PRS_HDR_VLAN_STACKED_SHIFT;
+ break;
+ case (MPLS_STACKED):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_MPLS_STACKED_SHIFT;
+ break;
+ case (IPV4_BROADCAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_BC_SHIFT;
+ break;
+ case (IPV4_MULTICAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_MC_SHIFT;
+ break;
+ case (IPV4_UNICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_UC_SHIFT;
+ break;
+ case (IPV4_MULTICAST_BROADCAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_MC_BC_SHIFT;
+ break;
+ case (IPV6_MULTICAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_1_MC_SHIFT;
+ break;
+ case (IPV6_UNICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_UC_SHIFT;
+ break;
+ case (IPV6_MULTICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_MC_SHIFT;
+ break;
+ }
+
+ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd,
+ p_FmPort->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP))
+ {
+ p_PcdParams->p_PrsParams->additionalParams
+ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].hdr = HEADER_TYPE_UDP;
+ p_PcdParams->p_PrsParams->additionalParams
+ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].swPrsEnable = TRUE;
+ p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams++;
+ }
+
+ /* set MPLS default next header - HW reset workaround */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
+ tmpHxs[hdrNum] |= PRS_HDR_MPLS_LBL_INTER_EN;
+ GET_PRS_HDR_NUM(L3HdrNum, HEADER_TYPE_USER_DEFINED_L3);
+ tmpHxs[hdrNum] |= (uint32_t)L3HdrNum << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
+
+ /* for GRE, disable errors */
+ GET_PRS_HDR_NUM(greHdrNum, HEADER_TYPE_GRE);
+ tmpHxs[greHdrNum] |= PRS_HDR_ERROR_DIS;
+
+ /* For UDP remove PAD from L4 checksum calculation */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_UDP);
+ tmpHxs[hdrNum] |= PRS_HDR_UDP_PAD_REMOVAL;
+ /* For TCP remove PAD from L4 checksum calculation */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_TCP);
+ tmpHxs[hdrNum] |= PRS_HDR_TCP_PAD_REMOVAL;
+
+ /* config additional params for specific headers */
+ for (i=0; i<p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams; i++)
+ {
+ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->additionalParams[i].hdr);
+ if (hdrNum== ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ if (hdrNum==NO_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Private headers may not use additional parameters"));
+
+ err = AdditionalPrsParams(p_FmPort, &p_PcdParams->p_PrsParams->additionalParams[i], &tmpHxs[hdrNum]);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+
+ /* Check if ip-reassembly port - need to update NIAs */
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+ /* link to sw parser code for IP Frag - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv4_LABEL);
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL);
+ }
+
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ /* link to sw parser code for IP Frag - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL);
+ }
+
+#ifdef FM_CAPWAP_SUPPORT
+ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd,
+ p_FmPort->netEnvId, HEADER_TYPE_UDP_LITE))
+ {
+ /* link to sw parser code for udp lite - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_USER_DEFINED_L4)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | UDP_LITE_SW_PATCH_LABEL);
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+ for (i=0 ; i<FM_PCD_PRS_NUM_OF_HDRS ; i++)
+ {
+ /* For all header set LCV as taken from netEnv*/
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].lcv,
+ FmPcdGetLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId, (uint8_t)i));
+ /* set HXS register according to default+Additional params+protocol options */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].softSeqAttach, tmpHxs[i]);
+ }
+
+ /* set tpid. */
+ tmpReg = PRS_TPID_DFLT;
+ if (p_PcdParams->p_PrsParams->setVlanTpid1)
+ {
+ tmpReg &= PRS_TPID2_MASK;
+ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid1 << PRS_PCTPID_SHIFT;
+ }
+ if (p_PcdParams->p_PrsParams->setVlanTpid2)
+ {
+ tmpReg &= PRS_TPID1_MASK;
+ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid2;
+ }
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pctpid, tmpReg);
+
+ /* enable parser */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, 0);
+
+ if (p_PcdParams->p_PrsParams->prsResultPrivateInfo)
+ p_FmPort->privateInfo = p_PcdParams->p_PrsParams->prsResultPrivateInfo;
+
+ } /* end parser */
+ else
+ p_FmPort->privateInfo = 0;
+
+ WRITE_UINT32(*p_BmiPrsStartOffset, GET_UINT32(*p_BmiPrsStartOffset) + p_FmPort->internalBufferOffset);
+
+ /* set initial parser result - used for all engines */
+ for (i=0;i<FM_PORT_PRS_RESULT_NUM_OF_WORDS;i++)
+ {
+ if (!i)
+ WRITE_UINT32(*(p_BmiInitPrsResult),
+ (uint32_t)(((uint32_t)p_FmPort->privateInfo << BMI_PR_PORTID_SHIFT)
+ | BMI_PRS_RESULT_HIGH));
+ else
+ {
+ if (i< FM_PORT_PRS_RESULT_NUM_OF_WORDS/2)
+ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_HIGH);
+ else
+ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_LOW);
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error DeletePcd(t_FmPort *p_FmPort)
+{
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiNia=NULL;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+
+ ASSERT_COND(p_FmPort);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!p_FmPort->pcdEngines)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("called for non PCD port"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ if ((GET_UINT32(*p_BmiNia) & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("port has to be detached previousely"));
+
+ /* "cut" PCD out of the port's flow - go to BMI */
+ /* WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); */
+
+ if (p_FmPort->pcdEngines | FM_PCD_PRS)
+ {
+ WRITE_UINT32(*p_BmiPrsStartOffset, 0);
+
+ /* stop parser */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
+ /* wait for parser to be in idle state */
+ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_KG)
+ {
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+
+ /* unbind all schemes */
+ p_FmPort->schemesPerPortVector = GetPortSchemeBindParams(p_FmPort, &schemeBind);
+
+ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ err = FmPcdKgDeleteOrUnbindPortToClsPlanGrp(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, p_FmPort->clsPlanGrpId);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ p_FmPort->useClsPlan = FALSE;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ /* unbind - we need to get the treeId too */
+ err = FmPcdCcUnbindTree(p_FmPort->h_FmPcd, p_FmPort->ccTreeId);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ p_FmPort->pcdEngines = 0;
+
+ return E_OK;
+}
+
+static t_Error AttachPCD(t_FmPort *p_FmPort)
+{
+ volatile uint32_t *p_BmiNia=NULL;
+
+ ASSERT_COND(p_FmPort);
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
+ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 1, p_FmPort->orFmanCtrl)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION,
+ ("may be called only for ports in BMI-to-BMI state."));
+
+ WRITE_UINT32(*p_BmiNia, p_FmPort->savedBmiNia);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN)
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, p_FmPort->savedQmiPnen);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN)
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, p_FmPort->savedNonRxQmiRegsPndn);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofene, p_FmPort->savedBmiFene);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfene, p_FmPort->savedBmiFene);
+ }
+ if (p_FmPort->requiredAction & UPDATE_NIA_FPNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne, p_FmPort->savedBmiFpne);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->savedBmiFpne);
+ }
+ if (p_FmPort->requiredAction & UPDATE_NIA_CMNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocmne, p_FmPort->savedBmiCmne);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcmne, p_FmPort->savedBmiCmne);
+ }
+
+ return E_OK;
+}
+
+static t_Error DetachPCD(t_FmPort *p_FmPort)
+{
+ volatile uint32_t *p_BmiNia=NULL;
+
+ ASSERT_COND(p_FmPort);
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN)
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+ break;
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_RX):
+ case (e_FM_PORT_TYPE_RX_10G):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage"));
+ }
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN)
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX);
+ break;
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage"));
+ }
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
+ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 2, p_FmPort->orFmanCtrl)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ p_FmPort->requiredAction = 0;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+void FmPortSetMacsecLcv(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ uint32_t macsecEn = BMI_PORT_CFG_EN_MACSEC;
+ uint32_t lcv, walking1Mask = 0x80000000;
+ uint8_t cnt = 0;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Rx ports only"));
+ return;
+ }
+
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
+ /* get LCV for MACSEC */
+ if ((p_FmPort->h_FmPcd) && ((lcv = FmPcdGetMacsecLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId))!= 0))
+ {
+ while (!(lcv & walking1Mask))
+ {
+ cnt++;
+ walking1Mask >>= 1;
+ }
+
+ macsecEn |= (uint32_t)cnt << BMI_PORT_CFG_MS_SEL_SHIFT;
+ }
+
+ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | macsecEn);
+}
+
+void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Tx ports only"));
+ return;
+ }
+
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfca;
+ tmpReg = GET_UINT32(*p_BmiCfgReg) & ~BMI_CMD_ATTR_MACCMD_MASK;
+ tmpReg |= BMI_CMD_ATTR_MACCMD_SECURED;
+ tmpReg |= (((uint32_t)dfltSci << BMI_CMD_ATTR_MACCMD_SC_SHIFT) & BMI_CMD_ATTR_MACCMD_SC_MASK);
+
+ WRITE_UINT32(*p_BmiCfgReg, tmpReg);
+}
+
+uint8_t FmPortGetNetEnvId(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->netEnvId;
+}
+
+uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->hardwarePortId;
+}
+
+uint32_t FmPortGetPcdEngines(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->pcdEngines;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t muramPageOffset;
+
+ ASSERT_COND(p_FmPort);
+ ASSERT_COND(p_Value);
+
+ if (p_FmPort->gprFunc != e_FM_PORT_GPR_EMPTY)
+ {
+ if (p_FmPort->gprFunc != gprFunc)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("gpr was assigned with different func"));
+ }
+ else
+ {
+ switch (gprFunc)
+ {
+ case (e_FM_PORT_GPR_MURAM_PAGE):
+ p_FmPort->p_MuramPage = FM_MURAM_AllocMem(p_FmPort->h_FmMuram,
+ 256,
+ 8);
+ if (!p_FmPort->p_MuramPage)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for page"));
+
+ IOMemSet32(p_FmPort->p_MuramPage, 0, 256);
+ muramPageOffset = (uint32_t)(XX_VirtToPhys(p_FmPort->p_MuramPage) -
+ p_FmPort->fmMuramPhysBaseAddr);
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr, muramPageOffset);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ogpr, muramPageOffset);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ p_FmPort->gprFunc = gprFunc;
+ }
+
+ switch (p_FmPort->gprFunc)
+ {
+ case (e_FM_PORT_GPR_MURAM_PAGE):
+ *p_Value = p_FmPort->p_MuramPage;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_CcParams)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int tmpInt;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+
+ /* this function called from Cc for pass and receive parameters port params between CC and PORT*/
+
+ if ((p_CcParams->getCcParams.type & OFFSET_OF_PR) &&
+ (p_FmPort->bufferOffsets.prsResultOffset != ILLEGAL_BASE))
+ {
+ p_CcParams->getCcParams.prOffset = (uint8_t)p_FmPort->bufferOffsets.prsResultOffset;
+ p_CcParams->getCcParams.type &= ~OFFSET_OF_PR;
+ }
+ if (p_CcParams->getCcParams.type & HW_PORT_ID)
+ {
+ p_CcParams->getCcParams.hardwarePortId = (uint8_t)p_FmPort->hardwarePortId;
+ p_CcParams->getCcParams.type &= ~HW_PORT_ID;
+ }
+ if ((p_CcParams->getCcParams.type & OFFSET_OF_DATA) &&
+ (p_FmPort->bufferOffsets.dataOffset != ILLEGAL_BASE))
+ {
+ p_CcParams->getCcParams.dataOffset = (uint16_t)p_FmPort->bufferOffsets.dataOffset;
+ p_CcParams->getCcParams.type &= ~OFFSET_OF_DATA;
+ }
+ if (p_CcParams->getCcParams.type & NUM_OF_TASKS)
+ {
+ p_CcParams->getCcParams.numOfTasks = (uint8_t)p_FmPort->tasks.num;
+ p_CcParams->getCcParams.type &= ~NUM_OF_TASKS;
+ }
+ if (p_CcParams->getCcParams.type & NUM_OF_EXTRA_TASKS)
+ {
+ p_CcParams->getCcParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra;
+ p_CcParams->getCcParams.type &= ~NUM_OF_EXTRA_TASKS;
+ }
+ if (p_CcParams->getCcParams.type & FM_REV)
+ {
+ p_CcParams->getCcParams.revInfo.majorRev = p_FmPort->fmRevInfo.majorRev;
+ p_CcParams->getCcParams.revInfo.minorRev = p_FmPort->fmRevInfo.minorRev;
+ p_CcParams->getCcParams.type &= ~FM_REV;
+ }
+ if (p_CcParams->getCcParams.type & GET_NIA_FPNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne);
+ else
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne);
+ p_CcParams->getCcParams.type &= ~GET_NIA_FPNE;
+ }
+ if (p_CcParams->getCcParams.type & GET_NIA_PNDN)
+ {
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn);
+ p_CcParams->getCcParams.type &= ~GET_NIA_PNDN;
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) &&
+ !(p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY))
+ {
+ p_FmPort->requiredAction |= UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ p_FmPort->orFmanCtrl = p_CcParams->setCcParams.orFmanCtrl;
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_PNEN))
+ {
+ p_FmPort->savedQmiPnen = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_PNEN;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNEN)
+ {
+ if (p_FmPort->savedQmiPnen != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNEN was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_PNDN))
+ {
+ p_FmPort->savedNonRxQmiRegsPndn = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_PNDN;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNDN)
+ {
+ if (p_FmPort->savedNonRxQmiRegsPndn != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNDN was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FENE) &&
+ (p_CcParams->setCcParams.overwrite ||
+ !(p_FmPort->requiredAction & UPDATE_NIA_FENE)))
+ {
+ p_FmPort->savedBmiFene = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_FENE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->savedBmiFene != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFENE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_FPNE))
+ {
+ p_FmPort->savedBmiFpne = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_FPNE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FPNE)
+ {
+ if (p_FmPort->savedBmiFpne != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFPNE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_CMNE))
+ {
+ p_FmPort->savedBmiCmne = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_CMNE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_CMNE)
+ {
+ if (p_FmPort->savedBmiCmne != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xCMNE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_PSO) &&
+ !(p_FmPort->requiredAction & UPDATE_PSO))
+ {
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+ /* set start parsing offset */
+ tmpInt = (int)GET_UINT32(*p_BmiPrsStartOffset)+ p_CcParams->setCcParams.psoSize;
+ if (tmpInt>0)
+ WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)tmpInt);
+
+ p_FmPort->requiredAction |= UPDATE_PSO;
+ p_FmPort->savedPrsStartOffset = p_CcParams->setCcParams.psoSize;
+
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_PSO)
+ {
+ if (p_FmPort->savedPrsStartOffset != p_CcParams->setCcParams.psoSize)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser start offset was defoned previousley different"));
+ }
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams)
+{
+ t_FmPort *p_FmPort;
+ uintptr_t baseAddr = p_FmPortParams->baseAddr;
+ uint32_t tmpReg;
+
+ /* Allocate FM structure */
+ p_FmPort = (t_FmPort *) XX_Malloc(sizeof(t_FmPort));
+ if (!p_FmPort)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver structure"));
+ return NULL;
+ }
+ memset(p_FmPort, 0, sizeof(t_FmPort));
+
+ /* Allocate the FM driver's parameters structure */
+ p_FmPort->p_FmPortDriverParam = (t_FmPortDriverParam *)XX_Malloc(sizeof(t_FmPortDriverParam));
+ if (!p_FmPort->p_FmPortDriverParam)
+ {
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver parameters"));
+ return NULL;
+ }
+ memset(p_FmPort->p_FmPortDriverParam, 0, sizeof(t_FmPortDriverParam));
+
+ /* Initialize FM port parameters which will be kept by the driver */
+ p_FmPort->portType = p_FmPortParams->portType;
+ p_FmPort->portId = p_FmPortParams->portId;
+ p_FmPort->pcdEngines = FM_PCD_NONE;
+ p_FmPort->f_Exception = p_FmPortParams->f_Exception;
+ p_FmPort->h_App = p_FmPortParams->h_App;
+ p_FmPort->h_Fm = p_FmPortParams->h_Fm;
+
+ /* get FM revision */
+ FM_GetRevision(p_FmPort->h_Fm, &p_FmPort->fmRevInfo);
+
+ /* calculate global portId number */
+ SW_PORT_ID_TO_HW_PORT_ID(p_FmPort->hardwarePortId, p_FmPort->portType, p_FmPortParams->portId);
+
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ DBG(WARNING,
+ ("Port ID %d is recommended for HC port. Overwriting HW defaults to be suitable for HC.",
+ FM_OH_PORT_ID));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_FmPortParams->portId == FM_OH_PORT_ID))
+ DBG(WARNING, ("Use non-zero portId for OP port due to insufficient resources on portId 0."));
+ }
+
+ /* Initialize FM port parameters for initialization phase only */
+ p_FmPort->p_FmPortDriverParam->baseAddr = baseAddr;
+ /* set memory map pointers */
+ p_FmPort->p_FmPortQmiRegs = (t_FmPortQmiRegs *)UINT_TO_PTR(baseAddr + QMI_PORT_REGS_OFFSET);
+ p_FmPort->p_FmPortBmiRegs = (u_FmPortBmiRegs *)UINT_TO_PTR(baseAddr + BMI_PORT_REGS_OFFSET);
+ p_FmPort->p_FmPortPrsRegs = (t_FmPortPrsRegs *)UINT_TO_PTR(baseAddr + PRS_PORT_REGS_OFFSET);
+
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize = DEFAULT_PORT_bufferPrefixContent_privDataSize;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult= DEFAULT_PORT_bufferPrefixContent_passPrsResult;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp= DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo
+ = DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign;
+ p_FmPort->p_FmPortDriverParam->dmaSwapData = DEFAULT_PORT_dmaSwapData;
+ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = DEFAULT_PORT_dmaIntContextCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = DEFAULT_PORT_dmaHeaderCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = DEFAULT_PORT_dmaScatterGatherCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = DEFAULT_PORT_dmaWriteOptimize;
+ p_FmPort->p_FmPortDriverParam->liodnBase = p_FmPortParams->liodnBase;
+ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_PORT_cheksumLastBytesIgnore;
+ p_FmPort->p_FmPortDriverParam->color = DEFAULT_PORT_color;
+
+ p_FmPort->maxFrameLength = DEFAULT_PORT_maxFrameLength;
+ /* resource distribution. */
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS;
+ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS;
+ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType, p_FmPort->fmRevInfo.majorRev);
+ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType);
+ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType);
+ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType);
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ {
+ /* Overwrite HC defaults */
+ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS;
+ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS;
+ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType, p_FmPort->fmRevInfo.majorRev);
+ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType);
+ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType);
+ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType);
+ }
+ else
+ {
+ p_FmPort->fifoBufs.num = 0;
+ p_FmPort->fifoBufs.extra = 0;
+ p_FmPort->openDmas.num = 0;
+ p_FmPort->openDmas.extra = 0;
+ p_FmPort->tasks.num = 0;
+ p_FmPort->tasks.extra = 0;
+ }
+ }
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ p_FmPort->p_FmPortDriverParam->syncReq = DEFAULT_PORT_syncReqForHc;
+ else
+ p_FmPort->p_FmPortDriverParam->syncReq = DEFAULT_PORT_syncReq;
+
+ /* Port type specific initialization: */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
+ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = DEFAULT_PORT_frmDiscardOverride;
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX):
+ case (e_FM_PORT_TYPE_RX_10G):
+ /* Initialize FM port parameters for initialization phase only */
+ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = DEFAULT_PORT_cutBytesFromEnd;
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = FALSE;
+ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = DEFAULT_PORT_frmDiscardOverride;
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = DEFAULT_PORT_rxFifoPriElevationLevel;
+ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = DEFAULT_PORT_rxFifoThreshold;
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfp);
+ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = (((tmpReg & BMI_RX_FIFO_PRI_ELEVATION_MASK) >> BMI_RX_FIFO_PRI_ELEVATION_SHIFT) + 1) * BMI_FIFO_UNITS ;
+ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = (((tmpReg & BMI_RX_FIFO_THRESHOLD_MASK) >> BMI_RX_FIFO_THRESHOLD_SHIFT) + 1) * BMI_FIFO_UNITS;
+ }
+
+ p_FmPort->p_FmPortDriverParam->bufMargins.endMargins = DEFAULT_PORT_BufMargins_endMargins;
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard;
+ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = DEFAULT_PORT_forwardIntContextReuse;
+#if (DPAA_VERSION >= 11)
+ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+ break;
+
+ case (e_FM_PORT_TYPE_TX):
+ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = FALSE;
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+ tmpReg = 0x00001013;
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp, tmpReg);
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+ case (e_FM_PORT_TYPE_TX_10G):
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = DEFAULT_PORT_txFifoMinFillLevel;
+ p_FmPort->fifoDeqPipelineDepth =
+ (uint8_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_fifoDeqPipelineDepth_1G :
+ DEFAULT_PORT_fifoDeqPipelineDepth_10G);
+ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = DEFAULT_PORT_txFifoLowComfLevel;
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp);
+ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel =
+ ((tmpReg & BMI_TX_FIFO_MIN_FILL_MASK) >> BMI_TX_FIFO_MIN_FILL_SHIFT) * BMI_FIFO_UNITS ;
+ p_FmPort->fifoDeqPipelineDepth =
+ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1);
+ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel =
+ (((tmpReg & BMI_TX_LOW_COMF_MASK) >> BMI_TX_LOW_COMF_SHIFT) + 1) * BMI_FIFO_UNITS;
+ }
+
+ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType;
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption;
+ p_FmPort->p_FmPortDriverParam->deqHighPriority =
+ (bool)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_deqHighPriority_1G :
+ DEFAULT_PORT_deqHighPriority_10G);
+ p_FmPort->p_FmPortDriverParam->deqByteCnt =
+ (uint16_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_deqByteCnt_1G :
+ DEFAULT_PORT_deqByteCnt_10G);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard;
+#if (DPAA_VERSION >= 11)
+ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption_HC;
+ p_FmPort->p_FmPortDriverParam->deqHighPriority = DEFAULT_PORT_deqHighPriority_1G;
+ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType;
+ p_FmPort->p_FmPortDriverParam->deqByteCnt = DEFAULT_PORT_deqByteCnt_1G;
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_OH;
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofp);
+ p_FmPort->fifoDeqPipelineDepth =
+ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ {
+ /* Overwrite HC defaults */
+ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_OH;
+ }
+ }
+
+#ifndef FM_FRAME_END_PARAMS_FOR_OP
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_notSupported;
+#endif /* !FM_FRAME_END_PARAMS_FOR_OP */
+
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if (!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6)))
+ p_FmPort->fifoDeqPipelineDepth = DEFAULT_notSupported;
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+ break;
+
+ default:
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ return NULL;
+ }
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = (e_FmPortDeqPrefetchOption)DEFAULT_notSupported;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ p_FmPort->imEn = p_FmPortParams->independentModeEnable;
+
+ if (p_FmPort->imEn)
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ p_FmPort->fifoDeqPipelineDepth = DEFAULT_PORT_fifoDeqPipelineDepth_IM;
+ FmPortConfigIM(p_FmPort, p_FmPortParams);
+ }
+ else
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX):
+ case (e_FM_PORT_TYPE_RX_10G):
+ /* Initialize FM port parameters for initialization phase only */
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools,
+ &p_FmPortParams->specificParams.rxParams.extBufPools,
+ sizeof(t_FmExtPools));
+ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.rxParams.errFqid;
+ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.rxParams.dfltFqid;
+ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.rxParams.liodnOffset;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_TX):
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.nonRxParams.errFqid;
+ p_FmPort->p_FmPortDriverParam->deqSubPortal =
+ (uint8_t)(p_FmPortParams->specificParams.nonRxParams.qmChannel & QMI_DEQ_CFG_SUBPORTAL_MASK);
+ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.nonRxParams.dfltFqid;
+ break;
+ default:
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ return NULL;
+ }
+ }
+
+ memset(p_FmPort->name, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPort->name, "FM-%d-port-%s-%d",
+ FmGetId(p_FmPort->h_Fm),
+ ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ?
+ "OH" : (p_FmPort->portType == e_FM_PORT_TYPE_RX ?
+ "1g-RX" : (p_FmPort->portType == e_FM_PORT_TYPE_TX ?
+ "1g-TX" : (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G ?
+ "10g-RX" : "10g-TX")))),
+ p_FmPort->portId) == 0)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ return NULL;
+ }
+
+ p_FmPort->h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPort->h_Spinlock)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ return NULL;
+ }
+
+ return p_FmPort;
+}
+
+/**************************************************************************//**
+ @Function FM_PORT_Init
+
+ @Description Initializes the FM module
+
+ @Param[in] h_FmPort - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Init(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPortDriverParam *p_Params;
+ t_Error err = E_OK;
+ t_FmInterModulePortInitParams fmParams;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ err = FmSpBuildBufferStructure(&p_FmPort->p_FmPortDriverParam->intContext,
+ &p_FmPort->p_FmPortDriverParam->bufferPrefixContent,
+ &p_FmPort->p_FmPortDriverParam->bufMargins,
+ &p_FmPort->bufferOffsets,
+ &p_FmPort->internalBufferOffset);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+ if ((p_FmPort->p_FmPortDriverParam->bcbWorkaround) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ {
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard |= FM_PORT_FRM_ERR_PHYSICAL;
+ p_FmPort->fifoBufs.num += 4*KILOBYTE;
+ }
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+ CHECK_INIT_PARAMETERS(p_FmPort, CheckInitParameters);
+
+ p_Params = p_FmPort->p_FmPortDriverParam;
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ if (!p_FmPort->imEn)
+ {
+ /* Call the external Buffer routine which also checks fifo
+ size and updates it if necessary */
+ /* define external buffer pools and pool depletion*/
+ err = SetExtBufferPools(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /************************************************************/
+ /* Call FM module routine for communicating parameters */
+ /************************************************************/
+ memset(&fmParams, 0, sizeof(fmParams));
+ fmParams.hardwarePortId = p_FmPort->hardwarePortId;
+ fmParams.portType = (e_FmPortType)p_FmPort->portType;
+ fmParams.numOfTasks = (uint8_t)p_FmPort->tasks.num;
+ fmParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra;
+ fmParams.numOfOpenDmas = (uint8_t)p_FmPort->openDmas.num;
+ fmParams.numOfExtraOpenDmas = (uint8_t)p_FmPort->openDmas.extra;
+ if (p_FmPort->fifoBufs.num)
+ {
+ err = VerifySizeOfFifo(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ fmParams.sizeOfFifo = p_FmPort->fifoBufs.num;
+ fmParams.extraSizeOfFifo = p_FmPort->fifoBufs.extra;
+ fmParams.independentMode = p_FmPort->imEn;
+ fmParams.liodnOffset = p_Params->liodnOffset;
+ fmParams.liodnBase = p_Params->liodnBase;
+ fmParams.deqPipelineDepth = p_FmPort->fifoDeqPipelineDepth;
+ fmParams.maxFrameLength = p_FmPort->maxFrameLength;
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ {
+ if (!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6)))
+ /* HC ports do not have fifoDeqPipelineDepth, but it is needed only
+ * for deq threshold calculation.
+ */
+ fmParams.deqPipelineDepth = 2;
+ }
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+
+
+ err = FmGetSetPortParams(p_FmPort->h_Fm, &fmParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* get params for use in init */
+ p_FmPort->fmMuramPhysBaseAddr =
+ (uint64_t)((uint64_t)(fmParams.fmMuramPhysBaseAddr.low) |
+ ((uint64_t)(fmParams.fmMuramPhysBaseAddr.high) << 32));
+ p_FmPort->h_FmMuram = FmGetMuramHandle(p_FmPort->h_Fm);
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ p_FmPort->tasks.num = fmParams.numOfTasks;
+ p_FmPort->tasks.extra = fmParams.numOfExtraTasks;
+ p_FmPort->openDmas.num = fmParams.numOfOpenDmas;
+ p_FmPort->openDmas.extra = fmParams.numOfExtraOpenDmas;
+ p_FmPort->fifoBufs.num = fmParams.sizeOfFifo;
+ p_FmPort->fifoBufs.extra = fmParams.extraSizeOfFifo;
+ }
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+ /**********************/
+ /* Init BMI Registers */
+ /**********************/
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ err = BmiRxPortInit(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ err = BmiTxPortInit(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ err = BmiOhPortInit(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ }
+
+ /**********************/
+ /* Init QMI Registers */
+ /**********************/
+ if (!p_FmPort->imEn && ((err = QmiInit(p_FmPort)) != E_OK))
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_FmPort->imEn && ((err = FmPortImInit(p_FmPort)) != E_OK))
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ FmPortDriverParamFree(p_FmPort);
+
+ return E_OK;
+}
+
+/**************************************************************************//**
+ @Function FM_PORT_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPort - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Free(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmInterModulePortFreeParams fmParams;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ if (p_FmPort->pcdEngines)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Trying to free a port with PCD. FM_PORT_DeletePCD must be called first."));
+
+ if (p_FmPort->enabled)
+ {
+ if (FM_PORT_Disable(p_FmPort) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM_PORT_Disable FAILED"));
+ }
+
+ if (p_FmPort->imEn)
+ FmPortImFree(p_FmPort);
+
+ FmPortDriverParamFree(p_FmPort);
+
+ fmParams.hardwarePortId = p_FmPort->hardwarePortId;
+ fmParams.portType = (e_FmPortType)p_FmPort->portType;
+ fmParams.deqPipelineDepth = p_FmPort->fifoDeqPipelineDepth;
+
+ FmFreePortParams(p_FmPort->h_Fm, &fmParams);
+
+#if (DPAA_VERSION >= 11)
+ if (FmVSPFreeForPort(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId) != E_OK)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("VSP free of port FAILED"));
+
+ if (p_FmPort->p_MuramPage)
+ FM_MURAM_FreeMem(p_FmPort->h_FmMuram, p_FmPort->p_MuramPage);
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_FmPort->h_Spinlock)
+ XX_FreeSpinlock(p_FmPort->h_Spinlock);
+
+ XX_Free(p_FmPort);
+
+ return E_OK;
+}
+
+
+/*************************************************/
+/* API Advanced Init unit functions */
+/*************************************************/
+
+t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->setNumOfOpenDmas = TRUE;
+ memcpy(&p_FmPort->openDmas, p_OpenDmas, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc));
+ p_FmPort->p_FmPortDriverParam->setNumOfTasks = TRUE;
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->setSizeOfFifo = TRUE;
+ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->deqHighPriority = highPri;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->deqType = deqType;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = deqPrefetchOption;
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_BackupBmPools)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools));
+ if (!p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed"));
+ memcpy(p_FmPort->p_FmPortDriverParam->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->deqByteCnt = deqByteCnt;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, t_FmBufferPrefixContent *p_FmBufferPrefixContent)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent));
+ /* if dataAlign was not initialized by user, we return to driver's deafult */
+ if (!p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign)
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = cheksumLastBytesIgnore;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = cutBytesFromEnd;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
+
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion,
+ &p_FmPortObservedBufPoolDepletion->poolDepletionParams,
+ sizeof(t_FmBufPoolDepletion));
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools,
+ &p_FmPortObservedBufPoolDepletion->poolsParams,
+ sizeof(t_FmExtPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
+
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, p_FmExtPools, sizeof(t_FmExtPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ p_FmPort->p_FmPortDriverParam->color = color;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->syncReq = syncReq;
+
+ return E_OK;
+}
+
+
+t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = override;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = errs;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dmaSwapData = swapData;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = intContextCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = headerCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = scatterGatherCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = optimize;
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ UNUSED(noScatherGather);
+ UNUSED(p_FmPort);
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->noScatherGather = noScatherGather;
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool forwardReuse)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = forwardReuse;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->maxFrameLength = length;
+
+ return E_OK;
+}
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->bcbWorkaround = TRUE;
+
+ return E_OK;
+}
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = minFillLevel;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Rx ports"));
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for IM ports!"));
+
+ p_FmPort->fifoDeqPipelineDepth = deqPipelineDepth;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = fifoLowComfLevel;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = fifoThreshold;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = priElevationLevel;
+
+ return E_OK;
+}
+/****************************************************/
+/* API Run-time Control unit functions */
+/****************************************************/
+
+t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((!p_NumOfOpenDmas->num) || (p_NumOfOpenDmas->num > MAX_NUM_OF_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-num can't be larger than %d", MAX_NUM_OF_DMAS));
+ if (p_NumOfOpenDmas->extra > MAX_NUM_OF_EXTRA_DMAS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
+ err = FmSetNumOfOpenDmas(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfOpenDmas->num, (uint8_t*)&p_NumOfOpenDmas->extra, FALSE);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ memcpy(&p_FmPort->openDmas, p_NumOfOpenDmas, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */
+ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND);
+
+ if ((!p_NumOfTasks->num) || (p_NumOfTasks->num > MAX_NUM_OF_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-num can't be larger than %d", MAX_NUM_OF_TASKS));
+ if (p_NumOfTasks->extra > MAX_NUM_OF_EXTRA_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
+
+ err = FmSetNumOfTasks(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfTasks->num, (uint8_t*)&p_NumOfTasks->extra, FALSE);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* update driver's struct */
+ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (!p_SizeOfFifo->num || (p_SizeOfFifo->num > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
+ if (p_SizeOfFifo->num % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be divisible by %d", BMI_FIFO_UNITS));
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ /* extra FIFO size (allowed only to Rx ports) */
+ if (p_SizeOfFifo->extra % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-extra has to be divisible by %d", BMI_FIFO_UNITS));
+ }
+ else
+ if (p_SizeOfFifo->extra)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No SizeOfFifo-extra for non Rx ports"));
+
+ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc));
+
+ /* we do not change user's parameter */
+ err = VerifySizeOfFifo(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = FmSetSizeOfFifo(p_FmPort->h_Fm,
+ p_FmPort->hardwarePortId,
+ &p_SizeOfFifo->num,
+ &p_SizeOfFifo->extra,
+ FALSE);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
+
+ return p_FmPort->bufferOffsets.dataOffset;
+}
+
+uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.pcdInfoOffset);
+}
+
+t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.prsResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.prsResultOffset);
+}
+
+uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.timeStampOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint64_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.timeStampOffset);
+}
+
+uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.hashResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.hashResultOffset);
+}
+
+t_Error FM_PORT_Disable(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ volatile uint32_t *p_BmiStatusReg = NULL;
+ bool rxPort = FALSE;
+ int tries;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
+ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rst;
+ rxPort = TRUE;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg;
+ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tst;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg;
+ p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ost;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* check if port is already disabled */
+ if (!(GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN))
+ {
+ if (!rxPort && !p_FmPort->imEn)
+ {
+ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN))
+ /* port is disabled */
+ return E_OK;
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistency: Port's QMI is enabled but BMI disabled"));
+ }
+ /* port is disabled */
+ return E_OK;
+ }
+
+ /* Disable QMI */
+ if (!rxPort && !p_FmPort->imEn)
+ {
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
+ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & ~QMI_PORT_CFG_EN);
+ /* wait for QMI to finish Handling dequeue tnums */
+ tries=1000;
+ while ((GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pns) & QMI_PORT_STATUS_DEQ_FD_BSY) &&
+ --tries)
+ XX_UDelay(1);
+ if (!tries)
+ {
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
+ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN);
+ RETURN_ERROR(MAJOR, E_BUSY, ("%s: can't disable! QMI busy", p_FmPort->name));
+ }
+ }
+
+ /* Disable BMI */
+ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) & ~BMI_PORT_CFG_EN);
+
+ if (p_FmPort->imEn)
+ FmPortImDisable(p_FmPort);
+
+ tries=5000;
+ while ((GET_UINT32(*p_BmiStatusReg) & BMI_PORT_STATUS_BSY) &&
+ --tries)
+ XX_UDelay(1);
+
+ if (!tries)
+ {
+ if (!rxPort && !p_FmPort->imEn)
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
+ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN);
+ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | BMI_PORT_CFG_EN);
+
+ RETURN_ERROR(MAJOR, E_BUSY, ("%s: can't disable! BMI Busy", p_FmPort->name));
+ }
+
+ p_FmPort->enabled = 0;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_Enable(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ bool rxPort = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
+ rxPort = TRUE;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* check if port is already enabled */
+ if (GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN)
+ {
+ if (!rxPort && !p_FmPort->imEn)
+ {
+ if (GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN)
+ /* port is enabled */
+ return E_OK;
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistency: Port's BMI is enabled but QMI disabled"));
+ }
+ /* port is enabled */
+ return E_OK;
+ }
+
+ if (p_FmPort->imEn)
+ FmPortImEnable(p_FmPort);
+
+ /* Enable QMI */
+ if (!rxPort && !p_FmPort->imEn)
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
+ GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN);
+
+ /* Enable BMI */
+ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | BMI_PORT_CFG_EN);
+
+ p_FmPort->enabled = 1;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpRateLimit, tmpRateLimitScale;
+ volatile uint32_t *p_RateLimitReg, *p_RateLimitScaleReg;
+ uint8_t factor, countUnitBit;
+ uint16_t baseGran;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only"));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt;
+ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts;
+ baseGran = 16000;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt;
+ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts;
+ baseGran = 10000;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ countUnitBit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm); /* TimeStamp per nano seconds units */
+ /* normally, we use 1 usec as the reference count */
+ factor = 1;
+ /* if ratelimit is too small for a 1usec factor, multiply the factor */
+ while (p_RateLimit->rateLimit < baseGran/factor)
+ {
+ if (countUnitBit==31)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too small"));
+
+ countUnitBit++;
+ factor <<= 1;
+ }
+ /* if ratelimit is too large for a 1usec factor, it is also larger than max rate*/
+ if (p_RateLimit->rateLimit > ((uint32_t)baseGran * (1<<10) * (uint32_t)factor))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too large"));
+
+ tmpRateLimit = (uint32_t)(p_RateLimit->rateLimit*factor/baseGran - 1);
+
+ if (!p_RateLimit->maxBurstSize || (p_RateLimit->maxBurstSize > MAX_BURST_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxBurstSize must be between 1K and %dk", MAX_BURST_SIZE));
+
+ tmpRateLimitScale = ((31 - (uint32_t)countUnitBit) << BMI_COUNT_RATE_UNIT_SHIFT) | BMI_RATE_LIMIT_EN;
+
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT;
+ else
+ {
+#ifndef FM_NO_ADVANCED_RATE_LIMITER
+
+ if ((p_FmPort->fmRevInfo.majorRev == 4) || (p_FmPort->fmRevInfo.majorRev >= 6))
+ {
+ switch (p_RateLimit->rateLimitDivider)
+ {
+ case (e_FM_PORT_DUAL_RATE_LIMITER_NONE):
+ break;
+ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2):
+ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_2;
+ break;
+ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4):
+ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_4;
+ break;
+ case (e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8):
+ tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_8;
+ break;
+ default:
+ break;
+ }
+ tmpRateLimit |= BMI_RATE_LIMIT_BURST_SIZE_GRAN;
+ }
+ else
+#endif /* ! FM_NO_ADVANCED_RATE_LIMITER */
+ {
+ if (p_RateLimit->rateLimitDivider != e_FM_PORT_DUAL_RATE_LIMITER_NONE)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigDualRateLimitScaleDown"));
+
+ if (p_RateLimit->maxBurstSize % 1000)
+ {
+ p_RateLimit->maxBurstSize = (uint16_t)((p_RateLimit->maxBurstSize/1000)+1);
+ DBG(WARNING, ("rateLimit.maxBurstSize rounded up to %d", (p_RateLimit->maxBurstSize/1000+1)*1000));
+ }
+ else
+ p_RateLimit->maxBurstSize = (uint16_t)(p_RateLimit->maxBurstSize/1000);
+ }
+ tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT;
+
+ }
+ WRITE_UINT32(*p_RateLimitScaleReg, tmpRateLimitScale);
+ WRITE_UINT32(*p_RateLimitReg, tmpRateLimit);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_RateLimitReg, *p_RateLimitScaleReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only"));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt;
+ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt;
+ p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ WRITE_UINT32(*p_RateLimitScaleReg, 0);
+ WRITE_UINT32(*p_RateLimitReg, 0);
+
+ return E_OK;
+}
+
+
+t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc);
+ if (enable)
+ tmpReg |= QMI_PORT_CFG_EN_COUNTERS ;
+ else
+ tmpReg &= ~QMI_PORT_CFG_EN_COUNTERS;
+
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, tmpReg);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiPcReg = NULL;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpc;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpc;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opc;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ if (enable)
+ WRITE_UINT32(*p_BmiPcReg, BMI_COUNTERS_EN);
+ else
+ WRITE_UINT32(*p_BmiPcReg, 0);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+ volatile uint32_t *p_BmiPcpReg = NULL;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpcp;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpcp;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opcp;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* check parameters */
+ if (!p_FmPortPerformanceCnt->taskCompVal ||
+ (p_FmPortPerformanceCnt->taskCompVal > p_FmPort->tasks.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.taskCompVal has to be in the range of 1 - %d (current value)!",
+ p_FmPort->tasks.num));
+ if (!p_FmPortPerformanceCnt->dmaCompVal ||
+ (p_FmPortPerformanceCnt->dmaCompVal > p_FmPort->openDmas.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.dmaCompVal has to be in the range of 1 - %d (current value)!",
+ p_FmPort->openDmas.num));
+ if (!p_FmPortPerformanceCnt->fifoCompVal ||
+ (p_FmPortPerformanceCnt->fifoCompVal > p_FmPort->fifoBufs.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.fifoCompVal has to be in the range of 256 - %d (current value)!",
+ p_FmPort->fifoBufs.num));
+ if (p_FmPortPerformanceCnt->fifoCompVal % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.fifoCompVal has to be divisible by %d",
+ BMI_FIFO_UNITS));
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ if (!p_FmPortPerformanceCnt->queueCompVal ||
+ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_RX_QUEUE_COMP))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.queueCompVal for Rx has to be in the range of 1 - %d",
+ MAX_PERFORMANCE_RX_QUEUE_COMP));
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ if (!p_FmPortPerformanceCnt->queueCompVal ||
+ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_TX_QUEUE_COMP))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.queueCompVal for Tx has to be in the range of 1 - %d",
+ MAX_PERFORMANCE_TX_QUEUE_COMP));
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ if (p_FmPortPerformanceCnt->queueCompVal)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("performanceCnt.queueCompVal is not relevant for H/O ports."));
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ tmpReg = 0;
+ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->queueCompVal - 1) << BMI_PERFORMANCE_PORT_COMP_SHIFT);
+ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->dmaCompVal- 1) << BMI_PERFORMANCE_DMA_COMP_SHIFT);
+ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->fifoCompVal/BMI_FIFO_UNITS - 1) << BMI_PERFORMANCE_FIFO_COMP_SHIFT);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && (p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->taskCompVal - 1) << BMI_PERFORMANCE_TASK_COMP_SHIFT);
+
+ WRITE_UINT32(*p_BmiPcpReg, tmpReg);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPortPerformanceCnt currParams, savedParams;
+ t_Error err;
+ bool underTest, failed = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ XX_Print("Analyzing Performance parameters for port (type %d, id%d)\n",
+ p_FmPort->portType, p_FmPort->portId);
+
+ currParams.taskCompVal = (uint8_t)p_FmPort->tasks.num;
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ currParams.queueCompVal = 0;
+ else
+ currParams.queueCompVal = 1;
+ currParams.dmaCompVal =(uint8_t) p_FmPort->openDmas.num;
+ currParams.fifoCompVal = p_FmPort->fifoBufs.num;
+
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+ ClearPerfCnts(p_FmPort);
+ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
+ XX_UDelay(1000000);
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
+ {
+ XX_Print ("Max num of defined port tasks (%d) utilized - Please enlarge\n",p_FmPort->tasks.num);
+ failed = TRUE;
+ }
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
+ {
+ XX_Print ("Max num of defined port openDmas (%d) utilized - Please enlarge\n",p_FmPort->openDmas.num);
+ failed = TRUE;
+ }
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
+ {
+ XX_Print("Max size of defined port fifo (%d) utilized - Please enlarge\n",p_FmPort->fifoBufs.num);
+ failed = TRUE;
+ }
+ if (failed)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+
+ memset(&savedParams, 0, sizeof(savedParams));
+ while (TRUE)
+ {
+ underTest = FALSE;
+ if ((currParams.taskCompVal != 1) && !savedParams.taskCompVal)
+ {
+ currParams.taskCompVal--;
+ underTest = TRUE;
+ }
+ if ((currParams.dmaCompVal != 1) && !savedParams.dmaCompVal)
+ {
+ currParams.dmaCompVal--;
+ underTest = TRUE;
+ }
+ if ((currParams.fifoCompVal != BMI_FIFO_UNITS) && !savedParams.fifoCompVal)
+ {
+ currParams.fifoCompVal -= BMI_FIFO_UNITS;
+ underTest = TRUE;
+ }
+ if (!underTest)
+ break;
+
+ ClearPerfCnts(p_FmPort);
+ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
+ XX_UDelay(1000000);
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+
+ if (!savedParams.taskCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
+ savedParams.taskCompVal = (uint8_t)(currParams.taskCompVal+2);
+ if (!savedParams.dmaCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
+ savedParams.dmaCompVal = (uint8_t)(currParams.dmaCompVal+2);
+ if (!savedParams.fifoCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
+ savedParams.fifoCompVal = currParams.fifoCompVal+(2*BMI_FIFO_UNITS);
+ }
+
+ XX_Print("best vals: tasks %d, dmas %d, fifos %d\n",
+ savedParams.taskCompVal, savedParams.dmaCompVal, savedParams.fifoCompVal);
+ return E_OK;
+}
+
+t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+ volatile uint32_t *p_BmiStcReg = NULL;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rstc;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tstc;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ostc;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ tmpReg = GET_UINT32(*p_BmiStcReg);
+
+ if (enable)
+ tmpReg |= BMI_COUNTERS_EN;
+ else
+ tmpReg &= ~BMI_COUNTERS_EN;
+
+ WRITE_UINT32(*p_BmiStcReg, tmpReg);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_ErrQReg, *p_ErrDiscard;
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsem;
+ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsem;
+ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (GET_UINT32(*p_ErrDiscard) & errs)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Selectd Errors that were configured to cause frame discard."));
+
+ WRITE_UINT32(*p_ErrQReg, errs);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(poolId<BM_MAX_NUM_OF_POOLS, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ for (i=0 ; i< FM_PORT_MAX_NUM_OF_EXT_POOLS ; i++)
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
+ if ((uint8_t)((tmpReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT) == poolId)
+ {
+ if (enable)
+ tmpReg |= BMI_EXT_BUF_POOL_EN_COUNTER;
+ else
+ tmpReg &= ~BMI_EXT_BUF_POOL_EN_COUNTER;
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], tmpReg);
+ break;
+ }
+ }
+ if (i == FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,("poolId %d is not included in this ports pools", poolId));
+
+ return E_OK;
+}
+
+uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters counter)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool bmiCounter = FALSE;
+ volatile uint32_t *p_Reg;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM):
+ /* check that counter is available for the port type */
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
+ return 0;
+ }
+ bmiCounter = FALSE;
+ case (e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ bmiCounter = FALSE;
+ break;
+ default: /* BMI counters (or error - will be checked in BMI routine )*/
+ bmiCounter = TRUE;
+ break;
+ }
+
+ if (bmiCounter)
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ if (BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ return 0;
+ }
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ if (BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ return 0;
+ }
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ if (BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ return 0;
+ }
+ break;
+ default:
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type"));
+ return 0;
+ }
+ return GET_UINT32(*p_Reg);
+ }
+ else /* QMI counter */
+ {
+ /* check that counters are enabled */
+ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc);
+ case (e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc);
+ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc);
+ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM):
+ return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc);
+ default:
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
+ return 0;
+ }
+ }
+}
+
+t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters counter, uint32_t value)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool bmiCounter = FALSE;
+ volatile uint32_t *p_Reg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM ):
+ /* check that counter is available for the port type */
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
+ case (e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ bmiCounter = FALSE;
+ break;
+ default: /* BMI counters (or error - will be checked in BMI routine )*/
+ bmiCounter = TRUE;
+ break;
+ }
+
+ if (bmiCounter)
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ if (BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ if (BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ if (BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type"));
+ }
+ WRITE_UINT32(*p_Reg, value);
+ }
+ else /* QMI counter */
+ {
+
+ /* check that counters are enabled */
+ if (!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc, value);
+ break;
+ case (e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc, value);
+ break;
+ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc, value);
+ break;
+ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM):
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc, value);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
+ }
+ }
+
+ return E_OK;
+}
+
+uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t extPoolReg;
+ uint8_t tmpPool;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
+ return 0;
+ }
+
+ for (i=0;i<FM_PORT_MAX_NUM_OF_EXT_POOLS;i++)
+ {
+ extPoolReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
+ if (extPoolReg & BMI_EXT_BUF_POOL_VALID)
+ {
+ tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT);
+ if (tmpPool == poolId)
+ {
+ if (extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER)
+ return GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i]);
+ else
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled"));
+ return 0;
+ }
+ }
+ }
+ }
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId));
+ return 0;
+}
+
+t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value)
+{
+ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort;
+ uint32_t extPoolReg;
+ uint8_t tmpPool;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
+
+
+ for (i=0;i<FM_PORT_MAX_NUM_OF_EXT_POOLS;i++)
+ {
+ extPoolReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
+ if (extPoolReg & BMI_EXT_BUF_POOL_VALID)
+ {
+ tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT);
+ if (tmpPool == poolId)
+ {
+ if (extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER)
+ {
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], value);
+ return E_OK;
+ }
+ else
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled"));
+ }
+ }
+ }
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId));
+}
+
+bool FM_PORT_IsStalled(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+ bool isStalled;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, FALSE);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, FALSE);
+
+ err = FmIsPortStalled(p_FmPort->h_Fm, p_FmPort->hardwarePortId, &isStalled);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return TRUE;
+ }
+ return isStalled;
+}
+
+t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ return FmResumeStalledPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
+}
+
+t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne);
+ if (l4Checksum)
+ tmpReg &= ~BMI_PORT_RFNE_FRWD_DCL4C;
+ else
+ tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C;
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, tmpReg);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+/* API Run-time PCD Control unit functions */
+/*****************************************************************************/
+
+#if (DPAA_VERSION >= 11)
+t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_VSPParams)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiStorageProfileId = NULL, *p_BmiVspe = NULL;
+ uint32_t tmpReg = 0, tmp = 0;
+ uint16_t hwStoragePrflId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->h_Fm, E_INVALID_HANDLE);
+ /*for numOfProfiles = 0 don't call this function*/
+ SANITY_CHECK_RETURN_ERROR(p_VSPParams->numOfProfiles, E_INVALID_VALUE);
+ /*dfltRelativeId should be in the range of numOfProfiles*/
+ SANITY_CHECK_RETURN_ERROR(IN_RANGE(0, p_VSPParams->dfltRelativeId, (p_VSPParams->numOfProfiles - 1)), E_INVALID_VALUE);
+ /*p_FmPort should be from Rx type or OP*/
+ SANITY_CHECK_RETURN_ERROR(((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE);
+ /*port should be disabled*/
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->enabled, E_INVALID_STATE);
+ /*if its called for Rx port relevant Tx Port should be passed (initialized) too and it should be disabled*/
+ SANITY_CHECK_RETURN_ERROR(((p_VSPParams->h_FmTxPort &&
+ !((t_FmPort *)(p_VSPParams->h_FmTxPort))->enabled) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE);
+ /*should be called before SetPCD - this port should be without PCD*/
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->pcdEngines, E_INVALID_STATE);
+
+ /*alloc window of VSPs for this port*/
+ err = FmVSPAllocForPort(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId,
+ p_VSPParams->numOfProfiles);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*get absolute VSP ID for dfltRelative*/
+ err = FmVSPGetAbsoluteProfileId(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId,
+ p_VSPParams->dfltRelativeId,
+ &hwStoragePrflId);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ /*fill relevant registers for p_FmPort and relative TxPort in the case p_FmPort from Rx type*/
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiStorageProfileId = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid);
+ p_BmiVspe = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfne);
+
+ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK;
+ tmpReg |= (uint32_t)hwStoragePrflId<<BMI_SP_ID_SHIFT;
+ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg);
+
+ tmpReg = GET_UINT32(*p_BmiVspe);
+ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN);
+
+ p_BmiStorageProfileId = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid;
+ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpp;
+ hwStoragePrflId = p_VSPParams->dfltRelativeId;
+ break;
+
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ tmpReg = NIA_ENG_BMI | NIA_BMI_AC_FETCH_ALL_FRAME;
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn,tmpReg);
+
+ p_BmiStorageProfileId = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofqid;
+ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opp;
+ tmp |= BMI_EBD_EN;
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ p_FmPort->vspe = TRUE;
+
+ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK;
+ tmpReg |= (uint32_t)hwStoragePrflId<<BMI_SP_ID_SHIFT;
+ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg);
+
+ tmpReg = GET_UINT32(*p_BmiVspe);
+ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN | tmp);
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
+ ASSERT_COND(p_FmPort->h_FmPcd);
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (numOfProfiles)
+ {
+ err = FmPcdPlcrAllocProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, numOfProfiles);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ /* set the port handle within the PCD policer, even if no profiles defined */
+ FmPcdPortRegister(p_FmPort->h_FmPcd, h_FmPort, p_FmPort->hardwarePortId);
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdPlcrFreeProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId);
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiHpnia = NULL;
+ uint32_t tmpReg;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ tmpReg = (uint32_t)((p_FmPort->pcdEngines & FM_PCD_CC)? NIA_KG_CC_EN:0);
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ /* if we want to change to direct scheme, we need to check that this scheme is valid */
+ if (p_FmPcdKgScheme->direct)
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_FmPcdKgScheme->h_DirectScheme);
+ /* check that this scheme is bound to this port */
+ if (!(p_FmPort->schemesPerPortVector & (uint32_t)(1 << (31 - (uint32_t)physicalSchemeId))))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with a scheme that is not bound to this port"));
+ }
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPort->h_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("called with invalid Scheme "));
+ }
+
+ if (!FmPcdKgIsSchemeValidSw(p_FmPcdKgScheme->h_DirectScheme))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with uninitialized Scheme "));
+ }
+
+ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg | NIA_KG_DIRECT | (uint32_t)physicalSchemeId);
+ }
+ else /* change to indirect scheme */
+ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg);
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiNia;
+ volatile uint32_t *p_BmiHpnia;
+ uint32_t tmpReg;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PLCR , E_INVALID_STATE);
+
+ /* check relevance of this routine - only when policer is used
+ directly after BMI or Parser */
+ if ((p_FmPort->pcdEngines & FM_PCD_KG) || (p_FmPort->pcdEngines & FM_PCD_CC))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("relevant only when PCD support mode is e_FM_PCD_SUPPORT_PLCR_ONLY or e_FM_PCD_SUPPORT_PRS_AND_PLCR"));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
+ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
+ tmpReg = 0;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Invalid profile"));
+ }
+
+ tmpReg = (uint32_t)(NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId);
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
+ {
+ /* update BMI HPNIA */
+ WRITE_UINT32(*p_BmiHpnia, tmpReg);
+ }
+ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
+ {
+ /* rfne may contain FDCS bits, so first we read them. */
+ tmpReg |= (GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK);
+ /* update BMI NIA */
+ WRITE_UINT32(*p_BmiNia, tmpReg);
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiCcBase=NULL;
+ volatile uint32_t *p_BmiNia=NULL;
+ uint32_t ccTreePhysOffset;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_VALUE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
+
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd,
+ h_CcTree,
+ NULL,
+ p_FmPort->h_IpReassemblyManip,
+ FALSE);
+ if (err != E_OK)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, NULL, h_CcTree, &ccTreePhysOffset, h_FmPort);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
+
+ p_FmPort->ccTreeId = h_CcTree;
+ RELEASE_LOCK(p_FmPort->lock);
+ }
+ else
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Coarse Classification not defined for this port."));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_AttachPCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+
+ err = AttachPCD(h_FmPort);
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_DetachPCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DetachPCD(h_FmPort);
+ if (err != E_OK)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ p_FmPort->pcdEngines &= ~FM_PCD_CC;
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParam)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ t_FmPortPcdParams modifiedPcdParams, *p_PcdParams;
+ t_FmPcdCcTreeParams *p_FmPcdCcTreeParams;
+ t_FmPortPcdCcParams fmPortPcdCcParams;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
+ ASSERT_COND(p_FmPort->h_FmPcd);
+
+ memcpy(&modifiedPcdParams, p_PcdParam, sizeof(t_FmPortPcdParams));
+ p_PcdParams = &modifiedPcdParams;
+ if (p_PcdParams->h_IpReassemblyManip)
+ {
+ if ((p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("pcdSupport must have KG for supporting IPR"));
+ }
+ p_FmPort->h_IpReassemblyManip = p_PcdParams->h_IpReassemblyManip;
+ if (!p_PcdParams->p_CcParams)
+ {
+ if (!((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR)))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport"));
+ }
+
+ /* No user-tree, need to build internal tree */
+ p_FmPcdCcTreeParams = (t_FmPcdCcTreeParams*)XX_Malloc(sizeof(t_FmPcdCcTreeParams));
+ if (!p_FmPcdCcTreeParams)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcTreeParams"));
+ memset(p_FmPcdCcTreeParams, 0, sizeof(t_FmPcdCcTreeParams));
+ p_FmPcdCcTreeParams->h_NetEnv = p_PcdParams->h_NetEnv;
+ p_FmPort->h_IpReassemblyTree = FM_PCD_CcRootBuild(p_FmPort->h_FmPcd, p_FmPcdCcTreeParams);
+
+ if (!p_FmPort->h_IpReassemblyTree)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ XX_Free(p_FmPcdCcTreeParams);
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM_PCD_CcBuildTree for IPR failed"));
+ }
+ if (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG)
+ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC;
+ else
+ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR;
+
+ memset(&fmPortPcdCcParams, 0, sizeof(t_FmPortPcdCcParams));
+ fmPortPcdCcParams.h_CcTree = p_FmPort->h_IpReassemblyTree;
+ p_PcdParams->p_CcParams = &fmPortPcdCcParams;
+ XX_Free(p_FmPcdCcTreeParams);
+ }
+
+ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd,
+ p_PcdParams->p_CcParams->h_CcTree,
+ p_PcdParams->h_NetEnv,
+ p_FmPort->h_IpReassemblyManip,
+ TRUE);
+ if (err != E_OK)
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd))
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ DBG(TRACE, ("Try LockAll - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = SetPcd(h_FmPort, p_PcdParams);
+ if (err)
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ (p_PcdParams->p_PrsParams->includeInPrsStatistics))
+ {
+ err = FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, TRUE);
+ if (err)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ p_FmPort->includeInPrsStatistics = TRUE;
+ }
+
+ FmPcdIncNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
+
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd))
+ {
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+#if (DPAA_VERSION >= 11)
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004
+ if ((p_FmPort->fmRevInfo.majorRev < 6) &&
+ (p_FmPort->pcdEngines & FM_PCD_KG))
+ {
+ int i;
+ for (i = 0; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ /* The following function must be locked */
+ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd,
+ p_PcdParams->p_KgParams->h_Schemes[i],
+ UPDATE_KG_NIA_CC_WA,
+ 0);
+ }
+#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */
+
+ /* Set post-bmi-fetch nia */
+ p_FmPort->savedBmiNia &= BMI_RFNE_FDCS_MASK;
+ p_FmPort->savedBmiNia |= (NIA_FM_CTL_AC_POST_BMI_FETCH | NIA_ENG_FM_CTL);
+
+ /* Set pre-bmi-fetch nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+#if (DPAA_VERSION >= 11)
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME | NIA_ENG_FM_CTL);
+#else
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER | NIA_ENG_FM_CTL);
+#endif /* (DPAA_VERSION >= 11) */
+ if ((err = FmPortGetSetCcParams(p_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+
+ /* Set pop-to-next-step nia */
+#if (DPAA_VERSION == 10)
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ {
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+ }
+ else
+ {
+#endif /* (DPAA_VERSION == 10) */
+ fmPortGetSetCcParams.getCcParams.type = GET_NIA_FPNE;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_CMNE;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
+#if (DPAA_VERSION == 10)
+ }
+#endif /* (DPAA_VERSION == 10) */
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* Set post-bmi-prepare-to-enq nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE;
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ | NIA_ENG_FM_CTL);
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+#if (DPAA_VERSION == 10)
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ {
+ /* Overwrite post-bmi-prepare-to-enq nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE;
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ_ORR | NIA_ENG_FM_CTL | NIA_ORDER_RESTOR);
+ fmPortGetSetCcParams.setCcParams.overwrite = TRUE;
+ }
+ else
+ {
+#endif /* (DPAA_VERSION == 10) */
+ /* Set the ORR bit (for order-restoration) */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FPNE;
+ fmPortGetSetCcParams.setCcParams.nia = fmPortGetSetCcParams.getCcParams.nia | NIA_ORDER_RESTOR;
+#if (DPAA_VERSION == 10)
+ }
+#endif /* (DPAA_VERSION == 10) */
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+ }
+ else
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+
+ err = AttachPCD(h_FmPort);
+ if (err)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_DeletePCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DetachPCD(h_FmPort);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ FmPcdDecNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
+
+ /* we do it anyway, instead of checking if included */
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ p_FmPort->includeInPrsStatistics)
+ {
+ FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, FALSE);
+ p_FmPort->includeInPrsStatistics = FALSE;
+ }
+
+ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ DBG(TRACE, ("Try LockAll - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DeletePcd(h_FmPort);
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ err = FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+ t_Error err = E_OK;
+ uint32_t tmpScmVec=0;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
+ schemeBind.useClsPlan = p_FmPort->useClsPlan;
+ for (i=0; i<schemeBind.numOfSchemes; i++)
+ {
+ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId(p_PortScheme->h_Schemes[i]);
+ /* build vector */
+ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err == E_OK)
+ p_FmPort->schemesPerPortVector |= tmpScmVec;
+
+#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004
+ if ((FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_FmPort->fmRevInfo.majorRev < 6))
+ {
+ for (i=0; i<p_PortScheme->numOfSchemes; i++)
+ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, p_PortScheme->h_Schemes[i], UPDATE_KG_NIA_CC_WA, 0);
+ }
+#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+ t_Error err = E_OK;
+ uint32_t tmpScmVec=0;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
+ for (i=0; i<schemeBind.numOfSchemes; i++)
+ {
+ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId(p_PortScheme->h_Schemes[i]);
+ /* build vector */
+ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err == E_OK)
+ p_FmPort->schemesPerPortVector &= ~tmpScmVec;
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+ volatile uint32_t *p_BmiNia = NULL;
+ uint32_t tmpReg;
+ uint8_t hdrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PRS , E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ tmpReg = 0;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) !=
+ GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ /* set the first header */
+ GET_PRS_HDR_NUM(hdrNum, p_FmPcdPrsStart->firstPrsHdr);
+ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
+ }
+ WRITE_UINT32(*p_BmiNia, (uint32_t)(NIA_ENG_PRS | (uint32_t)hdrNum | tmpReg));
+
+ /* set start parsing offset */
+ WRITE_UINT32(*p_BmiPrsStartOffset,
+ (uint32_t)(p_FmPcdPrsStart->parsingOffset +
+ p_FmPort->internalBufferOffset));
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PORT_DumpRegs(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ char arr[20];
+ uint8_t flag;
+ int i=0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortQmiRegs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortBmiRegs, E_INVALID_HANDLE);
+
+ memset(arr, 0, sizeof(arr));
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ strcpy(arr, "OFFLINE-PARSING");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ strcpy(arr, "HOST-COMMAND");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_RX):
+ strcpy(arr, "RX");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_RX_10G):
+ strcpy(arr, "RX-10G");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_TX):
+ strcpy(arr, "TX");
+ flag = 2;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ strcpy(arr, "TX-10G");
+ flag = 2;
+ break;
+ default:
+ return ERROR_CODE(E_INVALID_VALUE);
+ }
+
+ DUMP_TITLE(NULL,
+ ("FMan-Port (%s #%d) registers:",
+ arr, p_FmPort->portId));
+
+ err = FmDumpPortRegs(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ DUMP_TITLE(p_FmPort->p_FmPortBmiRegs, ("Bmi Port Regs"));
+
+ switch (flag)
+ {
+ case (0):
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ost);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oicp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofpne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opso);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occb);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oim);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofed);
+
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai), ("fmbm_oprai"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofqid );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oefqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsdm );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsem );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofene );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmts);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmt);
+
+ {
+#ifndef FM_NO_OP_OBSERVED_POOLS
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi, ("fmbm_oebmpi"));
+
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi[i], sizeof(uint32_t));
+ }
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocgm);
+ }
+#endif /* !FM_NO_OP_OBSERVED_POOLS */
+ }
+
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ostc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofrc );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdc );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofledc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofufdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_offc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofwdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofldec);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_otuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofuc);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg), ("fmbm_odcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ogpr);
+ break;
+ case (1):
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rcfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rst);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_reth);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfed);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_ricp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rebm);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfpne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpso);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpp);
+
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai), ("fmbm_rprai"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_refqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsdm);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsem);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfene);
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi, ("fmbm_ebmpi"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt, ("fmbm_acnt"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm, ("fmbm_rcgm"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_NUM_OF_CONGESTION_GRPS/32)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[i], sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rmpd);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rstc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfrc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfbc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rlfc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rffc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfcd);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfldec);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rodc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rccn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rtuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rrquc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpac);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg), ("fmbm_rdcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rgpr);
+ break;
+ case (2):
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tst);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfed);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ticp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfeqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfene);
+#if (DPAA_VERSION >= 11)
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfne);
+#endif /* (DPAA_VERSION >= 11) */
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmts);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmt);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tstc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfrc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfledc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfufdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tccn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttcquc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfuc);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg), ("fmbm_tdcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tgpr);
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid flag"));
+ }
+
+ DUMP_TITLE(p_FmPort->p_FmPortQmiRegs, ("Qmi Port Regs"));
+
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnc);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pns);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnts);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnen);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnetfc);
+
+ if (flag !=1)
+ {
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndn);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndtfc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndfdc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndcc);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort;
+ uint8_t priorityTmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS];
+ int i;
+ uint8_t mod;
+ uint32_t tmpReg = 0;
+#if (DPAA_VERSION >= 11)
+ int j;
+ t_Error err;
+#endif /* (DPAA_VERSION >= 11) */
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ /* un-necessary check of the indexes; probably will be needed in the future when there
+ will be more CGs available ....
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("CG id!"));
+ */
+
+#ifdef FM_NO_OP_OBSERVED_CGS
+ if ((p_FmPort->fmRevInfo.majorRev != 4) &&
+ (p_FmPort->fmRevInfo.majorRev < 6))
+ {
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
+ }
+ else
+#endif /* FM_NO_OP_OBSERVED_CGS */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
+
+ opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE);
+
+ /* to minimize memory access (groups may belong to the same regsiter, and may
+ be out of order), we first collect all information into a 256 booleans array,
+ representing each possible group. */
+
+ memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool));
+ memset(&priorityTmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(uint8_t));
+
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ {
+ tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE;
+
+#if (DPAA_VERSION >= 11)
+ for (j=0;j<FM_MAX_NUM_OF_PFC_PRIORITIES;j++)
+ if (p_CongestionGrps->pfcPrioritiesEn[i][j])
+ priorityTmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] |= (0x01 <<(FM_MAX_NUM_OF_PFC_PRIORITIES-j-1));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ for (i=0; i<FM_PORT_NUM_OF_CONGESTION_GRPS; i++)
+ {
+ mod = (uint8_t)(i%32);
+ /* each 32 congestion groups are represented by a register */
+ if (mod == 0) /* first in a 32 bunch of congestion groups, get the currest register state */
+ tmpReg = opPort ? GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm):
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)]);
+
+ /* set in the register, the bit representing the relevant congestion group. */
+
+ if (tmpArray[i])
+ {
+ tmpReg |= (0x00000001 << (uint32_t)mod);
+
+#if (DPAA_VERSION >= 11)
+ err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm,i,priorityTmpArray[i]);
+ if (err)
+ return err;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */
+ {
+ if (opPort)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)], tmpReg);
+ }
+ }
+
+ return E_OK;
+}
+
+t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort;
+ int i;
+ uint8_t mod;
+ uint32_t tmpReg = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ /* un-necessary check of the indexes; probably will be needed in the future when there
+ will be more CGs available ....
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("CG id!"));
+ */
+
+#ifdef FM_NO_OP_OBSERVED_CGS
+ if ((p_FmPort->fmRevInfo.majorRev != 4) &&
+ (p_FmPort->fmRevInfo.majorRev < 6))
+ {
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
+ }
+ else
+#endif /* FM_NO_OP_OBSERVED_CGS */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
+
+ opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE);
+
+ /* to minimize memory access (groups may belong to the same regsiter, and may
+ be out of order), we first collect all information into a 256 booleans array,
+ representing each possible group. */
+ memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool));
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE;
+
+ for (i=0; i<FM_PORT_NUM_OF_CONGESTION_GRPS; i++)
+ {
+ mod = (uint8_t)(i%32);
+ /* each 32 congestion groups are represented by a register */
+ if (mod == 0) /* first in a 32 bunch of congestion groups, get the currest register state */
+ tmpReg = opPort ? GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm):
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)]);
+
+ /* set in the register, the bit representing the relevant congestion group. */
+ if (tmpArray[i])
+ {
+ tmpReg &= ~(0x00000001 << (uint32_t)mod);
+
+#if (DPAA_VERSION >= 11)
+ {
+ t_Error err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm, i, 0);
+ if (err)
+ return err;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */
+ {
+ if (opPort)
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg);
+ else
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[FM_PORT_CG_REG_NUM(i)], tmpReg);
+ }
+ }
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+#endif /* (DPAA_VERSION >= 11) */
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h
new file mode 100644
index 0000000..7873595
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h
@@ -0,0 +1,945 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_port.h
+
+ @Description FM Port internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_PORT_H
+#define __FM_PORT_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_port_ext.h"
+
+#include "fm_common.h"
+#include "fm_sp_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_PORT
+
+
+#define MIN_EXT_BUF_SIZE 64
+#define DATA_ALIGNMENT 64
+#define MAX_LIODN_OFFSET 64
+
+/**************************************************************************//**
+ @Description Memory Map defines
+*//***************************************************************************/
+#define BMI_PORT_REGS_OFFSET 0
+#define QMI_PORT_REGS_OFFSET 0x400
+#define PRS_PORT_REGS_OFFSET 0x800
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_PORT_deqHighPriority_1G FALSE
+#define DEFAULT_PORT_deqHighPriority_10G TRUE
+#define DEFAULT_PORT_deqType e_FM_PORT_DEQ_TYPE1
+#define DEFAULT_PORT_deqPrefetchOption e_FM_PORT_DEQ_FULL_PREFETCH
+#define DEFAULT_PORT_deqPrefetchOption_HC e_FM_PORT_DEQ_NO_PREFETCH
+#define DEFAULT_PORT_deqByteCnt_10G 0x1400
+#define DEFAULT_PORT_deqByteCnt_1G 0x400
+#define DEFAULT_PORT_bufferPrefixContent_privDataSize DEFAULT_FM_SP_bufferPrefixContent_privDataSize
+#define DEFAULT_PORT_bufferPrefixContent_passPrsResult DEFAULT_FM_SP_bufferPrefixContent_passPrsResult
+#define DEFAULT_PORT_bufferPrefixContent_passTimeStamp DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp
+#define DEFAULT_PORT_bufferPrefixContent_allOtherPCDInfo DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo
+#define DEFAULT_PORT_bufferPrefixContent_dataAlign DEFAULT_FM_SP_bufferPrefixContent_dataAlign
+#define DEFAULT_PORT_cheksumLastBytesIgnore 0
+#define DEFAULT_PORT_cutBytesFromEnd 4
+#define DEFAULT_PORT_txFifoMinFillLevel 0
+#define DEFAULT_PORT_fifoDeqPipelineDepth_IM 2
+#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 1
+#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4
+#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2
+
+#define DEFAULT_PORT_txFifoLowComfLevel (5*KILOBYTE)
+#define DEFAULT_PORT_rxFifoPriElevationLevel BMI_MAX_FIFO_SIZE
+#define DEFAULT_PORT_rxFifoThreshold (BMI_MAX_FIFO_SIZE*3/4)
+#define DEFAULT_PORT_frmDiscardOverride FALSE
+
+#define DEFAULT_PORT_dmaSwapData DEFAULT_FM_SP_dmaSwapData
+#define DEFAULT_PORT_dmaIntContextCacheAttr DEFAULT_FM_SP_dmaIntContextCacheAttr
+#define DEFAULT_PORT_dmaHeaderCacheAttr DEFAULT_FM_SP_dmaHeaderCacheAttr
+#define DEFAULT_PORT_dmaScatterGatherCacheAttr DEFAULT_FM_SP_dmaScatterGatherCacheAttr
+#define DEFAULT_PORT_dmaWriteOptimize DEFAULT_FM_SP_dmaWriteOptimize
+
+#define DEFAULT_PORT_noScatherGather DEFAULT_FM_SP_noScatherGather
+#define DEFAULT_PORT_forwardIntContextReuse FALSE
+#define DEFAULT_PORT_BufMargins_startMargins 32
+#define DEFAULT_PORT_BufMargins_endMargins 0
+#define DEFAULT_PORT_syncReq TRUE
+#define DEFAULT_PORT_syncReqForHc FALSE
+#define DEFAULT_PORT_color e_FM_PORT_COLOR_GREEN
+#define DEFAULT_PORT_errorsToDiscard FM_PORT_FRM_ERR_CLS_DISCARD
+/* #define DEFAULT_PORT_dualRateLimitScaleDown e_FM_PORT_DUAL_RATE_LIMITER_NONE */
+/* #define DEFAULT_PORT_rateLimitBurstSizeHighGranularity FALSE */
+#define DEFAULT_PORT_exception IM_EV_BSY
+#define DEFAULT_PORT_maxFrameLength 9600
+
+#define DEFAULT_notSupported 0xff
+
+/* Host command port MUST NOT be changed to more than 1 !!! */
+#define DEFAULT_PORT_numOfTasks(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 16 : \
+ ((((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX) || \
+ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ? 3 : 1))
+
+#define DEFAULT_PORT_extraNumOfTasks(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 8 : \
+ ((((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX)) ? 2 : 0))
+
+#define DEFAULT_PORT_numOfOpenDmas(type, rev) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_TX_10G) || \
+ ((type) == e_FM_PORT_TYPE_RX_10G)) ? 8 : ((rev>=6) ? 2 : 1))
+
+#define DEFAULT_PORT_extraNumOfOpenDmas(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 8 : \
+ ((((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX)) ? 1 : 0))
+
+#define DEFAULT_PORT_numOfFifoBufs(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 48 : \
+ ((((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX)) ? 44 : 8))
+
+#define DEFAULT_PORT_extraNumOfFifoBufs 0
+
+#define DEFAULT_PORT_txBdRingLength 16
+#define DEFAULT_PORT_rxBdRingLength 128
+#define DEFAULT_PORT_ImfwExtStructsMemId 0
+#define DEFAULT_PORT_ImfwExtStructsMemAttr MEMORY_ATTR_CACHEABLE
+
+#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32)
+
+/**************************************************************************//**
+ @Collection PCD Engines
+*//***************************************************************************/
+typedef uint32_t fmPcdEngines_t; /**< options as defined below: */
+
+#define FM_PCD_NONE 0 /**< No PCD Engine indicated */
+#define FM_PCD_PRS 0x80000000 /**< Parser indicated */
+#define FM_PCD_KG 0x40000000 /**< Keygen indicated */
+#define FM_PCD_CC 0x20000000 /**< Coarse classification indicated */
+#define FM_PCD_PLCR 0x10000000 /**< Policer indicated */
+#define FM_PCD_MANIP 0x08000000 /**< Manipulation indicated */
+/* @} */
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS 8
+#define FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS 256
+#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32)
+
+#define FM_OH_PORT_ID 0
+
+/***********************************************************************/
+/* SW parser IP-fragmentation labels (offsets) */
+/***********************************************************************/
+#if (DPAA_VERSION == 10)
+#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x025
+#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x300
+#else
+#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x046
+#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x2E0
+#endif /* (DPAA_VERSION == 10) */
+#define IP_FRAG_SW_PATCH_IPv6_LABEL \
+ (IP_FRAG_SW_PATCH_IPv4_LABEL + IP_FRAG_SW_PATCH_IPv4_SIZE)
+
+#ifdef FM_CAPWAP_SUPPORT
+#define UDP_LITE_SW_PATCH_LABEL 0x2E0
+#endif /* FM_CAPWAP_SUPPORT */
+
+/**************************************************************************//**
+ @Description Memory Mapped Registers
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_rcfg; /**< Rx Configuration */
+ volatile uint32_t fmbm_rst; /**< Rx Status */
+ volatile uint32_t fmbm_rda; /**< Rx DMA attributes*/
+ volatile uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/
+ volatile uint32_t fmbm_rfed; /**< Rx Frame End Data*/
+ volatile uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/
+ volatile uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/
+ volatile uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/
+ volatile uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/
+ volatile uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/
+ volatile uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/
+ volatile uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/
+ volatile uint32_t fmbm_rpp; /**< Rx Policer Profile */
+ volatile uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */
+ volatile uint32_t fmbm_reth; /**< Rx Excessive Threshold */
+ volatile uint32_t reserved1[0x01];/**< (0x03C) */
+ volatile uint32_t fmbm_rprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+ /**< Rx Parse Results Array Initialization*/
+ volatile uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/
+ volatile uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/
+ volatile uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/
+ volatile uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/
+ volatile uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */
+ volatile uint32_t reserved2[0x02];/**< (0x074-0x078) */
+ volatile uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */
+ volatile uint32_t reserved3[0x20];/**< (0x080 0x0FF) */
+ volatile uint32_t fmbm_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS];
+ /**< Buffer Manager pool Information-*/
+ volatile uint32_t fmbm_acnt[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS];
+ /**< Allocate Counter-*/
+ volatile uint32_t reserved4[0x08];
+ /**< 0x130/0x140 - 0x15F reserved -*/
+ volatile uint32_t fmbm_rcgm[FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS/32];
+ /**< Congestion Group Map*/
+ volatile uint32_t fmbm_rmpd; /**< BM Pool Depletion */
+ volatile uint32_t reserved5[0x1F];/**< (0x184 0x1FF) */
+ volatile uint32_t fmbm_rstc; /**< Rx Statistics Counters*/
+ volatile uint32_t fmbm_rfrc; /**< Rx Frame Counter*/
+ volatile uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/
+ volatile uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/
+ volatile uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/
+ volatile uint32_t fmbm_rfcd; /**< Rx Frame Discard Counter*/
+ volatile uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/
+ volatile uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard Counter-*/
+ volatile uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter-*/
+ volatile uint32_t fmbm_rpec; /**< Rx RX Prepare to enqueue Counter-*/
+ volatile uint32_t reserved6[0x16];/**< (0x228 0x27F) */
+ volatile uint32_t fmbm_rpc; /**< Rx Performance Counters*/
+ volatile uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/
+ volatile uint32_t fmbm_rccn; /**< Rx Cycle Counter*/
+ volatile uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/
+ volatile uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization Counter*/
+ volatile uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/
+ volatile uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/
+ volatile uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/
+ volatile uint32_t reserved7[0x18];/**< (0x2A0-0x2FF) */
+ volatile uint32_t fmbm_rdcfg[0x3];/**< Rx Debug-*/
+ volatile uint32_t fmbm_rgpr; /**< Rx General Purpose Register. */
+ volatile uint32_t reserved8[0x3a];/**< (0x310-0x3FF) */
+} _PackedType t_FmPortRxBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_tcfg; /**< Tx Configuration */
+ volatile uint32_t fmbm_tst; /**< Tx Status */
+ volatile uint32_t fmbm_tda; /**< Tx DMA attributes */
+ volatile uint32_t fmbm_tfp; /**< Tx FIFO Parameters */
+ volatile uint32_t fmbm_tfed; /**< Tx Frame End Data */
+ volatile uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */
+ volatile uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */
+ volatile uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */
+ volatile uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */
+ volatile uint32_t fmbm_tfeqid; /**< Tx Frame Error Queue ID */
+ volatile uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */
+ volatile uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */
+ volatile uint32_t fmbm_trlmt; /**< Tx Rate Limiter */
+ volatile uint32_t fmbm_tccb; /**< Tx Coarse Classification Base */
+ volatile uint32_t reserved0[0x0e];/**< (0x038-0x070) */
+ volatile uint32_t fmbm_tfne; /**< Tx Frame Next Engine */
+ volatile uint32_t reserved1[0x02];/**< (0x074-0x7C) */
+ volatile uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */
+ volatile uint32_t reserved2[0x60];/**< (0x080-0x200) */
+ volatile uint32_t fmbm_tstc; /**< Tx Statistics Counters */
+ volatile uint32_t fmbm_tfrc; /**< Tx Frame Counter */
+ volatile uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */
+ volatile uint32_t fmbm_tfledc; /**< Tx Frame Length error discard counter */
+ volatile uint32_t fmbm_tfufdc; /**< Tx Frame unsupported format discard Counter */
+ volatile uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */
+ volatile uint32_t reserved3[0x1A];/**< (0x218-0x280) */
+ volatile uint32_t fmbm_tpc; /**< Tx Performance Counters*/
+ volatile uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/
+ volatile uint32_t fmbm_tccn; /**< Tx Cycle Counter*/
+ volatile uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/
+ volatile uint32_t fmbm_ttcquc; /**< Tx Transmit Confirm Queue Utilization Counter*/
+ volatile uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/
+ volatile uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/
+ volatile uint32_t reserved4[16]; /**< (0x29C-0x2FF) */
+ volatile uint32_t fmbm_tdcfg[0x3];/**< Tx Debug-*/
+ volatile uint32_t fmbm_tgpr; /**< O/H General Purpose Register */
+ volatile uint32_t reserved5[0x3a];/**< (0x310-0x3FF) */
+} _PackedType t_FmPortTxBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_ocfg; /**< O/H Configuration */
+ volatile uint32_t fmbm_ost; /**< O/H Status */
+ volatile uint32_t fmbm_oda; /**< O/H DMA attributes */
+ volatile uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */
+ volatile uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */
+ volatile uint32_t fmbm_ofne; /**< O/H Frame Next Engine */
+ volatile uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */
+ volatile uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */
+ volatile uint32_t fmbm_opso; /**< O/H Parse Start Offset */
+ volatile uint32_t fmbm_opp; /**< O/H Policer Profile */
+ volatile uint32_t fmbm_occb; /**< O/H Coarse Classification base */
+ volatile uint32_t fmbm_oim; /**< O/H Internal margins*/
+ volatile uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/
+ volatile uint32_t fmbm_ofed; /**< O/H Frame End Data*/
+ volatile uint32_t reserved0[2]; /**< (0x038 - 0x03F) */
+ volatile uint32_t fmbm_oprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+ /**< O/H Parse Results Array Initialization */
+ volatile uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */
+ volatile uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */
+ volatile uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */
+ volatile uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */
+ volatile uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */
+ volatile uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */
+ volatile uint32_t fmbm_orlmt; /**< O/H Rate Limiter */
+ volatile uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */
+ volatile uint32_t reserved1[0x20];/**< (0x080 - 0x0FF) */
+ volatile uint32_t fmbm_oebmpi[2]; /**< Buffer Manager Observed Pool Information */
+ volatile uint32_t reserved2[0x16];/**< (0x108 - 0x15F) */
+ volatile uint32_t fmbm_ocgm; /**< Observed Congestion Group Map */
+ volatile uint32_t reserved3[0x7]; /**< (0x164 - 0x17F) */
+ volatile uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */
+ volatile uint32_t reserved4[0x1F];/**< (0x184 - 0x1FF) */
+ volatile uint32_t fmbm_ostc; /**< O/H Statistics Counters */
+ volatile uint32_t fmbm_ofrc; /**< O/H Frame Counter */
+ volatile uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */
+ volatile uint32_t fmbm_ofledc; /**< O/H Frames Length Error Discard Counter */
+ volatile uint32_t fmbm_ofufdc; /**< O/H Frames Unsupported Format Discard Counter */
+ volatile uint32_t fmbm_offc; /**< O/H Filter Frames Counter */
+ volatile uint32_t fmbm_ofwdc; /**< - Rx Frames WRED Discard Counter */
+ volatile uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Counter */
+ volatile uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */
+ volatile uint32_t fmbm_oodc; /**< O/H Out of Buffers Discard Counter */
+ volatile uint32_t fmbm_opec; /**< O/H Prepare to enqueue Counter */
+ volatile uint32_t reserved5[0x15];/**< ( - 0x27F) */
+ volatile uint32_t fmbm_opc; /**< O/H Performance Counters */
+ volatile uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */
+ volatile uint32_t fmbm_occn; /**< O/H Cycle Counter */
+ volatile uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */
+ volatile uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */
+ volatile uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */
+ volatile uint32_t reserved6[26]; /**< (0x298-0x2FF) */
+ volatile uint32_t fmbm_odcfg[0x3];/**< O/H Debug (only 1 in P1023) */
+ volatile uint32_t fmbm_ogpr; /**< O/H General Purpose Register. */
+ volatile uint32_t reserved7[0x3a];/**< (0x310 0x3FF) */
+} _PackedType t_FmPortOhBmiRegs;
+
+typedef _Packed union
+{
+ t_FmPortRxBmiRegs rxPortBmiRegs;
+ t_FmPortTxBmiRegs txPortBmiRegs;
+ t_FmPortOhBmiRegs ohPortBmiRegs;
+} _PackedType u_FmPortBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t reserved1[2]; /**< 0xn024 - 0x02B */
+ volatile uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */
+ volatile uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */
+ volatile uint32_t fmqm_pndtfc; /**< PortID n Dequeue Total Frame Counter */
+ volatile uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID from Default Counter */
+ volatile uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */
+} _PackedType t_FmPortNonRxQmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmqm_pnc; /**< PortID n Configuration Register */
+ volatile uint32_t fmqm_pns; /**< PortID n Status Register */
+ volatile uint32_t fmqm_pnts; /**< PortID n Task Status Register */
+ volatile uint32_t reserved0[4]; /**< 0xn00C - 0xn01B */
+ volatile uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */
+ volatile uint32_t fmqm_pnetfc; /**< PortID n Enqueue Total Frame Counter */
+ t_FmPortNonRxQmiRegs nonRxQmiRegs; /**< Registers for Tx Hc & Op ports */
+} _PackedType t_FmPortQmiRegs;
+
+typedef _Packed struct
+{
+ _Packed struct
+ {
+ volatile uint32_t softSeqAttach; /**< Soft Sequence Attachment */
+ volatile uint32_t lcv; /**< Line-up Enable Confirmation Mask */
+ } _PackedType hdrs[FM_PCD_PRS_NUM_OF_HDRS];
+ volatile uint8_t reserved0[0x378];
+ volatile uint32_t pcac; /**< Parse Internal Memory Configuration Access Control Register */
+ volatile uint32_t pctpid; /**< Parse Internal Memory Configured TPID Register */
+} _PackedType t_FmPortPrsRegs;
+
+/**************************************************************************//*
+ @Description Basic buffer descriptor (BD) structure
+*//***************************************************************************/
+typedef _Packed struct
+{
+ volatile uint16_t status;
+ volatile uint16_t length;
+ volatile uint8_t reserved0[0x6];
+ volatile uint8_t reserved1[0x1];
+ volatile t_FmPhysAddr buff;
+} _PackedType t_FmImBd;
+
+typedef _Packed struct
+{
+ volatile uint16_t gen; /**< tbd */
+ volatile uint8_t reserved0[0x1];
+ volatile t_FmPhysAddr bdRingBase; /**< tbd */
+ volatile uint16_t bdRingSize; /**< tbd */
+ volatile uint16_t offsetIn; /**< tbd */
+ volatile uint16_t offsetOut; /**< tbd */
+ volatile uint8_t reserved1[0x12]; /**< 0x0e - 0x1f */
+} _PackedType t_FmPortImQd;
+
+typedef _Packed struct
+{
+ volatile uint32_t mode; /**< Mode register */
+ volatile uint32_t rxQdPtr; /**< tbd */
+ volatile uint32_t txQdPtr; /**< tbd */
+ volatile uint16_t mrblr; /**< tbd */
+ volatile uint16_t rxQdBsyCnt; /**< tbd */
+ volatile uint8_t reserved0[0x10]; /**< 0x10 - 0x1f */
+ t_FmPortImQd rxQd;
+ t_FmPortImQd txQd;
+ volatile uint8_t reserved1[0xa0]; /**< 0x60 - 0xff */
+} _PackedType t_FmPortImPram;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/**************************************************************************//**
+ @Description Registers bit fields
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description BMI defines
+*//***************************************************************************/
+#if (DPAA_VERSION >= 11)
+#define BMI_SP_ID_MASK 0xff000000
+#define BMI_SP_ID_SHIFT 24
+#define BMI_SP_EN 0x01000000
+#define BMI_EBD_EN 0x80000000
+#endif /* (DPAA_VERSION >= 11) */
+
+#define BMI_PORT_CFG_EN 0x80000000
+#define BMI_PORT_CFG_EN_MACSEC 0x00800000
+#define BMI_PORT_CFG_FDOVR 0x02000000
+#define BMI_PORT_CFG_IM 0x01000000
+#define BMI_PORT_STATUS_BSY 0x80000000
+#define BMI_COUNTERS_EN 0x80000000
+#define BMI_DMA_ATTR_WRITE_OPTIMIZE FM_SP_DMA_ATTR_WRITE_OPTIMIZE
+
+#define BMI_PORT_RFNE_FRWD_DCL4C 0x10000000
+#define BMI_PORT_RFNE_FRWD_RPD 0x40000000
+#define BMI_RFNE_FDCS_MASK 0xFF000000
+
+#define BMI_CMD_MR_LEAC 0x00200000
+#define BMI_CMD_MR_SLEAC 0x00100000
+#define BMI_CMD_MR_MA 0x00080000
+#define BMI_CMD_MR_DEAS 0x00040000
+#define BMI_CMD_TX_MR_DEF (0)
+#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \
+ BMI_CMD_MR_SLEAC | \
+ BMI_CMD_MR_MA | \
+ BMI_CMD_MR_DEAS)
+#define BMI_CMD_ATTR_ORDER 0x80000000
+#define BMI_CMD_ATTR_SYNC 0x02000000
+#define BMI_CMD_ATTR_MODE_MISS_ALLIGN_ADDR_EN 0x00080000
+#define BMI_CMD_ATTR_MACCMD_MASK 0x0000ff00
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE 0x00008000
+#define BMI_CMD_ATTR_MACCMD_SECURED 0x00001000
+#define BMI_CMD_ATTR_MACCMD_SC_MASK 0x00000f00
+
+#define BMI_EXT_BUF_POOL_EN_COUNTER FM_SP_EXT_BUF_POOL_EN_COUNTER
+#define BMI_EXT_BUF_POOL_VALID FM_SP_EXT_BUF_POOL_VALID
+
+#define BMI_EXT_BUF_POOL_BACKUP FM_SP_EXT_BUF_POOL_BACKUP
+
+#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000
+#define BMI_STATUS_RX_MASK_UNUSED (uint32_t)(~(FM_PORT_FRM_ERR_DMA | \
+ FM_PORT_FRM_ERR_PHYSICAL | \
+ FM_PORT_FRM_ERR_SIZE | \
+ FM_PORT_FRM_ERR_CLS_DISCARD | \
+ FM_PORT_FRM_ERR_EXTRACTION | \
+ FM_PORT_FRM_ERR_NO_SCHEME | \
+ FM_PORT_FRM_ERR_COLOR_RED | \
+ FM_PORT_FRM_ERR_COLOR_YELLOW | \
+ FM_PORT_FRM_ERR_ILL_PLCR | \
+ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \
+ FM_PORT_FRM_ERR_PRS_TIMEOUT | \
+ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \
+ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \
+ FM_PORT_FRM_ERR_PRS_HDR_ERR | \
+ FM_PORT_FRM_ERR_IPRE | \
+ FM_PORT_FRM_ERR_IPR_NCSP | \
+ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW))
+
+#define BMI_STATUS_OP_MASK_UNUSED (uint32_t)(BMI_STATUS_RX_MASK_UNUSED & \
+ ~(FM_PORT_FRM_ERR_LENGTH | \
+ FM_PORT_FRM_ERR_NON_FM | \
+ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT))
+
+#define BMI_RATE_LIMIT_EN 0x80000000
+#define BMI_RATE_LIMIT_BURST_SIZE_GRAN 0x80000000
+#define BMI_RATE_LIMIT_SCALE_BY_2 0x00000001
+#define BMI_RATE_LIMIT_SCALE_BY_4 0x00000002
+#define BMI_RATE_LIMIT_SCALE_BY_8 0x00000003
+
+#define BMI_RX_FIFO_THRESHOLD_BC 0x80000000
+
+#define BMI_PRS_RESULT_HIGH 0x00000000
+#define BMI_PRS_RESULT_LOW 0xFFFFFFFF
+
+
+#define RX_ERRS_TO_ENQ (FM_PORT_FRM_ERR_DMA | \
+ FM_PORT_FRM_ERR_PHYSICAL | \
+ FM_PORT_FRM_ERR_SIZE | \
+ FM_PORT_FRM_ERR_EXTRACTION | \
+ FM_PORT_FRM_ERR_NO_SCHEME | \
+ FM_PORT_FRM_ERR_ILL_PLCR | \
+ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \
+ FM_PORT_FRM_ERR_PRS_TIMEOUT | \
+ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \
+ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \
+ FM_PORT_FRM_ERR_PRS_HDR_ERR | \
+ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \
+ FM_PORT_FRM_ERR_IPRE)
+
+#define OP_ERRS_TO_ENQ (RX_ERRS_TO_ENQ | \
+ FM_PORT_FRM_ERR_LENGTH | \
+ FM_PORT_FRM_ERR_NON_FM | \
+ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT)
+
+
+#define BMI_RX_FIFO_PRI_ELEVATION_MASK 0x03FF0000
+#define BMI_RX_FIFO_THRESHOLD_MASK 0x000003FF
+#define BMI_TX_FIFO_MIN_FILL_MASK 0x03FF0000
+#define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000F000
+#define BMI_TX_LOW_COMF_MASK 0x000003FF
+
+/* shifts */
+#define BMI_PORT_CFG_MS_SEL_SHIFT 16
+#define BMI_DMA_ATTR_SWP_SHIFT FM_SP_DMA_ATTR_SWP_SHIFT
+#define BMI_DMA_ATTR_IC_CACHE_SHIFT FM_SP_DMA_ATTR_IC_CACHE_SHIFT
+#define BMI_DMA_ATTR_HDR_CACHE_SHIFT FM_SP_DMA_ATTR_HDR_CACHE_SHIFT
+#define BMI_DMA_ATTR_SG_CACHE_SHIFT FM_SP_DMA_ATTR_SG_CACHE_SHIFT
+
+#define BMI_IM_FOF_SHIFT 28
+#define BMI_PR_PORTID_SHIFT 24
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16
+#define BMI_RX_FIFO_THRESHOLD_SHIFT 0
+
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+
+#define BMI_IC_TO_EXT_SHIFT FM_SP_IC_TO_EXT_SHIFT
+#define BMI_IC_FROM_INT_SHIFT FM_SP_IC_FROM_INT_SHIFT
+#define BMI_IC_SIZE_SHIFT FM_SP_IC_SIZE_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT 28
+
+#define BMI_EXT_BUF_MARG_START_SHIFT FM_SP_EXT_BUF_MARG_START_SHIFT
+#define BMI_SG_DISABLE FM_SP_SG_DISABLE
+#define BMI_EXT_BUF_MARG_END_SHIFT FM_SP_EXT_BUF_MARG_END_SHIFT
+
+#define BMI_CMD_ATTR_COLOR_SHIFT 26
+#define BMI_CMD_ATTR_COM_MODE_SHIFT 16
+#define BMI_CMD_ATTR_MACCMD_SHIFT 8
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE_SHIFT 15
+#define BMI_CMD_ATTR_MACCMD_SECURED_SHIFT 12
+#define BMI_CMD_ATTR_MACCMD_SC_SHIFT 8
+
+#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT
+#define BMI_POOL_DEP_NUM_OF_POOLS_VECTOR_SHIFT 24
+
+#define BMI_EXT_BUF_POOL_ID_SHIFT FM_SP_EXT_BUF_POOL_ID_SHIFT
+#define BMI_TX_FIFO_MIN_FILL_SHIFT 16
+#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
+#define BMI_TX_LOW_COMF_SHIFT 0
+
+#define BMI_FRAME_END_CS_IGNORE_SHIFT 24
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24
+#define BMI_PERFORMANCE_PORT_COMP_SHIFT 16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12
+#define BMI_PERFORMANCE_FIFO_COMP_SHIFT 0
+
+#define BMI_MAX_BURST_SHIFT 16
+#define BMI_COUNT_RATE_UNIT_SHIFT 16
+
+/* sizes */
+#define FRAME_END_DATA_SIZE 16
+#define FRAME_OFFSET_UNITS 16
+#define MIN_TX_INT_OFFSET 16
+#define MAX_FRAME_OFFSET 64
+#define MAX_FIFO_PIPELINE_DEPTH 8
+#define MAX_PERFORMANCE_TASK_COMP 64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP 8
+#define MAX_PERFORMANCE_RX_QUEUE_COMP 64
+#define MAX_PERFORMANCE_DMA_COMP 16
+#define MAX_NUM_OF_TASKS 64
+#define MAX_NUM_OF_EXTRA_TASKS 8
+#define MAX_NUM_OF_DMAS 16
+#define MAX_NUM_OF_EXTRA_DMAS 8
+#define MAX_BURST_SIZE 1024
+#define MIN_NUM_OF_OP_DMAS 2
+
+/**************************************************************************//**
+ @Description QMI defines
+*//***************************************************************************/
+/* masks */
+#define QMI_PORT_CFG_EN 0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS 0x10000000
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000
+
+#define QMI_DEQ_CFG_PREFETCH_NO_TNUM 0x02000000
+#define QMI_DEQ_CFG_PREFETCH_WAITING_TNUM 0
+#define QMI_DEQ_CFG_PREFETCH_1_FRAME 0
+#define QMI_DEQ_CFG_PREFETCH_3_FRAMES 0x01000000
+
+#define QMI_DEQ_CFG_PRI 0x80000000
+#define QMI_DEQ_CFG_TYPE1 0x10000000
+#define QMI_DEQ_CFG_TYPE2 0x20000000
+#define QMI_DEQ_CFG_TYPE3 0x30000000
+
+#define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f
+#define QMI_DEQ_CFG_SUBPORTAL_SHIFT 20
+
+/**************************************************************************//**
+ @Description PARSER defines
+*//***************************************************************************/
+/* masks */
+#define PRS_HDR_ERROR_DIS 0x00000800
+#define PRS_HDR_SW_PRS_EN 0x00000400
+#define PRS_CP_OFFSET_MASK 0x0000000F
+#define PRS_TPID1_MASK 0xFFFF0000
+#define PRS_TPID2_MASK 0x0000FFFF
+#define PRS_TPID_DFLT 0x91009100
+
+#define PRS_HDR_MPLS_LBL_INTER_EN 0x00200000
+#define PRS_HDR_IPV6_ROUTE_HDR_EN 0x00008000
+#define PRS_HDR_PPPOE_MTU_CHECK_EN 0x80000000
+#define PRS_HDR_UDP_PAD_REMOVAL 0x80000000
+#define PRS_HDR_TCP_PAD_REMOVAL 0x80000000
+#define PRS_CAC_STOP 0x00000001
+#define PRS_CAC_ACTIVE 0x00000100
+
+/* shifts */
+#define PRS_PCTPID_SHIFT 16
+#define PRS_HDR_MPLS_NEXT_HDR_SHIFT 22
+#define PRS_HDR_ETH_BC_SHIFT 28
+#define PRS_HDR_ETH_MC_SHIFT 24
+#define PRS_HDR_VLAN_STACKED_SHIFT 16
+#define PRS_HDR_MPLS_STACKED_SHIFT 16
+#define PRS_HDR_IPV4_1_BC_SHIFT 28
+#define PRS_HDR_IPV4_1_MC_SHIFT 24
+#define PRS_HDR_IPV4_2_UC_SHIFT 20
+#define PRS_HDR_IPV4_2_MC_BC_SHIFT 16
+#define PRS_HDR_IPV6_1_MC_SHIFT 24
+#define PRS_HDR_IPV6_2_UC_SHIFT 20
+#define PRS_HDR_IPV6_2_MC_SHIFT 16
+
+#define PRS_HDR_ETH_BC_MASK 0x0fffffff
+#define PRS_HDR_ETH_MC_MASK 0xf0ffffff
+#define PRS_HDR_VLAN_STACKED_MASK 0xfff0ffff
+#define PRS_HDR_MPLS_STACKED_MASK 0xfff0ffff
+#define PRS_HDR_IPV4_1_BC_MASK 0x0fffffff
+#define PRS_HDR_IPV4_1_MC_MASK 0xf0ffffff
+#define PRS_HDR_IPV4_2_UC_MASK 0xff0fffff
+#define PRS_HDR_IPV4_2_MC_BC_MASK 0xfff0ffff
+#define PRS_HDR_IPV6_1_MC_MASK 0xf0ffffff
+#define PRS_HDR_IPV6_2_UC_MASK 0xff0fffff
+#define PRS_HDR_IPV6_2_MC_MASK 0xfff0ffff
+
+/* others */
+#define PRS_HDR_ENTRY_SIZE 8
+#define DEFAULT_CLS_PLAN_VECTOR 0xFFFFFFFF
+
+#define IPSEC_SW_PATCH_START 0x20
+#define SCTP_SW_PATCH_START 0x4D
+#define DCCP_SW_PATCH_START 0x41
+
+/**************************************************************************//**
+ @Description IM defines
+*//***************************************************************************/
+#define BD_R_E 0x80000000
+#define BD_L 0x08000000
+
+#define BD_RX_CRE 0x00080000
+#define BD_RX_FTL 0x00040000
+#define BD_RX_FTS 0x00020000
+#define BD_RX_OV 0x00010000
+
+#define BD_RX_ERRORS (BD_RX_CRE | BD_RX_FTL | BD_RX_FTS | BD_RX_OV)
+#define BD_ERROR_PASS_FRAME BD_RX_ERRORS
+
+#define FM_IM_SIZEOF_BD sizeof(t_FmImBd)
+
+#define BD_STATUS_MASK 0xffff0000
+#define BD_LENGTH_MASK 0x0000ffff
+
+#define BD_STATUS_AND_LENGTH_SET(bd, val) WRITE_UINT32(*(volatile uint32_t*)(bd), (val))
+
+#define BD_STATUS_AND_LENGTH(bd) GET_UINT32(*(volatile uint32_t*)(bd))
+
+#define BD_GET(id) &p_FmPort->im.p_BdRing[id]
+
+#define IM_ILEGAL_BD_ID 0xffff
+
+/* others */
+#define IM_PRAM_ALIGN 0x100
+
+/* masks */
+#define IM_MODE_GBL 0x20000000
+#define IM_MODE_BO_MASK 0x18000000
+#define IM_MODE_BO_SHIFT 3
+#define IM_MODE_GRC_STP 0x00800000
+
+#define IM_MODE_SET_BO(val) (uint32_t)((val << (31-IM_MODE_BO_SHIFT)) & IM_MODE_BO_MASK)
+
+#define IM_RXQD_BSYINTM 0x0008
+#define IM_RXQD_RXFINTM 0x0010
+#define IM_RXQD_FPMEVT_SEL_MASK 0x0003
+
+#define IM_EV_BSY 0x40000000
+#define IM_EV_RX 0x80000000
+
+
+/**************************************************************************//**
+ @Description Additional defines
+*//***************************************************************************/
+
+typedef struct {
+ t_Handle h_FmMuram;
+ t_FmPortImPram *p_FmPortImPram;
+ uint8_t fwExtStructsMemId;
+ uint32_t fwExtStructsMemAttr;
+ uint16_t bdRingSize;
+ t_FmImBd *p_BdRing;
+ t_Handle *p_BdShadow;
+ uint16_t currBdId;
+ uint16_t firstBdOfFrameId;
+
+ /* Rx port parameters */
+ uint8_t dataMemId; /**< Memory partition ID for data buffers */
+ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */
+ t_BufferPoolInfo rxPool;
+ uint16_t mrblr;
+ uint16_t rxFrameAccumLength;
+ t_FmPortImRxStoreCallback *f_RxStore;
+
+ /* Tx port parameters */
+ uint32_t txFirstBdStatus;
+ t_FmPortImTxConfCallback *f_TxConf;
+} t_FmMacIm;
+
+
+typedef struct {
+ uint32_t dfltFqid;
+ uint32_t confFqid;
+ uint32_t errFqid;
+ uintptr_t baseAddr;
+ uint8_t deqSubPortal;
+ bool deqHighPriority;
+ e_FmPortDeqType deqType;
+ e_FmPortDeqPrefetchOption deqPrefetchOption;
+ uint16_t deqByteCnt;
+ uint8_t cheksumLastBytesIgnore;
+ uint8_t cutBytesFromEnd;
+ t_FmBufPoolDepletion bufPoolDepletion;
+ uint8_t pipelineDepth;
+ uint16_t fifoLowComfLevel;
+ bool frmDiscardOverride;
+ bool enRateLimit;
+ t_FmPortRateLimit rateLimit;
+ e_FmPortDualRateLimiterScaleDown rateLimitDivider;
+ bool enBufPoolDepletion;
+ uint16_t liodnOffset;
+ uint16_t liodnBase;
+ t_FmExtPools extBufPools;
+ e_FmDmaSwapOption dmaSwapData;
+ e_FmDmaCacheOption dmaIntContextCacheAttr;
+ e_FmDmaCacheOption dmaHeaderCacheAttr;
+ e_FmDmaCacheOption dmaScatterGatherCacheAttr;
+ bool dmaReadOptimize;
+ bool dmaWriteOptimize;
+ uint32_t txFifoMinFillLevel;
+ uint32_t txFifoLowComfLevel;
+ uint32_t rxFifoPriElevationLevel;
+ uint32_t rxFifoThreshold;
+ t_FmSpBufMargins bufMargins;
+ t_FmSpIntContextDataCopy intContext;
+ bool syncReq;
+ e_FmPortColor color;
+ fmPortFrameErrSelect_t errorsToDiscard;
+ fmPortFrameErrSelect_t errorsToEnq;
+ bool forwardReuseIntContext;
+ t_FmBufferPrefixContent bufferPrefixContent;
+ t_FmBackupBmPools *p_BackupBmPools;
+ bool dontReleaseBuf;
+ bool setNumOfTasks;
+ bool setNumOfOpenDmas;
+ bool setSizeOfFifo;
+#if (DPAA_VERSION >= 11)
+ bool noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+ bool bcbWorkaround;
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+} t_FmPortDriverParam;
+
+
+typedef struct t_FmPortRxPoolsParams
+{
+ uint8_t numOfPools;
+ uint16_t secondLargestBufSize;
+ uint16_t largestBufSize;
+} t_FmPortRxPoolsParams;
+
+typedef struct {
+ t_Handle h_Fm;
+ t_Handle h_FmPcd;
+ t_Handle h_FmMuram;
+ t_FmRevisionInfo fmRevInfo;
+ uint8_t portId;
+ e_FmPortType portType;
+ int enabled;
+ char name[MODULE_NAME_SIZE];
+ uint8_t hardwarePortId;
+ uint16_t fmClkFreq;
+ t_FmPortQmiRegs *p_FmPortQmiRegs;
+ u_FmPortBmiRegs *p_FmPortBmiRegs;
+ t_FmPortPrsRegs *p_FmPortPrsRegs;
+ fmPcdEngines_t pcdEngines;
+ uint32_t savedBmiNia;
+ uint8_t netEnvId;
+ uint32_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint8_t privateInfo;
+ uint32_t schemesPerPortVector;
+ bool useClsPlan;
+ uint8_t clsPlanGrpId;
+ t_Handle ccTreeId;
+ t_Handle completeArg;
+ void (*f_Complete)(t_Handle arg);
+ t_FmSpBufferOffsets bufferOffsets;
+ /* Independent-Mode parameters support */
+ bool imEn;
+ t_FmMacIm im;
+ uint8_t fifoDeqPipelineDepth;
+ volatile bool lock;
+ t_Handle h_Spinlock;
+ t_FmPortExceptionCallback *f_Exception;
+ t_Handle h_App;
+ uint8_t internalBufferOffset;
+ uint8_t fmanCtrlEventId;
+ uint32_t exceptions;
+ bool polling;
+ t_FmExtPools extBufPools;
+ uint32_t requiredAction;
+ uint32_t savedQmiPnen;
+ uint32_t savedBmiFene;
+ uint32_t savedBmiFpne;
+ uint32_t savedBmiCmne;
+ uint32_t savedNonRxQmiRegsPndn;
+ int savedPrsStartOffset;
+ bool includeInPrsStatistics;
+ uint16_t maxFrameLength;
+ t_FmFmanCtrl orFmanCtrl;
+ t_FmPortRsrc openDmas;
+ t_FmPortRsrc tasks;
+ t_FmPortRsrc fifoBufs;
+ t_FmPortRxPoolsParams rxPoolsParams;
+ t_Handle h_IpReassemblyManip;
+ t_Handle h_IpReassemblyTree;
+ uint64_t fmMuramPhysBaseAddr;
+#if (DPAA_VERSION >= 11)
+ bool vspe;
+ e_FmPortGprFuncType gprFunc;
+ void *p_MuramPage;
+#endif /* (DPAA_VERSION >= 11) */
+
+ t_FmPortDriverParam *p_FmPortDriverParam;
+} t_FmPort;
+
+
+void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams);
+t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort);
+
+t_Error FmPortImInit(t_FmPort *p_FmPort);
+void FmPortImFree(t_FmPort *p_FmPort);
+
+t_Error FmPortImEnable (t_FmPort *p_FmPort);
+t_Error FmPortImDisable (t_FmPort *p_FmPort);
+t_Error FmPortImRx (t_FmPort *p_FmPort);
+
+void FmPortSetMacsecLcv(t_Handle h_FmPort);
+void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci);
+
+
+t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas);
+t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks);
+t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo);
+
+static __inline__ uint8_t * BdBufferGet (t_PhysToVirt *f_PhysToVirt, t_FmImBd *p_Bd)
+{
+ uint64_t physAddr = (uint64_t)((uint64_t)GET_UINT8(p_Bd->buff.high) << 32);
+ physAddr |= GET_UINT32(p_Bd->buff.low);
+
+ return (uint8_t *)f_PhysToVirt((physAddress_t)(physAddr));
+}
+
+static __inline__ void SET_ADDR(volatile t_FmPhysAddr *fmPhysAddr, uint64_t value)
+{
+ WRITE_UINT8(fmPhysAddr->high,(uint8_t)((value & 0x000000ff00000000LL) >> 32));
+ WRITE_UINT32(fmPhysAddr->low,(uint32_t)value);
+}
+
+static __inline__ void BdBufferSet(t_VirtToPhys *f_VirtToPhys, t_FmImBd *p_Bd, uint8_t *p_Buffer)
+{
+ uint64_t physAddr = (uint64_t)(f_VirtToPhys(p_Buffer));
+ SET_ADDR(&p_Bd->buff, physAddr);
+}
+
+static __inline__ uint16_t GetNextBdId(t_FmPort *p_FmPort, uint16_t id)
+{
+ if (id < p_FmPort->im.bdRingSize-1)
+ return (uint16_t)(id+1);
+ else
+ return 0;
+}
+
+
+#endif /* __FM_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c
new file mode 100644
index 0000000..bf358a5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_port_im.c
+
+ @Description FM Port Independent-Mode ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "string_ext.h"
+#include "error_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_port.h"
+
+
+#define TX_CONF_STATUS_UNSENT 0x1
+
+
+typedef enum e_TxConfType
+{
+ e_TX_CONF_TYPE_CHECK = 0 /**< check if all the buffers were touched by the muxator, no confirmation callback */
+ ,e_TX_CONF_TYPE_CALLBACK = 1 /**< confirm to user all the available sent buffers */
+ ,e_TX_CONF_TYPE_FLUSH = 3 /**< confirm all buffers plus the unsent one with an appropriate status */
+} e_TxConfType;
+
+
+static void ImException(t_Handle h_FmPort, uint32_t event)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ ASSERT_COND(((event & IM_EV_RX) && FmIsMaster(p_FmPort->h_Fm)) ||
+ !FmIsMaster(p_FmPort->h_Fm));
+
+ if (event & IM_EV_RX)
+ FmPortImRx(p_FmPort);
+ if ((event & IM_EV_BSY) && p_FmPort->f_Exception)
+ p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY);
+}
+
+
+static t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType)
+{
+ t_Error retVal = E_BUSY;
+ uint32_t bdStatus;
+ uint16_t savedStartBdId, confBdId;
+
+ ASSERT_COND(p_FmPort);
+
+ /*
+ if (confType==e_TX_CONF_TYPE_CHECK)
+ return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY);
+ */
+
+ confBdId = savedStartBdId = p_FmPort->im.currBdId;
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
+
+ /* If R bit is set, we don't enter, or we break.
+ we run till we get to R, or complete the loop */
+ while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK))
+ {
+ if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */
+ BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0);
+
+ /* case 1: R bit is 0 and Length is set -> confirm! */
+ if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK))
+ {
+ if (p_FmPort->im.f_TxConf)
+ {
+ if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E))
+ p_FmPort->im.f_TxConf(p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
+ TX_CONF_STATUS_UNSENT,
+ p_FmPort->im.p_BdShadow[confBdId]);
+ else
+ p_FmPort->im.f_TxConf(p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
+ 0,
+ p_FmPort->im.p_BdShadow[confBdId]);
+ }
+ }
+ /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */
+
+ confBdId = GetNextBdId(p_FmPort, confBdId);
+ if (confBdId == savedStartBdId)
+ retVal = E_OK;
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
+ }
+
+ return retVal;
+}
+
+t_Error FmPortImEnable(t_FmPort *p_FmPort)
+{
+ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP));
+ return E_OK;
+}
+
+t_Error FmPortImDisable(t_FmPort *p_FmPort)
+{
+ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP));
+ return E_OK;
+}
+
+t_Error FmPortImRx(t_FmPort *p_FmPort)
+{
+ t_Handle h_CurrUserPriv, h_NewUserPriv;
+ uint32_t bdStatus;
+ volatile uint8_t buffPos;
+ uint16_t length;
+ uint16_t errors/*, reportErrors*/;
+ uint8_t *p_CurData, *p_Data;
+ uint32_t flags;
+
+ ASSERT_COND(p_FmPort);
+
+ flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock);
+ if (p_FmPort->lock)
+ {
+ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
+ return E_OK;
+ }
+ p_FmPort->lock = TRUE;
+ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+
+ while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */
+ {
+ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL)
+ {
+ p_FmPort->lock = FALSE;
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
+ }
+
+ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
+ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
+
+ errors = 0;
+ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
+ h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId];
+ length = (uint16_t)((bdStatus & BD_L) ?
+ ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength):
+ (bdStatus & BD_LENGTH_MASK));
+ p_FmPort->im.rxFrameAccumLength += length;
+
+ /* determine whether buffer is first, last, first and last (single */
+ /* buffer frame) or middle (not first and not last) */
+ buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ?
+ ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) :
+ ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF));
+
+ if (bdStatus & BD_L)
+ {
+ p_FmPort->im.rxFrameAccumLength = 0;
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
+
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E);
+
+ errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16);
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv;
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4));
+ /* Pass the buffer if one of the conditions is true:
+ - There are no errors
+ - This is a part of a larger frame ( the application has already received some buffers )
+ - There is an error, but it was defined to be passed anyway. */
+ if ((buffPos != SINGLE_BUF) || !errors || (errors & (uint16_t)(BD_ERROR_PASS_FRAME>>16)))
+ {
+ if (p_FmPort->im.f_RxStore(p_FmPort->h_App,
+ p_CurData,
+ length,
+ errors,
+ buffPos,
+ h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE)
+ break;
+ }
+ else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
+ p_CurData,
+ h_CurrUserPriv))
+ {
+ p_FmPort->lock = FALSE;
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer"));
+ }
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ }
+ p_FmPort->lock = FALSE;
+ return E_OK;
+}
+
+void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams)
+{
+ ASSERT_COND(p_FmPort);
+
+ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.h_FmMuram = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram;
+ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.imRxTxParams.liodnOffset;
+ p_FmPort->im.dataMemId = p_FmPortParams->specificParams.imRxTxParams.dataMemId;
+ p_FmPort->im.dataMemAttributes = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes;
+
+ p_FmPort->im.fwExtStructsMemId = DEFAULT_PORT_ImfwExtStructsMemId;
+ p_FmPort->im.fwExtStructsMemAttr = DEFAULT_PORT_ImfwExtStructsMemAttr;
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ p_FmPort->im.rxPool.h_BufferPool = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool;
+ p_FmPort->im.rxPool.f_GetBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf;
+ p_FmPort->im.rxPool.f_PutBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf;
+ p_FmPort->im.rxPool.bufferSize = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize;
+ p_FmPort->im.rxPool.f_PhysToVirt = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt;
+ if (!p_FmPort->im.rxPool.f_PhysToVirt)
+ p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt;
+ p_FmPort->im.rxPool.f_VirtToPhys = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys;
+ if (!p_FmPort->im.rxPool.f_VirtToPhys)
+ p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys;
+ p_FmPort->im.f_RxStore = p_FmPortParams->specificParams.imRxTxParams.f_RxStore;
+
+ p_FmPort->im.mrblr = 0x8000;
+ while (p_FmPort->im.mrblr)
+ {
+ if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr)
+ break;
+ p_FmPort->im.mrblr >>= 1;
+ }
+ if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize)
+ DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr));
+ p_FmPort->im.bdRingSize = DEFAULT_PORT_rxBdRingLength;
+ p_FmPort->exceptions = DEFAULT_PORT_exception;
+ if (FmIsMaster(p_FmPort->h_Fm))
+ p_FmPort->polling = FALSE;
+ else
+ p_FmPort->polling = TRUE;
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ p_FmPort->im.f_TxConf = p_FmPortParams->specificParams.imRxTxParams.f_TxConf;
+
+ p_FmPort->im.bdRingSize = DEFAULT_PORT_txBdRingLength;
+ }
+}
+
+t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort)
+{
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ if (!POWER_OF_2(p_FmPort->im.mrblr))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!"));
+ if (p_FmPort->im.mrblr < 256)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!"));
+ if (p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+ }
+
+ return E_OK;
+}
+
+t_Error FmPortImInit(t_FmPort *p_FmPort)
+{
+ t_FmImBd *p_Bd=NULL;
+ t_Handle h_BufContext;
+ uint64_t tmpPhysBase;
+ uint16_t log2Num;
+ uint8_t *p_Data/*, *p_Tmp*/;
+ int i;
+ t_Error err;
+ uint16_t tmpReg16;
+ uint32_t tmpReg32;
+
+ ASSERT_COND(p_FmPort);
+
+ p_FmPort->im.p_FmPortImPram =
+ (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN);
+ if (!p_FmPort->im.p_FmPortImPram)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!"));
+ WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ p_FmPort->im.p_BdRing =
+ (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize),
+ p_FmPort->im.fwExtStructsMemId,
+ 4);
+ if (!p_FmPort->im.p_BdRing)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!"));
+ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ if (!p_FmPort->im.p_BdShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
+ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+
+ /* Initialize the Rx-BD ring */
+ for (i=0; i<p_FmPort->im.bdRingSize; i++)
+ {
+ p_Bd = BD_GET(i);
+ BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E);
+
+ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL)
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data);
+ p_FmPort->im.p_BdShadow[i] = h_BufContext;
+ }
+
+ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
+ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
+ else
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
+
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr + 0x20));
+
+ LOG2((uint64_t)p_FmPort->im.mrblr, log2Num);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num);
+
+ /* Initialize Rx QD */
+ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
+ SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ /* Update the IM PRAM address in the BMI */
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr));
+ if (!p_FmPort->polling || p_FmPort->exceptions)
+ {
+ /* Allocate, configure and register interrupts */
+ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
+ tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK);
+ tmpReg32 = 0;
+
+ if (p_FmPort->exceptions & IM_EV_BSY)
+ {
+ tmpReg16 |= IM_RXQD_BSYINTM;
+ tmpReg32 |= IM_EV_BSY;
+ }
+ if (!p_FmPort->polling)
+ {
+ tmpReg16 |= IM_RXQD_RXFINTM;
+ tmpReg32 |= IM_EV_RX;
+ }
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+
+ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort);
+
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ else
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4);
+ if (!p_FmPort->im.p_BdRing)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!"));
+ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ if (!p_FmPort->im.p_BdShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
+ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+
+ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
+ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
+ else
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
+
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr + 0x40));
+
+ /* Initialize Tx QD */
+ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
+ SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ /* Update the IM PRAM address in the BMI */
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr));
+ }
+
+
+ return E_OK;
+}
+
+void FmPortImFree(t_FmPort *p_FmPort)
+{
+ uint32_t bdStatus;
+ uint8_t *p_CurData;
+
+ ASSERT_COND(p_FmPort);
+ ASSERT_COND(p_FmPort->im.p_FmPortImPram);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ if (!p_FmPort->polling || p_FmPort->exceptions)
+ {
+ /* Deallocate and unregister interrupts */
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
+
+ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
+
+ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ }
+ /* Try first clean what has received */
+ FmPortImRx(p_FmPort);
+
+ /* Now, get rid of the the empty buffer! */
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+
+ while (bdStatus & BD_R_E) /* while there is data in the Rx BD */
+ {
+ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
+
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL);
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0);
+
+ p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
+ p_CurData,
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ }
+ }
+ else
+ TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH);
+
+ FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram);
+
+ if (p_FmPort->im.p_BdShadow)
+ XX_Free(p_FmPort->im.p_BdShadow);
+
+ if (p_FmPort->im.p_BdRing)
+ XX_FreeSmart(p_FmPort->im.p_BdRing);
+}
+
+
+t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.mrblr = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.bdRingSize = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.bdRingSize = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,
+ uint8_t memId,
+ uint32_t memAttributes)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.fwExtStructsMemId = memId;
+ p_FmPort->im.fwExtStructsMemAttr = memAttributes;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only"));
+
+ if (!FmIsMaster(p_FmPort->h_Fm))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;"
+ "in guest-partitions, IM is always in polling!"));
+
+ p_FmPort->polling = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+ uint16_t tmpReg16;
+ uint32_t tmpReg32;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (exception == e_FM_PORT_EXCEPTION_IM_BUSY)
+ {
+ if (enable)
+ {
+ p_FmPort->exceptions |= IM_EV_BSY;
+ if (p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ)
+ {
+ /* Allocate, configure and register interrupts */
+ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
+
+ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort);
+ tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM);
+ tmpReg32 = IM_EV_BSY;
+ }
+ else
+ {
+ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM);
+ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY;
+ }
+
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ else
+ {
+ p_FmPort->exceptions &= ~IM_EV_BSY;
+ if (!p_FmPort->exceptions && p_FmPort->polling)
+ {
+ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY;
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ }
+ }
+ else
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception."));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ImTx( t_Handle h_FmPort,
+ uint8_t *p_Data,
+ uint16_t length,
+ bool lastBuffer,
+ t_Handle h_BufContext)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint16_t nextBdId;
+ uint32_t bdStatus, nextBdStatus;
+ bool firstBuffer;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId));
+
+ if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E))
+ {
+ /* Confirm the current BD - BD is available */
+ if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf))
+ p_FmPort->im.f_TxConf (p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)),
+ 0,
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
+
+ bdStatus = length;
+
+ /* if this is the first BD of a frame */
+ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
+ {
+ firstBuffer = TRUE;
+ p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E);
+
+ if (!lastBuffer)
+ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
+ }
+ else
+ firstBuffer = FALSE;
+
+ BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext;
+
+ /* deal with last */
+ if (lastBuffer)
+ {
+ /* if single buffer frame */
+ if (firstBuffer)
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L);
+ else
+ {
+ /* Set the last BD of the frame */
+ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L));
+ /* Set the first BD of the frame */
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus);
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4));
+ }
+ else if (!firstBuffer) /* mid frame buffer */
+ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E);
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ }
+ else
+ {
+ /* Discard current frame. Return error. */
+ if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID)
+ {
+ /* Error: No free BD */
+ /* Response: Discard current frame. Return error. */
+ uint16_t cleanBdId = p_FmPort->im.firstBdOfFrameId;
+
+ ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId);
+
+ /* Since firstInFrame is not NULL, one buffer at least has already been
+ inserted into the BD ring. Using do-while covers the situation of a
+ frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented
+ prior to testing whether or not it's equal to TxBd). */
+ do
+ {
+ BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0);
+ /* Advance BD pointer */
+ cleanBdId = GetNextBdId(p_FmPort, cleanBdId);
+ } while (cleanBdId != p_FmPort->im.currBdId);
+
+ p_FmPort->im.currBdId = cleanBdId;
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+
+ return ERROR_CODE(E_FULL);
+ }
+
+ return E_OK;
+}
+
+void FM_PORT_ImTxConf(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK);
+}
+
+t_Error FM_PORT_ImRx(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ return FmPortImRx(p_FmPort);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile
new file mode 100644
index 0000000..b82bb6f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-RTC.o
+
+fsl-ncsw-RTC-objs := fm_rtc.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c
new file mode 100644
index 0000000..d65b1d4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c
@@ -0,0 +1,878 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_rtc.c
+
+ @Description FM RTC driver implementation.
+
+ @Cautions None
+*//***************************************************************************/
+
+#include "error_ext.h"
+#include "debug_ext.h"
+#include "string_ext.h"
+#include "part_ext.h"
+#include "xx_ext.h"
+#include "ncsw_ext.h"
+
+#include "fm_rtc.h"
+#include "fm_common.h"
+
+
+/*****************************************************************************/
+static void SetDefaultParam(t_FmRtc *p_Rtc)
+{
+ t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
+ int i;
+
+ p_Rtc->outputClockDivisor = DEFAULT_outputClockDivisor;
+ p_Rtc->p_RtcDriverParam->bypass = DEFAULT_bypass;
+ p_RtcDriverParam->srcClk = DEFAULT_srcClock;
+ p_RtcDriverParam->invertInputClkPhase = DEFAULT_invertInputClkPhase;
+ p_RtcDriverParam->invertOutputClkPhase = DEFAULT_invertOutputClkPhase;
+ p_RtcDriverParam->pulseRealign = DEFAULT_pulseRealign;
+ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
+ {
+ p_RtcDriverParam->alarmPolarity[i] = DEFAULT_alarmPolarity;
+ }
+ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)
+ {
+ p_RtcDriverParam->triggerPolarity[i] = DEFAULT_triggerPolarity;
+ }
+ p_Rtc->clockPeriodNanoSec = DEFAULT_clockPeriod; /* 1 usec */
+}
+
+/*****************************************************************************/
+static t_Error CheckInitParameters(t_FmRtc *p_Rtc)
+{
+ t_FmRtcDriverParam *p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
+ int i;
+
+ if ((p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_EXTERNAL) &&
+ (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) &&
+ (p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_OSCILATOR))
+ RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined"));
+
+ if (p_Rtc->outputClockDivisor == 0)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Divisor for output clock (should be positive)"));
+ }
+
+ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
+ {
+ if ((p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW) &&
+ (p_RtcDriverParam->alarmPolarity[i] != e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH))
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i));
+ }
+ }
+ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)
+ {
+ if ((p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_FALLING_EDGE) &&
+ (p_RtcDriverParam->triggerPolarity[i] != e_FM_RTC_TRIGGER_ON_RISING_EDGE))
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i));
+ }
+ }
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+static void RtcExceptions(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ t_FmRtcMemMap *p_MemMap;
+ register uint32_t events;
+
+ ASSERT_COND(p_Rtc);
+ p_MemMap = p_Rtc->p_MemMap;
+
+ /* Get valid events */
+ events = GET_UINT32(p_MemMap->tmr_tevent);
+ events &= GET_UINT32(p_MemMap->tmr_temask);
+
+ /* Clear event bits */
+ WRITE_UINT32(p_MemMap->tmr_tevent, events);
+
+ if (events & TMR_TEVENT_ALM1)
+ {
+ if (p_Rtc->alarmParams[0].clearOnExpiration)
+ {
+ WRITE_UINT32(p_MemMap->tmr_alarm[0].tmr_alarm_l, 0);
+ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM1);
+ }
+ ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback);
+ p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0);
+ }
+ if (events & TMR_TEVENT_ALM2)
+ {
+ if (p_Rtc->alarmParams[1].clearOnExpiration)
+ {
+ WRITE_UINT32(p_MemMap->tmr_alarm[1].tmr_alarm_l, 0);
+ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) & ~TMR_TEVENT_ALM2);
+ }
+ ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback);
+ p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1);
+ }
+ if (events & TMR_TEVENT_PP1)
+ {
+ ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback);
+ p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0);
+ }
+ if (events & TMR_TEVENT_PP2)
+ {
+ ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback);
+ p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1);
+ }
+ if (events & TMR_TEVENT_ETS1)
+ {
+ ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback);
+ p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0);
+ }
+ if (events & TMR_TEVENT_ETS2)
+ {
+ ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback);
+ p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1);
+ }
+}
+
+
+/*****************************************************************************/
+t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam)
+{
+ t_FmRtc *p_Rtc;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL);
+
+ /* Allocate memory for the FM RTC driver parameters */
+ p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc));
+ if (!p_Rtc)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure"));
+ return NULL;
+ }
+
+ memset(p_Rtc, 0, sizeof(t_FmRtc));
+
+ /* Allocate memory for the FM RTC driver parameters */
+ p_Rtc->p_RtcDriverParam = (t_FmRtcDriverParam *)XX_Malloc(sizeof(t_FmRtcDriverParam));
+ if (!p_Rtc->p_RtcDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters"));
+ XX_Free(p_Rtc);
+ return NULL;
+ }
+
+ memset(p_Rtc->p_RtcDriverParam, 0, sizeof(t_FmRtcDriverParam));
+
+ /* Store RTC configuration parameters */
+ p_Rtc->h_Fm = p_FmRtcParam->h_Fm;
+
+ /* Set default RTC configuration parameters */
+ SetDefaultParam(p_Rtc);
+
+ /* Store RTC parameters in the RTC control structure */
+ p_Rtc->p_MemMap = (t_FmRtcMemMap *)UINT_TO_PTR(p_FmRtcParam->baseAddress);
+ p_Rtc->h_App = p_FmRtcParam->h_App;
+
+ return p_Rtc;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Init(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ t_FmRtcDriverParam *p_RtcDriverParam;
+ t_FmRtcMemMap *p_MemMap;
+ uint32_t freqCompensation;
+ uint32_t tmrCtrl;
+ int i;
+ uint64_t tmpDouble;
+
+ p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
+ p_MemMap = p_Rtc->p_MemMap;
+
+ if (CheckInitParameters(p_Rtc)!=E_OK)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Init Parameters are not Valid"));
+
+ /* TODO check that no timestamping MACs are working in this stage. */
+ WRITE_UINT32(p_MemMap->tmr_ctrl, TMR_CTRL_TMSR);
+ XX_UDelay(10);
+ WRITE_UINT32(p_MemMap->tmr_ctrl, 0);
+
+ /* Set the source clock */
+ switch (p_RtcDriverParam->srcClk)
+ {
+ case e_FM_RTC_SOURCE_CLOCK_SYSTEM:
+ tmrCtrl = TMR_CTRL_CKSEL_MAC_CLK;
+ break;
+ case e_FM_RTC_SOURCE_CLOCK_OSCILATOR:
+ tmrCtrl = TMR_CTRL_CKSEL_OSC_CLK;
+ break;
+ default:
+ /* Use a clock from the External TMR reference clock.*/
+ tmrCtrl = TMR_CTRL_CKSEL_EXT_CLK;
+ break;
+ }
+
+ /* whatever period the user picked, the timestamp will advance in '1' every time
+ * the period passed. */
+ tmrCtrl |= ((1 << TMR_CTRL_TCLK_PERIOD_SHIFT) & TMR_CTRL_TCLK_PERIOD_MASK);
+
+ if (p_RtcDriverParam->invertInputClkPhase)
+ tmrCtrl |= TMR_CTRL_CIPH;
+ if (p_RtcDriverParam->invertOutputClkPhase)
+ tmrCtrl |= TMR_CTRL_COPH;
+
+ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
+ {
+ if (p_RtcDriverParam->alarmPolarity[i] == e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW)
+ tmrCtrl |= (TMR_CTRL_ALMP1 >> i);
+ }
+
+ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)
+ if (p_RtcDriverParam->triggerPolarity[i] == e_FM_RTC_TRIGGER_ON_FALLING_EDGE)
+ tmrCtrl |= (TMR_CTRL_ETEP1 << i);
+
+ if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass)
+ tmrCtrl |= TMR_CTRL_BYP;
+
+ WRITE_UINT32(p_MemMap->tmr_ctrl, tmrCtrl);
+
+ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
+ {
+ /* Clear TMR_ALARM registers */
+ WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_l, 0xFFFFFFFF);
+ WRITE_UINT32(p_MemMap->tmr_alarm[i].tmr_alarm_h, 0xFFFFFFFF);
+ }
+
+ /* Clear TMR_TEVENT */
+ WRITE_UINT32(p_MemMap->tmr_tevent, TMR_TEVENT_ALL);
+
+ /* Initialize TMR_TEMASK */
+ WRITE_UINT32(p_MemMap->tmr_temask, 0);
+
+
+ /* find source clock frequency in Mhz */
+ if (p_Rtc->p_RtcDriverParam->srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM)
+ p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->extSrcClkFreq;
+ else
+ p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetClockFreq(p_Rtc->h_Fm)/2);
+
+ /* if timer in Master mode Initialize TMR_CTRL */
+ /* We want the counter (TMR_CNT) to count in nano-seconds */
+ if (!p_RtcDriverParam->timerSlaveMode && p_Rtc->p_RtcDriverParam->bypass)
+ {
+ p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz);
+ }
+ else
+ {
+ /* Initialize TMR_ADD with the initial frequency compensation value:
+ freqCompensation = (2^32 / frequency ratio) */
+ /* frequency ratio = sorce clock/rtc clock =
+ * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */
+ freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000,
+ p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz);
+ WRITE_UINT32(p_MemMap->tmr_add, freqCompensation);
+ }
+ /* check the legality of the relation between source and destination clocks */
+ /* should be larger than 1.0001 */
+ tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz;
+ if ((tmpDouble) <= 10001)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Invalid relation between source and destination clocks. Should be larger than 1.0001"));
+
+
+ for (i=0; i < 2; i++)
+ /* Clear TMR_FIPER registers */
+ WRITE_UINT32(p_MemMap->tmr_fiper[i], 0xFFFFFFFF);
+
+ /* Initialize TMR_PRSC */
+ WRITE_UINT32(p_MemMap->tmr_prsc, p_Rtc->outputClockDivisor);
+
+ /* Clear TMR_OFF */
+ WRITE_UINT32(p_MemMap->tmr_off_l, 0);
+ WRITE_UINT32(p_MemMap->tmr_off_h, 0);
+
+ /* Register the FM RTC interrupt */
+ FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc);
+
+ /* Free parameters structures */
+ XX_Free(p_Rtc->p_RtcDriverParam);
+ p_Rtc->p_RtcDriverParam = NULL;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Free(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+
+ if (p_Rtc->p_RtcDriverParam)
+ {
+ XX_Free(p_Rtc->p_RtcDriverParam);
+ }
+ else
+ {
+ FM_RTC_Disable(h_FmRtc);
+ }
+
+ /* Unregister FM RTC interrupt */
+ FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL);
+ XX_Free(p_Rtc);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc,
+ e_FmSrcClk srcClk,
+ uint32_t freqInMhz)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->srcClk = srcClk;
+ if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM)
+ p_Rtc->p_RtcDriverParam->extSrcClkFreq = freqInMhz;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->clockPeriodNanoSec = period;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->bypass = enabled;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->invertInputClkPhase = inverted;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->invertOutputClkPhase = inverted;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->outputClockDivisor = divisor;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->pulseRealign = enable;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc,
+ uint8_t alarmId,
+ e_FmRtcAlarmPolarity alarmPolarity)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (alarmId >= FM_RTC_NUM_OF_ALARMS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
+ }
+
+ p_Rtc->p_RtcDriverParam->alarmPolarity[alarmId] = alarmPolarity;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ e_FmRtcTriggerPolarity triggerPolarity)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
+ }
+
+ p_Rtc->p_RtcDriverParam->triggerPolarity[triggerId] = triggerPolarity;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint32_t tmrCtrl;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl);
+
+ /* TODO check that no timestamping MACs are working in this stage. */
+ if (resetClock)
+ {
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TMSR));
+
+ XX_UDelay(10);
+ /* Clear TMR_OFF */
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, 0);
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, 0);
+ }
+
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl | TMR_CTRL_TE));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Disable(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint32_t tmrCtrl;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* TODO A check must be added here, that no timestamping MAC's
+ * are working in this stage. */
+ tmrCtrl = GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl);
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, (tmrCtrl & ~(TMR_CTRL_TE)));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* TMR_OFF_L must be written first */
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_l, (uint32_t)offset);
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_off_h, (uint32_t)(offset >> 32));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ t_FmRtcMemMap *p_MemMap;
+ uint32_t tmpReg;
+ uint64_t tmpAlarm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_MemMap = p_Rtc->p_MemMap;
+
+ if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
+ }
+
+ if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec));
+ if (p_FmRtcAlarmParams->alarmTime % (uint64_t)p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm time must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec));
+ tmpAlarm = p_FmRtcAlarmParams->alarmTime/(uint64_t)p_Rtc->clockPeriodNanoSec;
+
+ /* TMR_ALARM_L must be written first */
+ WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_l, (uint32_t)tmpAlarm);
+ WRITE_UINT32(p_MemMap->tmr_alarm[p_FmRtcAlarmParams->alarmId].tmr_alarm_h,
+ (uint32_t)(tmpAlarm >> 32));
+
+ if (p_FmRtcAlarmParams->f_AlarmCallback)
+ {
+ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback;
+ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration;
+
+ if (p_FmRtcAlarmParams->alarmId == 0)
+ tmpReg = TMR_TEVENT_ALM1;
+ else
+ tmpReg = TMR_TEVENT_ALM2;
+ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg);
+ }
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ t_FmRtcMemMap *p_MemMap;
+ uint32_t tmpReg;
+ uint64_t tmpFiper;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_MemMap = p_Rtc->p_MemMap;
+
+ if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
+ }
+ if (GET_UINT32(p_MemMap->tmr_ctrl) & TMR_CTRL_TE)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled."));
+ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec));
+ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod % (uint64_t)p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse must be a multiple of RTC period - %d nanoseconds", p_Rtc->clockPeriodNanoSec));
+ tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod/(uint64_t)p_Rtc->clockPeriodNanoSec;
+ if (tmpFiper & 0xffffffff00000000LL)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse/RTC Period must be smaller than 4294967296", p_Rtc->clockPeriodNanoSec));
+
+ WRITE_UINT32(p_MemMap->tmr_fiper[p_FmRtcPeriodicPulseParams->periodicPulseId], (uint32_t)tmpFiper);
+
+ if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback)
+ {
+ p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback =
+ p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback;
+
+ if (p_FmRtcPeriodicPulseParams->periodicPulseId == 0)
+ tmpReg = TMR_TEVENT_PP1;
+ else
+ tmpReg = TMR_TEVENT_PP2;
+ WRITE_UINT32(p_MemMap->tmr_temask, GET_UINT32(p_MemMap->tmr_temask) | tmpReg);
+ }
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
+ }
+
+ p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL;
+
+ if (periodicPulseId == 0)
+ tmpReg = TMR_TEVENT_PP1;
+ else
+ tmpReg = TMR_TEVENT_PP2;
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg);
+
+ if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & TMR_CTRL_FS)
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~TMR_CTRL_FS);
+
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_fiper[periodicPulseId], 0xFFFFFFFF);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
+ }
+
+ if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback)
+ {
+ p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback;
+ if (p_FmRtcExternalTriggerParams->externalTriggerId == 0)
+ tmpReg = TMR_TEVENT_ETS1;
+ else
+ tmpReg = TMR_TEVENT_ETS2;
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) | tmpReg);
+ }
+
+ if (p_FmRtcExternalTriggerParams->usePulseAsInput)
+ {
+ if (p_FmRtcExternalTriggerParams->externalTriggerId == 0)
+ tmpReg = TMR_CTRL_PP1L;
+ else
+ tmpReg = TMR_CTRL_PP2L;
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) | tmpReg);
+ }
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
+
+ p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL;
+
+ if (externalTriggerId == 0)
+ tmpReg = TMR_TEVENT_ETS1;
+ else
+ tmpReg = TMR_TEVENT_ETS2;
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_temask, GET_UINT32(p_Rtc->p_MemMap->tmr_temask) & ~tmpReg);
+
+ if (externalTriggerId == 0)
+ tmpReg = TMR_CTRL_PP1L;
+ else
+ tmpReg = TMR_CTRL_PP2L;
+
+ if (GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & tmpReg)
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_ctrl, GET_UINT32(p_Rtc->p_MemMap->tmr_ctrl) & ~tmpReg);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ uint64_t *p_TimeStamp)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint64_t timeStamp;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
+ }
+
+ timeStamp = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_l);
+ timeStamp |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_etts[triggerId].tmr_etts_h) << 32);
+
+ timeStamp = timeStamp*p_Rtc->clockPeriodNanoSec;
+ *p_TimeStamp = timeStamp;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint64_t time;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* TMR_CNT_L must be read first to get an accurate value */
+ time = (uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_l);
+ time |= ((uint64_t)GET_UINT32(p_Rtc->p_MemMap->tmr_cnt_h) << 32);
+
+ time = time*p_Rtc->clockPeriodNanoSec;
+
+ *p_Ts = time;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ ts = ts/p_Rtc->clockPeriodNanoSec;
+ /* TMR_CNT_L must be written first to get an accurate value */
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_l, (uint32_t)ts);
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_cnt_h, (uint32_t)(ts >> 32));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ *p_Compensation = GET_UINT32(p_Rtc->p_MemMap->tmr_add);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* set the new freqCompensation */
+ WRITE_UINT32(p_Rtc->p_MemMap->tmr_add, freqCompensation);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ t_FmRtcMemMap *p_MemMap = p_Rtc->p_MemMap;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_MemMap)
+ {
+
+ DUMP_TITLE(p_MemMap, ("RTC:"));
+ DUMP_VAR(p_MemMap, tmr_id);
+ DUMP_VAR(p_MemMap, tmr_id2);
+ DUMP_VAR(p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_MemMap, tmr_tevent);
+ DUMP_VAR(p_MemMap, tmr_temask);
+ DUMP_VAR(p_MemMap, tmr_cnt_h);
+ DUMP_VAR(p_MemMap, tmr_cnt_l);
+ DUMP_VAR(p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_MemMap, tmr_add);
+ DUMP_VAR(p_MemMap, tmr_acc);
+ DUMP_VAR(p_MemMap, tmr_prsc);
+ DUMP_VAR(p_MemMap, tmr_off_h);
+ DUMP_VAR(p_MemMap, tmr_off_l);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_h);
+ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_l);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_fiper[i]);
+ DUMP_VAR(p_MemMap, tmr_fiper[i]);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l);
+ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l);
+ }
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h
new file mode 100644
index 0000000..4c1a422
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_rtc.h
+
+ @Description Memory map and internal definitions for FM RTC IEEE1588 Timer driver.
+
+ @Cautions None
+*//***************************************************************************/
+
+#ifndef __FM_RTC_H__
+#define __FM_RTC_H__
+
+#include "std_ext.h"
+#include "fm_rtc_ext.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_RTC
+
+/* General definitions */
+
+#define NANOSEC_PER_ONE_HZ_TICK 1000000000
+#define MIN_RTC_CLK_FREQ_HZ 1000
+#define MHz 1000000
+
+#define ACCUMULATOR_OVERFLOW ((uint64_t)(1LL << 32))
+
+/* RTC default values */
+#define DEFAULT_srcClock e_FM_RTC_SOURCE_CLOCK_SYSTEM
+#define DEFAULT_bypass FALSE
+#define DEFAULT_invertInputClkPhase FALSE
+#define DEFAULT_invertOutputClkPhase FALSE
+#define DEFAULT_outputClockDivisor 0x00000002
+#define DEFAULT_alarmPolarity e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH
+#define DEFAULT_triggerPolarity e_FM_RTC_TRIGGER_ON_FALLING_EDGE
+#define DEFAULT_pulseRealign FALSE
+#define DEFAULT_clockPeriod 1000
+
+/* FM RTC Registers definitions */
+#define TMR_CTRL_ALMP1 0x80000000
+#define TMR_CTRL_ALMP2 0x40000000
+#define TMR_CTRL_FS 0x10000000
+#define TMR_CTRL_PP1L 0x08000000
+#define TMR_CTRL_PP2L 0x04000000
+#define TMR_CTRL_TCLK_PERIOD_MASK 0x03FF0000
+#define TMR_CTRL_FRD 0x00004000
+#define TMR_CTRL_SLV 0x00002000
+#define TMR_CTRL_ETEP1 0x00000100
+#define TMR_CTRL_COPH 0x00000080
+#define TMR_CTRL_CIPH 0x00000040
+#define TMR_CTRL_TMSR 0x00000020
+#define TMR_CTRL_DBG 0x00000010
+#define TMR_CTRL_BYP 0x00000008
+#define TMR_CTRL_TE 0x00000004
+#define TMR_CTRL_CKSEL_OSC_CLK 0x00000003
+#define TMR_CTRL_CKSEL_MAC_CLK 0x00000001
+#define TMR_CTRL_CKSEL_EXT_CLK 0x00000000
+#define TMR_CTRL_TCLK_PERIOD_SHIFT 16
+
+#define TMR_TEVENT_ETS2 0x02000000
+#define TMR_TEVENT_ETS1 0x01000000
+#define TMR_TEVENT_ALM2 0x00020000
+#define TMR_TEVENT_ALM1 0x00010000
+#define TMR_TEVENT_PP1 0x00000080
+#define TMR_TEVENT_PP2 0x00000040
+#define TMR_TEVENT_PP3 0x00000020
+#define TMR_TEVENT_ALL (TMR_TEVENT_ETS2 | TMR_TEVENT_ETS1 | \
+ TMR_TEVENT_ALM2 | TMR_TEVENT_ALM1 | \
+ TMR_TEVENT_PP1 | TMR_TEVENT_PP2 | TMR_TEVENT_PP3)
+
+#define TMR_PRSC_OCK_MASK 0x0000FFFF
+
+
+/**************************************************************************//**
+ @Description Memory Mapped Registers
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description FM RTC timer alarm
+*//***************************************************************************/
+typedef _Packed struct t_TmrAlaram
+{
+ volatile uint32_t tmr_alarm_h; /**< */
+ volatile uint32_t tmr_alarm_l; /**< */
+} _PackedType t_TmrAlaram;
+
+/**************************************************************************//**
+ @Description FM RTC timer Ex trigger
+*//***************************************************************************/
+typedef _Packed struct t_TmrExtTrigger
+{
+ volatile uint32_t tmr_etts_h; /**< */
+ volatile uint32_t tmr_etts_l; /**< */
+} _PackedType t_TmrExtTrigger;
+
+typedef _Packed struct
+{
+ volatile uint32_t tmr_id; /* Module ID and version register */
+ volatile uint32_t tmr_id2; /* Module ID and configuration register */
+ volatile uint32_t PTP_RESERVED1[30];
+ volatile uint32_t tmr_ctrl; /* timer control register */
+ volatile uint32_t tmr_tevent; /* timer event register */
+ volatile uint32_t tmr_temask; /* timer event mask register */
+ volatile uint32_t PTP_RESERVED2[3];
+ volatile uint32_t tmr_cnt_h; /* timer counter high register */
+ volatile uint32_t tmr_cnt_l; /* timer counter low register */
+ volatile uint32_t tmr_add; /* timer drift compensation addend register */
+ volatile uint32_t tmr_acc; /* timer accumulator register */
+ volatile uint32_t tmr_prsc; /* timer prescale */
+ volatile uint32_t PTP_RESERVED3;
+ volatile uint32_t tmr_off_h; /* timer offset high */
+ volatile uint32_t tmr_off_l; /* timer offset low */
+ volatile t_TmrAlaram tmr_alarm[FM_RTC_NUM_OF_ALARMS]; /* timer alarm */
+ volatile uint32_t PTP_RESERVED4[2];
+ volatile uint32_t tmr_fiper[FM_RTC_NUM_OF_PERIODIC_PULSES]; /* timer fixed period interval */
+ volatile uint32_t PTP_RESERVED5[2];
+ volatile t_TmrExtTrigger tmr_etts[FM_RTC_NUM_OF_EXT_TRIGGERS]; /*time stamp general purpose external */
+ volatile uint32_t PTP_RESERVED6[3];
+} _PackedType t_FmRtcMemMap;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/**************************************************************************//**
+ @Description RTC FM driver parameters structure.
+*//***************************************************************************/
+typedef struct t_FmRtcDriverParam
+{
+ t_Handle h_Fm; /**< */
+ e_FmSrcClk srcClk; /**< */
+ uint32_t extSrcClkFreq; /**< */
+ uint32_t rtcFreqHz; /**< */
+ bool timerSlaveMode; /*Slave/Master Mode*/
+ bool invertInputClkPhase;
+ bool invertOutputClkPhase;
+ uint32_t eventsMask;
+ bool bypass; /**< Indicates if frequency compensation is bypassed */
+ bool pulseRealign;
+ e_FmRtcAlarmPolarity alarmPolarity[FM_RTC_NUM_OF_ALARMS];
+ e_FmRtcTriggerPolarity triggerPolarity[FM_RTC_NUM_OF_EXT_TRIGGERS];
+} t_FmRtcDriverParam;
+
+typedef struct t_FmRtcAlarm
+{
+ t_FmRtcExceptionsCallback *f_AlarmCallback;
+ bool clearOnExpiration;
+} t_FmRtcAlarm;
+
+typedef struct t_FmRtcPeriodicPulse
+{
+ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback;
+} t_FmRtcPeriodicPulse;
+
+typedef struct t_FmRtcExternalTrigger
+{
+ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback;
+} t_FmRtcExternalTrigger;
+
+
+/**************************************************************************//**
+ @Description RTC FM driver control structure.
+*//***************************************************************************/
+typedef struct t_FmRtc
+{
+ t_Part *p_Part; /**< Pointer to the integration device */
+ t_Handle h_Fm;
+ t_Handle h_App; /**< Application handle */
+ t_FmRtcMemMap *p_MemMap; /**< Pointer to RTC memory map */
+ uint32_t clockPeriodNanoSec; /**< RTC clock period in nano-seconds (for FS mode) */
+ uint32_t srcClkFreqMhz;
+ uint16_t outputClockDivisor; /**< Output clock divisor (for FS mode) */
+ t_FmRtcAlarm alarmParams[FM_RTC_NUM_OF_ALARMS];
+ t_FmRtcPeriodicPulse periodicPulseParams[FM_RTC_NUM_OF_PERIODIC_PULSES];
+ t_FmRtcExternalTrigger externalTriggerParams[FM_RTC_NUM_OF_EXT_TRIGGERS];
+ t_FmRtcDriverParam *p_RtcDriverParam; /**< RTC Driver parameters (for Init phase) */
+} t_FmRtc;
+
+
+#endif /* __FM_RTC_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile
new file mode 100644
index 0000000..977583a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-sp.o
+
+fsl-ncsw-sp-objs := fm_sp.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c
new file mode 100644
index 0000000..a457078
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c
@@ -0,0 +1,857 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_sp.c
+
+ @Description FM PCD Storage profile ...
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+
+#include "fm_vsp_ext.h"
+#include "fm_sp.h"
+#include "fm_common.h"
+
+
+#if (DPAA_VERSION >= 11)
+
+static void fm_vsp_fill_entry(fm_pcd_storage_profile_regs *regs,
+ uint16_t index,
+ fm_storage_profile_params *fm_vsp_params)
+{
+ int i = 0, j = 0;
+ fm_pcd_storage_profile_regs *sp_regs;
+ uint32_t tmp_reg, vector;
+ t_FmExtPools *ext_buf_pools = fm_vsp_params->fm_ext_pools;
+ t_FmBufPoolDepletion *buf_pool_depletion= fm_vsp_params->buf_pool_depletion;
+ t_FmBackupBmPools *backup_pools = fm_vsp_params->backup_pools;
+ t_FmSpIntContextDataCopy *int_context_data_copy = fm_vsp_params->int_context;
+ t_FmSpBufMargins *external_buffer_margins = fm_vsp_params->buf_margins;
+ bool no_scather_gather = fm_vsp_params->no_scather_gather;
+ uint16_t liodn_offset = fm_vsp_params->liodn_offset;
+
+ ASSERT_COND(regs);
+ ASSERT_COND(ext_buf_pools);
+ ASSERT_COND(int_context_data_copy);
+ ASSERT_COND(external_buffer_margins);
+ ASSERT_COND(IN_RANGE(0, index, FM_VSP_MAX_NUM_OF_ENTRIES));
+
+ sp_regs = &regs[index];
+
+ /* fill external buffers manager pool information register*/
+ for (i=0;i<ext_buf_pools->numOfPoolsUsed;i++)
+ {
+ tmp_reg = FM_SP_EXT_BUF_POOL_VALID | FM_SP_EXT_BUF_POOL_EN_COUNTER;
+ tmp_reg |= ((uint32_t)ext_buf_pools->extBufPool[i].id << FM_SP_EXT_BUF_POOL_ID_SHIFT);
+ tmp_reg |= ext_buf_pools->extBufPool[i].size;
+ /* functionality available only for some deriviatives (limited by config) */
+ if (backup_pools)
+ for (j=0;j<backup_pools->numOfBackupPools;j++)
+ if (ext_buf_pools->extBufPool[i].id == backup_pools->poolIds[j])
+ {
+ tmp_reg |= FM_SP_EXT_BUF_POOL_BACKUP;
+ break;
+ }
+
+ WRITE_UINT32(sp_regs->fm_sp_ebmpi[i], tmp_reg);
+ }
+
+ /* clear unused pools */
+ for (i=ext_buf_pools->numOfPoolsUsed;i<FM_PORT_MAX_NUM_OF_EXT_POOLS;i++)
+ WRITE_UINT32(sp_regs->fm_sp_ebmpi[i], 0);
+
+ /* fill pool depletion register*/
+ tmp_reg = 0;
+
+ if (buf_pool_depletion && buf_pool_depletion->poolsGrpModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ vector = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ if (buf_pool_depletion->poolsToConsider[i])
+ for (j=0;j<ext_buf_pools->numOfPoolsUsed;j++)
+ if (i == ext_buf_pools->extBufPool[j].id)
+ {
+ vector |= 0x80000000 >> j;
+ break;
+ }
+
+ /* configure num of pools and vector for number of pools mode */
+ tmp_reg |= (((uint32_t)buf_pool_depletion->numOfPools - 1) << FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT);
+ tmp_reg |= vector;
+ }
+
+ if (buf_pool_depletion && buf_pool_depletion->singlePoolModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ vector = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ if (buf_pool_depletion->poolsToConsiderForSingleMode[i])
+ for (j=0;j<ext_buf_pools->numOfPoolsUsed;j++)
+ if (i == ext_buf_pools->extBufPool[j].id)
+ {
+ vector |= 0x00000080 >> j;
+ break;
+ }
+
+ /* configure num of pools and vector for number of pools mode */
+ tmp_reg |= vector;
+ }
+
+ /* fill QbbPEV */
+ if (buf_pool_depletion)
+ {
+ vector = 0;
+ for (i=0; i<FM_MAX_NUM_OF_PFC_PRIORITIES; i++)
+ if (buf_pool_depletion->pfcPrioritiesEn[i] == TRUE)
+ vector|= 0x00008000 >> i;
+ tmp_reg |= vector;
+ }
+ WRITE_UINT32(sp_regs->fm_sp_mpd, tmp_reg);
+
+ /* fill dma attributes register */
+ tmp_reg = 0;
+ tmp_reg |= (uint32_t)fm_vsp_params->dma_swap_data << FM_SP_DMA_ATTR_SWP_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->int_context_cache_attr << FM_SP_DMA_ATTR_IC_CACHE_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->header_cache_attr << FM_SP_DMA_ATTR_HDR_CACHE_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->scatter_gather_cache_attr << FM_SP_DMA_ATTR_SG_CACHE_SHIFT;
+ if (fm_vsp_params->dma_write_optimize)
+ tmp_reg |= FM_SP_DMA_ATTR_WRITE_OPTIMIZE;
+ WRITE_UINT32(sp_regs->fm_sp_da, tmp_reg);
+
+ /* IC parameters - fill internal context parameters register */
+ tmp_reg = 0;
+ tmp_reg |= (((uint32_t)int_context_data_copy->extBufOffset/OFFSET_UNITS) << FM_SP_IC_TO_EXT_SHIFT);
+ tmp_reg |= (((uint32_t)int_context_data_copy->intContextOffset/OFFSET_UNITS) << FM_SP_IC_FROM_INT_SHIFT);
+ tmp_reg |= (((uint32_t)int_context_data_copy->size/OFFSET_UNITS) << FM_SP_IC_SIZE_SHIFT);
+ WRITE_UINT32(sp_regs->fm_sp_icp, tmp_reg);
+
+ /* buffer margins - fill external buffer margins register */
+ tmp_reg = 0;
+ tmp_reg |= (((uint32_t)external_buffer_margins->startMargins) << FM_SP_EXT_BUF_MARG_START_SHIFT);
+ tmp_reg |= (((uint32_t)external_buffer_margins->endMargins) << FM_SP_EXT_BUF_MARG_END_SHIFT);
+ if (no_scather_gather)
+ tmp_reg |= FM_SP_SG_DISABLE;
+ WRITE_UINT32(sp_regs->fm_sp_ebm, tmp_reg);
+
+ /* buffer margins - fill spliodn register */
+ WRITE_UINT32(sp_regs->fm_sp_spliodn, liodn_offset);
+}
+
+static t_Error CheckParamsGeneratedInternally(t_FmVspEntry *p_FmVspEntry)
+{
+ t_Error err = E_OK;
+
+ if ((err = FmSpCheckIntContextParams(&p_FmVspEntry->intContext))!= E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if ((err = FmSpCheckBufMargins(&p_FmVspEntry->bufMargins)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return err;
+
+}
+static t_Error CheckParams(t_FmVspEntry *p_FmVspEntry)
+{
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->h_Fm, E_INVALID_HANDLE);
+
+ if ((err = FmSpCheckBufPoolsParams(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools,
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools,
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)) != E_OK)
+
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset & ~FM_LIODN_OFFSET_MASK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+
+ err = FmVSPCheckRelativeProfile(p_FmVspEntry->h_Fm,
+ p_FmVspEntry->portType,
+ p_FmVspEntry->portId,
+ p_FmVspEntry->relativeProfileId);
+
+ return err;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools,
+ uint8_t *orderedArray,
+ uint16_t *sizesArray)
+{
+ uint16_t bufSize = 0;
+ int i=0, j=0, k=0;
+
+ /* First we copy the external buffers pools information to an ordered local array */
+ for (i=0;i<p_FmExtPools->numOfPoolsUsed;i++)
+ {
+ /* get pool size */
+ bufSize = p_FmExtPools->extBufPool[i].size;
+
+ /* keep sizes in an array according to poolId for direct access */
+ sizesArray[p_FmExtPools->extBufPool[i].id] = bufSize;
+
+ /* save poolId in an ordered array according to size */
+ for (j=0;j<=i;j++)
+ {
+ /* this is the next free place in the array */
+ if (j==i)
+ orderedArray[i] = p_FmExtPools->extBufPool[i].id;
+ else
+ {
+ /* find the right place for this poolId */
+ if (bufSize < sizesArray[orderedArray[j]])
+ {
+ /* move the poolIds one place ahead to make room for this poolId */
+ for (k=i;k>j;k--)
+ orderedArray[k] = orderedArray[k-1];
+
+ /* now k==j, this is the place for the new size */
+ orderedArray[k] = p_FmExtPools->extBufPool[i].id;
+ break;
+ }
+ }
+ }
+ }
+}
+
+t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools,
+ t_FmBackupBmPools *p_FmBackupBmPools,
+ t_FmBufPoolDepletion *p_FmBufPoolDepletion)
+{
+
+ int i = 0, j = 0;
+ bool found;
+ uint8_t count = 0;
+
+ if (p_FmExtPools)
+ {
+ if (p_FmExtPools->numOfPoolsUsed > FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfPoolsUsed can't be larger than %d", FM_PORT_MAX_NUM_OF_EXT_POOLS));
+
+ for (i=0;i<p_FmExtPools->numOfPoolsUsed;i++)
+ {
+ if (p_FmExtPools->extBufPool[i].id >= BM_MAX_NUM_OF_POOLS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].id can't be larger than %d", i, BM_MAX_NUM_OF_POOLS));
+ if (!p_FmExtPools->extBufPool[i].size)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].size is 0", i));
+ }
+ }
+ if (!p_FmExtPools && (p_FmBackupBmPools || p_FmBufPoolDepletion))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("backupBmPools ot bufPoolDepletion can not be defined without external pools"));
+
+ /* backup BM pools indication is valid only for some chip derivatives
+ (limited by the config routine) */
+ if (p_FmBackupBmPools)
+ {
+ if (p_FmBackupBmPools->numOfBackupPools >= p_FmExtPools->numOfPoolsUsed)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_BackupBmPools must be smaller than extBufPools.numOfPoolsUsed"));
+ found = FALSE;
+ for (i = 0;i<p_FmBackupBmPools->numOfBackupPools;i++)
+ {
+
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (p_FmBackupBmPools->poolIds[i] == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("All p_BackupBmPools.poolIds must be included in extBufPools.extBufPool[n].id"));
+ else
+ found = FALSE;
+ }
+ }
+
+ /* up to extBufPools.numOfPoolsUsed pools may be defined */
+ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->poolsGrpModeEnable)
+ {
+ if ((p_FmBufPoolDepletion->numOfPools > p_FmExtPools->numOfPoolsUsed))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can't be larger than %d and can't be larger than numOfPoolsUsed", FM_PORT_MAX_NUM_OF_EXT_POOLS));
+
+ if (!p_FmBufPoolDepletion->numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when poolsGrpModeEnable=TRUE"));
+
+ found = FALSE;
+ count = 0;
+ /* for each pool that is in poolsToConsider, check if it is defined
+ in extBufPool */
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_FmBufPoolDepletion->poolsToConsider[i])
+ {
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (i == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ count++;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
+ else
+ found = FALSE;
+ }
+ }
+ /* check that the number of pools that we have checked is equal to the number announced by the user */
+ if (count != p_FmBufPoolDepletion->numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools is larger than the number of pools defined."));
+ }
+
+ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->singlePoolModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ found = FALSE;
+ count = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_FmBufPoolDepletion->poolsToConsiderForSingleMode[i])
+ {
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (i == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ count++;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
+ else
+ found = FALSE;
+ }
+ }
+ if (!count)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("No pools defined for single buffer mode pool depletion."));
+ }
+
+ return E_OK;
+}
+
+t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy)
+{
+ /* Check that divisible by 16 and not larger than 240 */
+ if (p_FmSpIntContextDataCopy->intContextOffset >MAX_INT_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset can't be larger than %d", MAX_INT_OFFSET));
+ if (p_FmSpIntContextDataCopy->intContextOffset % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset has to be divisible by %d", OFFSET_UNITS));
+
+ /* check that ic size+ic internal offset, does not exceed ic block size */
+ if (p_FmSpIntContextDataCopy->size + p_FmSpIntContextDataCopy->intContextOffset > MAX_IC_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size + intContext.intContextOffset has to be smaller than %d", MAX_IC_SIZE));
+ /* Check that divisible by 16 and not larger than 256 */
+ if (p_FmSpIntContextDataCopy->size % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size has to be divisible by %d", OFFSET_UNITS));
+
+ /* Check that divisible by 16 and not larger than 4K */
+ if (p_FmSpIntContextDataCopy->extBufOffset > MAX_EXT_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset can't be larger than %d", MAX_EXT_OFFSET));
+ if (p_FmSpIntContextDataCopy->extBufOffset % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset has to be divisible by %d", OFFSET_UNITS));
+
+ return E_OK;
+}
+
+t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins)
+{
+ /* Check the margin definition */
+ if (p_FmSpBufMargins->startMargins > MAX_EXT_BUFFER_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
+ if (p_FmSpBufMargins->endMargins > MAX_EXT_BUFFER_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.endMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
+
+ return E_OK;
+}
+
+t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy,
+ t_FmBufferPrefixContent *p_BufferPrefixContent,
+ t_FmSpBufMargins *p_FmSpBufMargins,
+ t_FmSpBufferOffsets *p_FmSpBufferOffsets,
+ uint8_t *internalBufferOffset)
+{
+ uint32_t tmp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmSpIntContextDataCopy, E_INVALID_VALUE);
+ ASSERT_COND(p_FmSpIntContextDataCopy);
+ ASSERT_COND(p_BufferPrefixContent);
+ ASSERT_COND(p_FmSpBufMargins);
+ ASSERT_COND(p_FmSpBufferOffsets);
+
+ /* Align start of internal context data to 16 byte */
+ p_FmSpIntContextDataCopy->extBufOffset =
+ (uint16_t)((p_BufferPrefixContent->privDataSize & (OFFSET_UNITS-1)) ?
+ ((p_BufferPrefixContent->privDataSize + OFFSET_UNITS) & ~(uint16_t)(OFFSET_UNITS-1)) :
+ p_BufferPrefixContent->privDataSize);
+
+ /* Translate margin and intContext params to FM parameters */
+ /* Initialize with illegal value. Later we'll set legal values. */
+ p_FmSpBufferOffsets->prsResultOffset = (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->timeStampOffset = (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->hashResultOffset= (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->pcdInfoOffset = (uint32_t)ILLEGAL_BASE;
+
+ /* Internally the driver supports 4 options
+ 1. prsResult/timestamp/hashResult selection (in fact 8 options, but for simplicity we'll
+ relate to it as 1).
+ 2. All IC context (from AD) not including debug.*/
+
+ /* This 'if' covers option 2. We copy from beginning of context. */
+ if (p_BufferPrefixContent->passAllOtherPCDInfo)
+ {
+ p_FmSpIntContextDataCopy->size = 128; /* must be aligned to 16 */
+ /* Start copying data after 16 bytes (FD) from the beginning of the internal context */
+ p_FmSpIntContextDataCopy->intContextOffset = 16;
+
+ if (p_BufferPrefixContent->passAllOtherPCDInfo)
+ p_FmSpBufferOffsets->pcdInfoOffset = p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passPrsResult)
+ p_FmSpBufferOffsets->prsResultOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 16);
+ if (p_BufferPrefixContent->passTimeStamp)
+ p_FmSpBufferOffsets->timeStampOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 48);
+ if (p_BufferPrefixContent->passHashResult)
+ p_FmSpBufferOffsets->hashResultOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 56);
+ }
+ else
+ {
+ /* This case covers the options under 1 */
+ /* Copy size must be in 16-byte granularity. */
+ p_FmSpIntContextDataCopy->size =
+ (uint16_t)((p_BufferPrefixContent->passPrsResult ? 32 : 0) +
+ ((p_BufferPrefixContent->passTimeStamp ||
+ p_BufferPrefixContent->passHashResult) ? 16 : 0));
+
+ /* Align start of internal context data to 16 byte */
+ p_FmSpIntContextDataCopy->intContextOffset =
+ (uint8_t)(p_BufferPrefixContent->passPrsResult ? 32 :
+ ((p_BufferPrefixContent->passTimeStamp ||
+ p_BufferPrefixContent->passHashResult) ? 64 : 0));
+
+ if (p_BufferPrefixContent->passPrsResult)
+ p_FmSpBufferOffsets->prsResultOffset = p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passTimeStamp)
+ p_FmSpBufferOffsets->timeStampOffset = p_BufferPrefixContent->passPrsResult ?
+ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult)) :
+ p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passHashResult)
+ /* If PR is not requested, whether TS is requested or not, IC will be copied from TS */
+ p_FmSpBufferOffsets->hashResultOffset = p_BufferPrefixContent->passPrsResult ?
+ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult) + 8) :
+ p_FmSpIntContextDataCopy->extBufOffset + 8;
+ }
+
+ if (p_FmSpIntContextDataCopy->size)
+ p_FmSpBufMargins->startMargins =
+ (uint16_t)(p_FmSpIntContextDataCopy->extBufOffset +
+ p_FmSpIntContextDataCopy->size);
+ else
+ /* No Internal Context passing, STartMargin is immediately after privateInfo */
+ p_FmSpBufMargins->startMargins = p_BufferPrefixContent->privDataSize;
+
+ /* save extra space for manip in both external and internal buffers */
+ if (p_BufferPrefixContent->manipExtraSpace)
+ {
+ uint8_t extraSpace;
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE) >= 256)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("p_BufferPrefixContent->manipExtraSpace should be less than %d",
+ 256-CAPWAP_FRAG_EXTRA_SPACE));
+ extraSpace = (uint8_t)(p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE);
+#else
+ extraSpace = p_BufferPrefixContent->manipExtraSpace;
+#endif /* FM_CAPWAP_SUPPORT */
+ p_FmSpBufferOffsets->manipOffset = p_FmSpBufMargins->startMargins;
+ p_FmSpBufMargins->startMargins += extraSpace;
+ *internalBufferOffset = extraSpace;
+ }
+
+ /* align data start */
+ tmp = (uint32_t)(p_FmSpBufMargins->startMargins % p_BufferPrefixContent->dataAlign);
+ if (tmp)
+ p_FmSpBufMargins->startMargins += (p_BufferPrefixContent->dataAlign-tmp);
+ p_FmSpBufferOffsets->dataOffset = p_FmSpBufMargins->startMargins;
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+#if (DPAA_VERSION >= 11)
+/*****************************************************************************/
+/* API routines */
+/*****************************************************************************/
+t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams)
+{
+ t_FmVspEntry *p_FmVspEntry = NULL;
+
+ p_FmVspEntry = (t_FmVspEntry *)XX_Malloc(sizeof(t_FmVspEntry));
+ if (!p_FmVspEntry)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed"));
+ return NULL;
+ }
+ memset(p_FmVspEntry, 0, sizeof(t_FmVspEntry));
+
+ p_FmVspEntry->p_FmVspEntryDriverParams = (t_FmVspEntryDriverParams *)XX_Malloc(sizeof(t_FmVspEntryDriverParams));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed"));
+ XX_Free(p_FmVspEntry);
+ return NULL;
+ }
+ memset(p_FmVspEntry->p_FmVspEntryDriverParams, 0, sizeof(t_FmVspEntryDriverParams));
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.privDataSize = DEFAULT_FM_SP_bufferPrefixContent_privDataSize;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passPrsResult= DEFAULT_FM_SP_bufferPrefixContent_passPrsResult;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passTimeStamp= DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passAllOtherPCDInfo
+ = DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign;
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = DEFAULT_FM_SP_dmaSwapData;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = DEFAULT_FM_SP_dmaIntContextCacheAttr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = DEFAULT_FM_SP_dmaHeaderCacheAttr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = DEFAULT_FM_SP_dmaScatterGatherCacheAttr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = DEFAULT_FM_SP_dmaWriteOptimize;
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = DEFAULT_FM_SP_noScatherGather;
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset = p_FmVspParams->liodnOffset;
+
+ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, &p_FmVspParams->extBufPools, sizeof(t_FmExtPools));
+
+ p_FmVspEntry->h_Fm = p_FmVspParams->h_Fm;
+ p_FmVspEntry->portType = p_FmVspParams->portParams.portType;
+ p_FmVspEntry->portId = p_FmVspParams->portParams.portId ;
+
+ p_FmVspEntry->relativeProfileId = p_FmVspParams->relativeProfileId;
+
+ return p_FmVspEntry;
+}
+
+t_Error FM_VSP_Init(t_Handle h_FmVsp)
+{
+
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp;
+ fm_storage_profile_params fm_vsp_params;
+ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS];
+ t_Error err;
+ uint16_t absoluteProfileId = 0;
+ int i = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams,E_INVALID_HANDLE);
+
+ CHECK_INIT_PARAMETERS(p_FmVspEntry, CheckParams);
+
+ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
+ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
+
+ err = FmSpBuildBufferStructure(&p_FmVspEntry->intContext,
+ &p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent,
+ &p_FmVspEntry->bufMargins,
+ &p_FmVspEntry->bufferOffsets,
+ &p_FmVspEntry->internalBufferOffset);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+
+ err = CheckParamsGeneratedInternally(p_FmVspEntry);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+
+ p_FmVspEntry->p_FmSpRegsBase =
+ (fm_pcd_storage_profile_regs *)FmGetVSPBaseAddr(p_FmVspEntry->h_Fm);
+ if (!p_FmVspEntry->p_FmSpRegsBase)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to initialize SpRegsBase"));
+
+ /* order external buffer pools in ascending order of buffer pools sizes */
+ FmSpSetBufPoolsInAscOrderOfBufSizes(&(p_FmVspEntry->p_FmVspEntryDriverParams)->extBufPools,
+ orderedArray,
+ sizesArray);
+
+ p_FmVspEntry->extBufPools.numOfPoolsUsed =
+ p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools.numOfPoolsUsed;
+ for (i = 0; i < p_FmVspEntry->extBufPools.numOfPoolsUsed; i++)
+ {
+ p_FmVspEntry->extBufPools.extBufPool[i].id = orderedArray[i];
+ p_FmVspEntry->extBufPools.extBufPool[i].size = sizesArray[orderedArray[i]];
+ }
+
+ /* on user responsibility to fill it according requirement */
+ memset(&fm_vsp_params, 0, sizeof(fm_storage_profile_params));
+ fm_vsp_params.dma_swap_data = p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData;
+ fm_vsp_params.int_context_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr;
+ fm_vsp_params.header_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr;
+ fm_vsp_params.scatter_gather_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr;
+ fm_vsp_params.dma_write_optimize = p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize;
+ fm_vsp_params.liodn_offset = p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset;
+ fm_vsp_params.no_scather_gather = p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather;
+
+ fm_vsp_params.buf_pool_depletion = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion;
+ fm_vsp_params.backup_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools;
+ fm_vsp_params.fm_ext_pools = &p_FmVspEntry->extBufPools;
+
+ fm_vsp_params.buf_margins = &p_FmVspEntry->bufMargins;
+ fm_vsp_params.int_context = &p_FmVspEntry->intContext;
+
+ /*no check on err - it was checked earlier*/
+ FmVSPGetAbsoluteProfileId(p_FmVspEntry->h_Fm,
+ p_FmVspEntry->portType,
+ p_FmVspEntry->portId,
+ p_FmVspEntry->relativeProfileId,
+ &absoluteProfileId);
+
+ /*set all registers related to VSP*/
+ fm_vsp_fill_entry(p_FmVspEntry->p_FmSpRegsBase, absoluteProfileId, &fm_vsp_params);
+
+ p_FmVspEntry->absoluteSpId = absoluteProfileId;
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams)
+ XX_Free(p_FmVspEntry->p_FmVspEntryDriverParams);
+ p_FmVspEntry->p_FmVspEntryDriverParams = NULL;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_Free(t_Handle h_FmVsp)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp;
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ XX_Free(p_FmVspEntry);
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, t_FmBufferPrefixContent *p_FmBufferPrefixContent)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent));
+ /* if dataAlign was not initialized by user, we return to driver's default */
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign)
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = swapData;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, e_FmDmaCacheOption intContextCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = intContextCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = headerCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, e_FmDmaCacheOption scatterGatherCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = scatterGatherCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = optimize;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = noScatherGather;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_BufPoolDepletion, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion = (t_FmBufPoolDepletion *)XX_Malloc(sizeof(t_FmBufPoolDepletion));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BufPoolDepletion allocation failed"));
+ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion));
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_BackupBmPools, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed"));
+ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools));
+
+ return E_OK;
+}
+
+uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, 0);
+
+ return p_FmVspEntry->bufferOffsets.dataOffset;
+}
+
+uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.pcdInfoOffset);
+}
+
+t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.prsResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.prsResultOffset);
+}
+
+uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.timeStampOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint64_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.timeStampOffset);
+}
+
+uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.hashResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.hashResultOffset);
+}
+
+#endif /* (DPAA_VERSION >= 11) */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h
new file mode 100644
index 0000000..30b41b6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_sp.h
+
+ @Description FM SP ...
+*//***************************************************************************/
+#ifndef __FM_SP_H
+#define __FM_SP_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_sp_common.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_SP
+
+
+
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct {
+ volatile uint32_t fm_sp_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /*offset 0 - 0xc*/
+ /**< Buffer Manager pool Information-*/
+
+ volatile uint32_t res[8-FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /*offset 0x10 - 0xc*/
+ volatile uint32_t fm_sp_acnt; /*offset 0x20*/
+ volatile uint32_t fm_sp_ebm; /*offset 0x24*/
+ volatile uint32_t fm_sp_da; /*offset 0x28*/
+ volatile uint32_t fm_sp_icp; /*offset 0x2c*/
+ volatile uint32_t fm_sp_mpd; /*offset 0x30*/
+ volatile uint32_t res1[2]; /*offset 0x34 - 0x38*/
+ volatile uint32_t fm_sp_spliodn; /*offset 0x3c*/
+} _PackedType fm_pcd_storage_profile_regs;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+typedef struct fm_storage_profile_params {
+ t_FmExtPools *fm_ext_pools;
+ t_FmBackupBmPools *backup_pools;
+ t_FmSpIntContextDataCopy *int_context;
+ t_FmSpBufMargins *buf_margins;
+
+ e_FmDmaSwapOption dma_swap_data;
+ e_FmDmaCacheOption int_context_cache_attr;
+ e_FmDmaCacheOption header_cache_attr;
+ e_FmDmaCacheOption scatter_gather_cache_attr;
+ bool dma_write_optimize;
+ uint16_t liodn_offset;
+ bool no_scather_gather;
+ t_FmBufPoolDepletion *buf_pool_depletion;
+} fm_storage_profile_params;
+
+typedef struct {
+ t_FmBufferPrefixContent bufferPrefixContent;
+ e_FmDmaSwapOption dmaSwapData;
+ e_FmDmaCacheOption dmaIntContextCacheAttr;
+ e_FmDmaCacheOption dmaHeaderCacheAttr;
+ e_FmDmaCacheOption dmaScatterGatherCacheAttr;
+ bool dmaWriteOptimize;
+ uint16_t liodnOffset;
+ bool noScatherGather;
+ t_FmBufPoolDepletion *p_BufPoolDepletion;
+ t_FmBackupBmPools *p_BackupBmPools;
+ t_FmExtPools extBufPools;
+} t_FmVspEntryDriverParams;
+
+typedef struct {
+ bool valid;
+ volatile bool lock;
+ uint8_t pointedOwners;
+ uint16_t absoluteSpId;
+ uint8_t internalBufferOffset;
+ t_FmSpBufMargins bufMargins;
+ t_FmSpIntContextDataCopy intContext;
+ t_FmSpBufferOffsets bufferOffsets;
+ t_Handle h_Fm;
+ e_FmPortType portType; /**< Port type */
+ uint8_t portId; /**< Port Id - relative to type */
+ uint8_t relativeProfileId;
+ fm_pcd_storage_profile_regs *p_FmSpRegsBase;
+ t_FmExtPools extBufPools;
+ t_FmVspEntryDriverParams *p_FmVspEntryDriverParams;
+} t_FmVspEntry;
+
+
+#endif /* __FM_SP_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c
new file mode 100644
index 0000000..10601ec
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c
@@ -0,0 +1,6162 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm.c
+
+ @Description FM driver routines implementation.
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "xx_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_common.h"
+#include "fm_ipc.h"
+#include "fm.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static volatile bool blockingFlag = FALSE;
+static void IpcMsgCompletionCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint8_t *p_Reply,
+ uint32_t replyLength,
+ t_Error status)
+{
+ UNUSED(h_Fm);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);
+ blockingFlag = FALSE;
+}
+
+static void FreeInitResources(t_Fm *p_Fm)
+{
+ if (p_Fm->camBaseAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr));
+ if (p_Fm->fifoBaseAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->fifoBaseAddr));
+ if (p_Fm->resAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->resAddr));
+}
+
+static bool IsFmanCtrlCodeLoaded(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ return (bool)!!(GET_UINT32(p_Iram->iready) & IRAM_READY);
+}
+
+static t_Error CheckFmParameters(t_Fm *p_Fm)
+{
+ if (IsFmanCtrlCodeLoaded(p_Fm) && !p_Fm->p_FmDriverParam->resetOnInit)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old FMan CTRL code is loaded; FM must be reset!"));
+#if (DPAA_VERSION < 11)
+ if (!p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats || (p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats > DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("axiDbgNumOfBeats has to be in the range 1 - %d", DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS));
+#endif /* (DPAA_VERSION < 11) */
+ if (p_Fm->p_FmDriverParam->dmaCamNumOfEntries % DMA_CAM_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCamNumOfEntries has to be divisble by %d", DMA_CAM_UNITS));
+ if (!p_Fm->p_FmDriverParam->dmaCamNumOfEntries || (p_Fm->p_FmDriverParam->dmaCamNumOfEntries > DMA_MODE_MAX_CAM_NUM_OF_ENTRIES))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCamNumOfEntries has to be in the range 1 - %d", DMA_MODE_MAX_CAM_NUM_OF_ENTRIES));
+ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency > DMA_THRESH_MAX_COMMQ)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_COMMQ));
+ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency > DMA_THRESH_MAX_COMMQ)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_COMMQ));
+ if (p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaCommQThresholds.clearEmergency must be smaller than dmaCommQThresholds.assertEmergency"));
+#if (DPAA_VERSION < 11)
+ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaReadBufThresholds.clearEmergency must be smaller than dmaReadBufThresholds.assertEmergency"));
+ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.assertEmergency can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.clearEmergency can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency >= p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaWriteBufThresholds.clearEmergency must be smaller than dmaWriteBufThresholds.assertEmergency"));
+#endif /* (DPAA_VERSION < 11) */
+#if (DPAA_VERSION >= 11)
+ if ((p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_INT_READ_EM)||
+ (p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_INT_WRITE_EM) ||
+ (p_Fm->p_FmDriverParam->dmaDbgCntMode == e_FM_DMA_DBG_CNT_RAW_WAR_PROT))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaDbgCntMode value not supported by this integration."));
+ if ((p_Fm->p_FmDriverParam->dmaEmergency.emergencyBusSelect == FM_DMA_MURAM_READ_EMERGENCY)||
+ (p_Fm->p_FmDriverParam->dmaEmergency.emergencyBusSelect == FM_DMA_MURAM_WRITE_EMERGENCY))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("emergencyBusSelect value not supported by this integration."));
+ if (p_Fm->p_FmDriverParam->dmaStopOnBusError)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaStopOnBusError not supported by this integration."));
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_Fm->p_FmDriverParam->dmaAidMode != e_FM_DMA_AID_OUT_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaAidMode not supported by this integration."));
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+ if (p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dmaAxiDbgNumOfBeats not supported by this integration."));
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (!p_Fm->p_FmStateStruct->fmClkFreq)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fmClkFreq must be set."));
+ if (USEC_TO_CLK(p_Fm->p_FmDriverParam->dmaWatchdog, p_Fm->p_FmStateStruct->fmClkFreq) > DMA_MAX_WATCHDOG)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("dmaWatchdog depends on FM clock. dmaWatchdog(in microseconds) * clk (in Mhz), may not exceed 0x08x", DMA_MAX_WATCHDOG));
+
+#if (DPAA_VERSION >= 11)
+ if ((p_Fm->partVSPBase + p_Fm->partNumOfVSPs) > FM_VSP_MAX_NUM_OF_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partVSPBase+partNumOfVSPs out of range!!!"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->p_FmStateStruct->totalFifoSize % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be divisible by %d", BMI_FIFO_UNITS));
+ if (!p_Fm->p_FmStateStruct->totalFifoSize ||
+ (p_Fm->p_FmStateStruct->totalFifoSize > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be in the range 256 - %d", BMI_MAX_FIFO_SIZE));
+ if (!p_Fm->p_FmStateStruct->totalNumOfTasks ||
+ (p_Fm->p_FmStateStruct->totalNumOfTasks > BMI_MAX_NUM_OF_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfTasks number has to be in the range 1 - %d", BMI_MAX_NUM_OF_TASKS));
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (!p_Fm->p_FmStateStruct->maxNumOfOpenDmas ||
+ (p_Fm->p_FmStateStruct->maxNumOfOpenDmas > BMI_MAX_NUM_OF_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfOpenDmas number has to be in the range 1 - %d", BMI_MAX_NUM_OF_DMAS));
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ if (p_Fm->p_FmDriverParam->thresholds.dispLimit > FPM_MAX_DISP_LIMIT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("thresholds.dispLimit can't be greater than %d", FPM_MAX_DISP_LIMIT));
+
+ if (!p_Fm->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
+ if (!p_Fm->f_BusError)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
+
+#ifdef FM_NO_WATCHDOG
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 2) &&
+ (p_Fm->p_FmDriverParam->dmaWatchdog))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("watchdog!"));
+#endif /* FM_NO_WATCHDOG */
+
+#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) &&
+ (p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("HaltOnEccError!"));
+#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */
+
+#ifdef FM_NO_TNUM_AGING
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ if (p_Fm->p_FmDriverParam->tnumAgingPeriod)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Tnum aging!"));
+#endif /* FM_NO_TNUM_AGING */
+
+ /* check that user did not set revision-dependent exceptions */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ if (p_Fm->p_FmDriverParam->userSetExceptions & FM_EX_BMI_DISPATCH_RAM_ECC)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_BMI_DISPATCH_RAM_ECC!"));
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4)
+ if (p_Fm->p_FmDriverParam->userSetExceptions & (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC/e_FM_EX_QMI_DOUBLE_ECC!"));
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ if (p_Fm->p_FmDriverParam->userSetExceptions & FM_EX_QMI_SINGLE_ECC)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC!"));
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ return E_OK;
+}
+
+
+static void SendIpcIsr(t_Fm *p_Fm, uint32_t macEvent, uint32_t pendingReg)
+{
+ ASSERT_COND(p_Fm->guestId == NCSW_MASTER_ID);
+
+ if (p_Fm->intrMng[macEvent].guestId == NCSW_MASTER_ID)
+ p_Fm->intrMng[macEvent].f_Isr(p_Fm->intrMng[macEvent].h_SrcHandle);
+
+ /* If the MAC is running on guest-partition and we have IPC session with it,
+ we inform him about the event through IPC; otherwise, we ignore the event. */
+ else if (p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId])
+ {
+ t_Error err;
+ t_FmIpcIsr fmIpcIsr;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_GUEST_ISR;
+ fmIpcIsr.pendingReg = pendingReg;
+ fmIpcIsr.boolErr = FALSE;
+ memcpy(msg.msgBody, &fmIpcIsr, sizeof(fmIpcIsr));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(fmIpcIsr),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ }
+ else
+ DBG(TRACE, ("FM Guest mode, without IPC - can't call ISR!"));
+}
+
+static void BmiErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event, mask, force;
+
+ event = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr);
+ mask = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier);
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr);
+ if (force & event)
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, force & ~event);
+
+ /* clear the acknowledged events */
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr, event);
+
+ if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STORAGE_PROFILE_ECC);
+ if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_LIST_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STATISTICS_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_DISPATCH_RAM_ECC);
+}
+
+static void QmiErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event, mask, force;
+
+ event = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie);
+ mask = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif);
+ if (force & event)
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, force & ~event);
+
+ /* clear the acknowledged events */
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie, event);
+
+ if (event & QMI_ERR_INTR_EN_DOUBLE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DOUBLE_ECC);
+ if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID);
+}
+
+static void DmaErrEvent(t_Fm *p_Fm)
+{
+ uint64_t addr=0;
+ uint32_t status, mask, tmpReg=0;
+ uint8_t tnum;
+ uint8_t hardwarePortId;
+ uint8_t relativePortId;
+ uint16_t liodn;
+
+ status = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr);
+ mask = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr);
+
+ /* get bus error regs before clearing BER */
+ if ((status & DMA_STATUS_BUS_ERR) && (mask & DMA_MODE_BER))
+ {
+ addr = (uint64_t)GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtal);
+ addr |= ((uint64_t)(GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtah)) << 32);
+
+ /* get information about the owner of that bus error */
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtcid);
+ }
+
+ /* clear set events */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsr, status);
+
+ if ((status & DMA_STATUS_BUS_ERR) && (mask & DMA_MODE_BER))
+ {
+ hardwarePortId = (uint8_t)(((tmpReg & DMA_TRANSFER_PORTID_MASK) >> DMA_TRANSFER_PORTID_SHIFT));
+ HW_PORT_ID_TO_SW_PORT_ID(relativePortId, hardwarePortId);
+ tnum = (uint8_t)((tmpReg & DMA_TRANSFER_TNUM_MASK) >> DMA_TRANSFER_TNUM_SHIFT);
+ liodn = (uint16_t)(tmpReg & DMA_TRANSFER_LIODN_MASK);
+ ASSERT_COND(p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] != e_FM_PORT_TYPE_DUMMY);
+ p_Fm->f_BusError(p_Fm->h_App,
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId],
+ relativePortId,
+ addr,
+ tnum,
+ liodn);
+ }
+ if (mask & DMA_MODE_ECC)
+ {
+ if (status & DMA_STATUS_FM_SPDAT_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SINGLE_PORT_ECC);
+ if (status & DMA_STATUS_READ_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_READ_ECC);
+ if (status & DMA_STATUS_SYSTEM_WRITE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SYSTEM_WRITE_ECC);
+ if (status & DMA_STATUS_FM_WRITE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_FM_WRITE_ECC);
+ }
+}
+
+static void FpmErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event;
+
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+
+ /* clear the all occurred events */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, event);
+
+ if ((event & FPM_EV_MASK_DOUBLE_ECC) && (event & FPM_EV_MASK_DOUBLE_ECC_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_DOUBLE_ECC);
+ if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_STALL_ON_TASKS);
+ if ((event & FPM_EV_MASK_SINGLE_ECC) && (event & FPM_EV_MASK_SINGLE_ECC_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_SINGLE_ECC);
+}
+
+static void MuramErrIntr(t_Fm *p_Fm)
+{
+ uint32_t event, mask;
+
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr);
+ mask = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie);
+
+ ASSERT_COND(event & FPM_RAM_CTL_MURAM_ECC);
+
+ /* clear MURAM event bit */
+ /* Prior to V3 this event bit clearing does not work ! ) */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, event & ~FPM_RAM_CTL_IRAM_ECC);
+
+ ASSERT_COND(event & FPM_RAM_CTL_RAMS_ECC_EN);
+
+ if ((mask & FPM_MURAM_ECC_ERR_EX_EN))
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_MURAM_ECC);
+}
+
+static void IramErrIntr(t_Fm *p_Fm)
+{
+ uint32_t event, mask;
+
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr) ;
+ mask = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie);
+
+ ASSERT_COND(event & FPM_RAM_CTL_IRAM_ECC);
+
+ /* clear the acknowledged events (do not clear IRAM event) */
+ /* Prior to V3 this event bit clearing does not work ! ) */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, event & ~FPM_RAM_CTL_MURAM_ECC);
+
+ ASSERT_COND(event & FPM_RAM_CTL_IRAM_ECC_EN);
+
+ if ((mask & FPM_IRAM_ECC_ERR_EX_EN))
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_IRAM_ECC);
+}
+
+static void QmiEvent(t_Fm *p_Fm)
+{
+ uint32_t event, mask, force;
+
+ event = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie);
+ mask = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_if);
+ if (force & event)
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_if, force & ~event);
+
+ /* clear the acknowledged events */
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie, event);
+
+ if (event & QMI_INTR_EN_SINGLE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_SINGLE_ECC);
+}
+
+static void UnimplementedIsr(t_Handle h_Arg)
+{
+ UNUSED(h_Arg);
+
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented ISR!"));
+}
+
+static void UnimplementedFmanCtrlIsr(t_Handle h_Arg, uint32_t event)
+{
+ UNUSED(h_Arg); UNUSED(event);
+
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented FmCtl ISR!"));
+}
+
+static void EnableTimeStamp(t_Fm *p_Fm)
+{
+ uint64_t fraction;
+ uint32_t integer, tsFrequency, tmpReg;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->p_FmStateStruct);
+ ASSERT_COND(p_Fm->p_FmStateStruct->count1MicroBit);
+
+ tsFrequency = (uint32_t)(1<<p_Fm->p_FmStateStruct->count1MicroBit); /* in Mhz */
+
+ /* configure timestamp so that bit 8 will count 1 microsecond */
+ /* Find effective count rate at TIMESTAMP least significant bits:
+ Effective_Count_Rate = 1MHz x 2^8 = 256MHz
+ Find frequency ratio between effective count rate and the clock:
+ Effective_Count_Rate / CLK e.g. for 600 MHz clock:
+ 256/600 = 0.4266666... */
+ integer = tsFrequency/p_Fm->p_FmStateStruct->fmClkFreq;
+ /* we multiply by 2^16 to keep the fraction of the division */
+ /* we do not divide back, since we write this value as fraction - see spec */
+ fraction = ((tsFrequency << 16) - (integer << 16) * p_Fm->p_FmStateStruct->fmClkFreq) / p_Fm->p_FmStateStruct->fmClkFreq;
+ /* we check remainder of the division in order to round up if not integer */
+ if (((tsFrequency << 16) - (integer << 16) * p_Fm->p_FmStateStruct->fmClkFreq) % p_Fm->p_FmStateStruct->fmClkFreq)
+ fraction++;
+
+ tmpReg = (integer << FPM_TS_INT_SHIFT) | (uint16_t)fraction;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc2, tmpReg);
+
+ /* enable timestamp with original clock */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1, FPM_TS_CTL_EN);
+
+ p_Fm->p_FmStateStruct->enabledTimeStamp = TRUE;
+}
+
+static t_Error ClearIRam(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+ int i;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+
+ for (i=0; i < (FM_IRAM_SIZE/4); i++)
+ WRITE_UINT32(p_Iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_Iram->iadd, FM_IRAM_SIZE - 4);
+ CORE_MemoryBarrier();
+ while (GET_UINT32(p_Iram->idata) != 0xffffffff) ;
+
+ return E_OK;
+}
+
+static t_Error LoadFmanCtrlCode(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+ int i;
+ uint32_t tmp;
+ uint8_t compTo16;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+
+ for (i=0; i < (p_Fm->p_FmDriverParam->firmware.size / 4); i++)
+ WRITE_UINT32(p_Iram->idata, p_Fm->p_FmDriverParam->firmware.p_Code[i]);
+
+ compTo16 = (uint8_t)(p_Fm->p_FmDriverParam->firmware.size % 16);
+ if (compTo16)
+ for (i=0; i < ((16-compTo16) / 4); i++)
+ WRITE_UINT32(p_Iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_Iram->iadd,p_Fm->p_FmDriverParam->firmware.size-4);
+ while (GET_UINT32(p_Iram->iadd) != (p_Fm->p_FmDriverParam->firmware.size-4)) ;
+
+ /* verify that writing has completed */
+ while (GET_UINT32(p_Iram->idata) != p_Fm->p_FmDriverParam->firmware.p_Code[(p_Fm->p_FmDriverParam->firmware.size / 4)-1]) ;
+
+ if (p_Fm->p_FmDriverParam->fwVerify)
+ {
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+ for (i=0; i < (p_Fm->p_FmDriverParam->firmware.size / 4); i++)
+ {
+ tmp = GET_UINT32(p_Iram->idata);
+ if (tmp != p_Fm->p_FmDriverParam->firmware.p_Code[i])
+ RETURN_ERROR(MAJOR, E_WRITE_FAILED,
+ ("UCode write error : write 0x%x, read 0x%x",
+ p_Fm->p_FmDriverParam->firmware.p_Code[i],tmp));
+ }
+ WRITE_UINT32(p_Iram->iadd, 0x0);
+ }
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_Iram->iready, IRAM_READY);
+ XX_UDelay(1000);
+
+ DBG(INFO, ("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.",
+ ((uint16_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[2],
+ ((uint8_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[6],
+ ((uint8_t *)p_Fm->p_FmDriverParam->firmware.p_Code)[7]));
+
+ return E_OK;
+}
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+static t_Error FwNotResetErratumBugzilla6173WA(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+ uint32_t tmpReg;
+
+ /* write to IRAM first location the debug instruction */
+ WRITE_UINT32(p_Iram->iadd, 0);
+ while (GET_UINT32(p_Iram->iadd) != 0) ;
+ WRITE_UINT32(p_Iram->idata, FM_FW_DEBUG_INSTRUCTION);
+
+ WRITE_UINT32(p_Iram->iadd, 0);
+ while (GET_UINT32(p_Iram->iadd) != 0) ;
+ while (GET_UINT32(p_Iram->idata) != FM_FW_DEBUG_INSTRUCTION) ;
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_Iram->iready, IRAM_READY);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+
+ /* reset FMAN */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+
+ /* verify breakpoint debug status register */
+ tmpReg = GET_UINT32(*(uint32_t *)UINT_TO_PTR(p_Fm->baseAddr + FM_DEBUG_STATUS_REGISTER_OFFSET));
+ if (!tmpReg)
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid debug status register value is '0'"));
+
+ /*************************************/
+ /* Load FMan-Controller code to IRAM */
+ /*************************************/
+ if (ClearIRam(p_Fm) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ if (p_Fm->p_FmDriverParam->firmware.p_Code &&
+ (LoadFmanCtrlCode(p_Fm) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ XX_UDelay(100);
+
+ /* reset FMAN again to start the microcode */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+
+ if (GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY)
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ /* clear tmpReg event bits in order not to clear standing events */
+ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ }
+
+ return E_OK;
+}
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+static void GuestErrorIsr(t_Fm *p_Fm, uint32_t pending)
+{
+#define FM_G_CALL_1G_MAC_ERR_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+#define FM_G_CALL_10G_MAC_ERR_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+
+ /* error interrupts */
+ if (pending & ERR_INTR_EN_1G_MAC0)
+ FM_G_CALL_1G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_1G_MAC1)
+ FM_G_CALL_1G_MAC_ERR_ISR(1);
+ if (pending & ERR_INTR_EN_1G_MAC2)
+ FM_G_CALL_1G_MAC_ERR_ISR(2);
+ if (pending & ERR_INTR_EN_1G_MAC3)
+ FM_G_CALL_1G_MAC_ERR_ISR(3);
+ if (pending & ERR_INTR_EN_1G_MAC4)
+ FM_G_CALL_1G_MAC_ERR_ISR(4);
+ if (pending & ERR_INTR_EN_1G_MAC5)
+ FM_G_CALL_1G_MAC_ERR_ISR(5);
+ if (pending & ERR_INTR_EN_1G_MAC6)
+ FM_G_CALL_1G_MAC_ERR_ISR(6);
+ if (pending & ERR_INTR_EN_1G_MAC7)
+ FM_G_CALL_1G_MAC_ERR_ISR(7);
+ if (pending & ERR_INTR_EN_10G_MAC0)
+ FM_G_CALL_10G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_10G_MAC1)
+ FM_G_CALL_10G_MAC_ERR_ISR(1);
+}
+
+static void GuestEventIsr(t_Fm *p_Fm, uint32_t pending)
+{
+#define FM_G_CALL_1G_MAC_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+#define FM_G_CALL_10G_MAC_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+
+ if (pending & INTR_EN_1G_MAC0)
+ FM_G_CALL_1G_MAC_ISR(0);
+ if (pending & INTR_EN_1G_MAC1)
+ FM_G_CALL_1G_MAC_ISR(1);
+ if (pending & INTR_EN_1G_MAC2)
+ FM_G_CALL_1G_MAC_ISR(2);
+ if (pending & INTR_EN_1G_MAC3)
+ FM_G_CALL_1G_MAC_ISR(3);
+ if (pending & INTR_EN_1G_MAC4)
+ FM_G_CALL_1G_MAC_ISR(4);
+ if (pending & INTR_EN_1G_MAC5)
+ FM_G_CALL_1G_MAC_ISR(5);
+ if (pending & INTR_EN_1G_MAC6)
+ FM_G_CALL_1G_MAC_ISR(6);
+ if (pending & INTR_EN_1G_MAC7)
+ FM_G_CALL_1G_MAC_ISR(7);
+ if (pending & INTR_EN_10G_MAC0)
+ FM_G_CALL_10G_MAC_ISR(0);
+ if (pending & INTR_EN_10G_MAC1)
+ FM_G_CALL_10G_MAC_ISR(1);
+ if (pending & INTR_EN_TMR)
+ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle);
+}
+
+#if (DPAA_VERSION >= 11)
+static t_Error SetVSPWindow(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t baseStorageProfile,
+ uint8_t log2NumOfProfiles)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint32_t tmpReg;
+
+ ASSERT_COND(h_Fm);
+ ASSERT_COND(hardwarePortId);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmBmiRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcVspSetPortWindow fmIpcVspSetPortWindow;
+ t_FmIpcMsg msg;
+ t_Error err = E_OK;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&fmIpcVspSetPortWindow, 0, sizeof(t_FmIpcVspSetPortWindow));
+ fmIpcVspSetPortWindow.hardwarePortId = hardwarePortId;
+ fmIpcVspSetPortWindow.baseStorageProfile = baseStorageProfile;
+ fmIpcVspSetPortWindow.log2NumOfProfiles = log2NumOfProfiles;
+ msg.msgId = FM_VSP_SET_PORT_WINDOW;
+ memcpy(msg.msgBody, &fmIpcVspSetPortWindow, sizeof(t_FmIpcVspSetPortWindow));
+
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Fm->p_FmBmiRegs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1]);
+ tmpReg |= (uint32_t)((uint32_t)baseStorageProfile & 0x3f) << 16;
+ tmpReg |= (uint32_t)log2NumOfProfiles << 28;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], tmpReg);
+
+ return E_OK;
+}
+
+static uint8_t AllocVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t profilesFound = 0;
+ int i = 0;
+ uint32_t intFlags;
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ if ((numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES) ||
+ (base + numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES))
+ return (uint8_t)ILLEGAL_BASE;
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_Fm->guestId;
+ ipcAllocParams.num = p_Fm->partNumOfVSPs;
+ ipcAllocParams.base = p_Fm->partVSPBase;
+ msg.msgId = FM_VSP_ALLOC;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if ((err != E_OK) ||
+ (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))))
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ else
+ memcpy((uint8_t*)&p_Fm->partVSPBase, reply.replyBody, sizeof(uint8_t));
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!"));
+ return (uint8_t)ILLEGAL_BASE;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ for (i = base; i < base + numOfProfiles; i++)
+ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE)
+ profilesFound++;
+ else
+ break;
+
+ if (profilesFound == numOfProfiles)
+ for (i = base; i<base + numOfProfiles; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = guestId;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ return (uint8_t)ILLEGAL_BASE;
+ }
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return base;
+}
+
+static void FreeVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ int i = 0;
+
+ ASSERT_COND(p_Fm);
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_Fm->guestId;
+ ipcAllocParams.num = p_Fm->partNumOfVSPs;
+ ipcAllocParams.base = p_Fm->partVSPBase;
+ msg.msgId = FM_VSP_FREE;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return;
+ }
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!"));
+ return;
+ }
+
+ ASSERT_COND(p_Fm->p_FmSp);
+
+ for (i=base; i<numOfProfiles; i++)
+ {
+ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == guestId)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+ else
+ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition"));
+ }
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+static t_Error FmGuestHandleIpcMsgCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg;
+
+ UNUSED(p_Reply);
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength > sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_Msg);
+
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_GUEST_ISR):
+ {
+ t_FmIpcIsr ipcIsr;
+
+ memcpy((uint8_t*)&ipcIsr, p_IpcMsg->msgBody, sizeof(t_FmIpcIsr));
+ if (ipcIsr.boolErr)
+ GuestErrorIsr(p_Fm, ipcIsr.pendingReg);
+ else
+ GuestEventIsr(p_Fm, ipcIsr.pendingReg);
+ break;
+ }
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+static t_Error FmHandleIpcMsgCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_Error err;
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg;
+ t_FmIpcReply *p_IpcReply = (t_FmIpcReply*)p_Reply;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_IpcMsg);
+
+ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_IPC_MAX_REPLY_SIZE));
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_GET_SET_PORT_PARAMS):
+ {
+ t_FmIpcPortInInitParams ipcInitParams;
+ t_FmInterModulePortInitParams initParams;
+ t_FmIpcPortOutInitParams ipcOutInitParams;
+
+ memcpy((uint8_t*)&ipcInitParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortInInitParams));
+ initParams.hardwarePortId = ipcInitParams.hardwarePortId;
+ initParams.portType = (e_FmPortType)ipcInitParams.enumPortType;
+ initParams.independentMode = (bool)(ipcInitParams.boolIndependentMode);
+ initParams.liodnOffset = ipcInitParams.liodnOffset;
+ initParams.numOfTasks = ipcInitParams.numOfTasks;
+ initParams.numOfExtraTasks = ipcInitParams.numOfExtraTasks;
+ initParams.numOfOpenDmas = ipcInitParams.numOfOpenDmas;
+ initParams.numOfExtraOpenDmas = ipcInitParams.numOfExtraOpenDmas;
+ initParams.sizeOfFifo = ipcInitParams.sizeOfFifo;
+ initParams.extraSizeOfFifo = ipcInitParams.extraSizeOfFifo;
+ initParams.deqPipelineDepth = ipcInitParams.deqPipelineDepth;
+ initParams.maxFrameLength = ipcInitParams.maxFrameLength;
+ initParams.liodnBase = ipcInitParams.liodnBase;
+
+ p_IpcReply->error = (uint32_t)FmGetSetPortParams(h_Fm, &initParams);
+
+ ipcOutInitParams.ipcPhysAddr.high = initParams.fmMuramPhysBaseAddr.high;
+ ipcOutInitParams.ipcPhysAddr.low = initParams.fmMuramPhysBaseAddr.low;
+ ipcOutInitParams.sizeOfFifo = initParams.sizeOfFifo;
+ ipcOutInitParams.extraSizeOfFifo = initParams.extraSizeOfFifo;
+ ipcOutInitParams.numOfTasks = initParams.numOfTasks;
+ ipcOutInitParams.numOfExtraTasks = initParams.numOfExtraTasks;
+ ipcOutInitParams.numOfOpenDmas = initParams.numOfOpenDmas;
+ ipcOutInitParams.numOfExtraOpenDmas = initParams.numOfExtraOpenDmas;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcOutInitParams, sizeof(ipcOutInitParams));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams);
+ break;
+ }
+ case (FM_SET_SIZE_OF_FIFO):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetSizeOfFifo(h_Fm,
+ ipcPortRsrcParams.hardwarePortId,
+ &ipcPortRsrcParams.val,
+ &ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_NUM_OF_TASKS):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetNumOfTasks(h_Fm, ipcPortRsrcParams.hardwarePortId,
+ (uint8_t*)&ipcPortRsrcParams.val,
+ (uint8_t*)&ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_NUM_OF_OPEN_DMAS):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetNumOfOpenDmas(h_Fm, ipcPortRsrcParams.hardwarePortId,
+ (uint8_t*)&ipcPortRsrcParams.val,
+ (uint8_t*)&ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_RESUME_STALLED_PORT):
+ *p_ReplyLength = sizeof(uint32_t);
+ p_IpcReply->error = (uint32_t)FmResumeStalledPort(h_Fm, p_IpcMsg->msgBody[0]);
+ break;
+ case (FM_MASTER_IS_ALIVE):
+ {
+ uint8_t guestId = p_IpcMsg->msgBody[0];
+ /* build the FM master partition IPC address */
+ memset(p_Fm->fmIpcHandlerModuleName[guestId], 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_Fm->fmIpcHandlerModuleName[guestId], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, guestId) != (guestId<10 ? 6:7))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ p_Fm->h_IpcSessions[guestId] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[guestId], p_Fm->fmModuleName);
+ if (p_Fm->h_IpcSessions[guestId] == NULL)
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Master IPC session for guest %d", guestId));
+ *(uint8_t*)(p_IpcReply->replyBody) = 1;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_IS_PORT_STALLED):
+ {
+ bool tmp;
+
+ p_IpcReply->error = (uint32_t)FmIsPortStalled(h_Fm, p_IpcMsg->msgBody[0], &tmp);
+ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)tmp;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_RESET_MAC):
+ {
+ t_FmIpcMacParams ipcMacParams;
+
+ memcpy((uint8_t*)&ipcMacParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacParams));
+ p_IpcReply->error = (uint32_t)FmResetMac(p_Fm,
+ (e_FmMacType)(ipcMacParams.enumType),
+ ipcMacParams.id);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_MAC_MAX_FRAME):
+ {
+ t_FmIpcMacMaxFrameParams ipcMacMaxFrameParams;
+
+ memcpy((uint8_t*)&ipcMacMaxFrameParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacMaxFrameParams));
+ err = FmSetMacMaxFrame(p_Fm,
+ (e_FmMacType)(ipcMacMaxFrameParams.macParams.enumType),
+ ipcMacMaxFrameParams.macParams.id,
+ ipcMacMaxFrameParams.maxFrameLength);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ break;
+ }
+#if (DPAA_VERSION >= 11)
+ case (FM_VSP_ALLOC) :
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ uint8_t vspBase;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ vspBase = AllocVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&vspBase, sizeof(uint8_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_VSP_FREE) :
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ FreeVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_VSP_SET_PORT_WINDOW) :
+ {
+ t_FmIpcVspSetPortWindow ipcVspSetPortWindow;
+ memcpy(&ipcVspSetPortWindow, p_IpcMsg->msgBody, sizeof(t_FmIpcVspSetPortWindow));
+ err = SetVSPWindow(h_Fm,
+ ipcVspSetPortWindow.hardwarePortId,
+ ipcVspSetPortWindow.baseStorageProfile,
+ ipcVspSetPortWindow.log2NumOfProfiles);
+ return err;
+ }
+ case (FM_SET_CONG_GRP_PFC_PRIO) :
+ {
+ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority;
+ memcpy(&fmIpcSetCongestionGroupPfcPriority, p_IpcMsg->msgBody, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+ err = FmSetCongestionGroupPFCpriority(h_Fm,
+ fmIpcSetCongestionGroupPfcPriority.congestionGroupId,
+ fmIpcSetCongestionGroupPfcPriority.priorityBitMap);
+ return err;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ case (FM_FREE_PORT):
+ {
+ t_FmInterModulePortFreeParams portParams;
+ t_FmIpcPortFreeParams ipcPortParams;
+
+ memcpy((uint8_t*)&ipcPortParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortFreeParams));
+ portParams.hardwarePortId = ipcPortParams.hardwarePortId;
+ portParams.portType = (e_FmPortType)(ipcPortParams.enumPortType);
+ portParams.deqPipelineDepth = ipcPortParams.deqPipelineDepth;
+ FmFreePortParams(h_Fm, &portParams);
+ break;
+ }
+ case (FM_REGISTER_INTR):
+ {
+ t_FmIpcRegisterIntr ipcRegIntr;
+
+ memcpy((uint8_t*)&ipcRegIntr, p_IpcMsg->msgBody, sizeof(ipcRegIntr));
+ p_Fm->intrMng[ipcRegIntr.event].guestId = ipcRegIntr.guestId;
+ break;
+ }
+ case (FM_GET_PARAMS):
+ {
+ t_FmIpcParams ipcParams;
+ uint32_t tmpReg;
+
+ /* Get clock frequency */
+ ipcParams.fmClkFreq = p_Fm->p_FmStateStruct->fmClkFreq;
+
+ /* read FM revision register 1 */
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1);
+ ipcParams.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+ ipcParams.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcParams, sizeof(t_FmIpcParams));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams);
+ break;
+ }
+ case (FM_GET_FMAN_CTRL_CODE_REV):
+ {
+ t_FmCtrlCodeRevisionInfo fmanCtrlRevInfo;
+ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo;
+
+ p_IpcReply->error = (uint32_t)FM_GetFmanCtrlCodeRevision(h_Fm, &fmanCtrlRevInfo);
+ ipcRevInfo.packageRev = fmanCtrlRevInfo.packageRev;
+ ipcRevInfo.majorRev = fmanCtrlRevInfo.majorRev;
+ ipcRevInfo.minorRev = fmanCtrlRevInfo.minorRev;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_FmIpcFmanCtrlCodeRevisionInfo));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcFmanCtrlCodeRevisionInfo);
+ break;
+ }
+
+ case (FM_DMA_STAT):
+ {
+ t_FmDmaStatus dmaStatus;
+ t_FmIpcDmaStatus ipcDmaStatus;
+
+ FM_GetDmaStatus(h_Fm, &dmaStatus);
+ ipcDmaStatus.boolCmqNotEmpty = (uint8_t)dmaStatus.cmqNotEmpty;
+ ipcDmaStatus.boolBusError = (uint8_t)dmaStatus.busError;
+ ipcDmaStatus.boolReadBufEccError = (uint8_t)dmaStatus.readBufEccError;
+ ipcDmaStatus.boolWriteBufEccSysError = (uint8_t)dmaStatus.writeBufEccSysError;
+ ipcDmaStatus.boolWriteBufEccFmError = (uint8_t)dmaStatus.writeBufEccFmError;
+ ipcDmaStatus.boolSinglePortEccError = (uint8_t)dmaStatus.singlePortEccError;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcDmaStatus, sizeof(t_FmIpcDmaStatus));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus);
+ break;
+ }
+ case (FM_ALLOC_FMAN_CTRL_EVENT_REG):
+ p_IpcReply->error = (uint32_t)FmAllocFmanCtrlEventReg(h_Fm, (uint8_t*)p_IpcReply->replyBody);
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_FREE_FMAN_CTRL_EVENT_REG):
+ FmFreeFmanCtrlEventReg(h_Fm, p_IpcMsg->msgBody[0]);
+ break;
+ case (FM_GET_TIMESTAMP_SCALE):
+ {
+ uint32_t timeStamp = FmGetTimeStampScale(h_Fm);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&timeStamp, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_GET_COUNTER):
+ {
+ e_FmCounters inCounter;
+ uint32_t outCounter;
+
+ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t));
+ outCounter = FM_GetCounter(h_Fm, inCounter);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_FMAN_CTRL_EVENTS_ENABLE):
+ {
+ t_FmIpcFmanEvents ipcFmanEvents;
+
+ memcpy((uint8_t*)&ipcFmanEvents, p_IpcMsg->msgBody, sizeof(t_FmIpcFmanEvents));
+ FmSetFmanCtrlIntr(h_Fm,
+ ipcFmanEvents.eventRegId,
+ ipcFmanEvents.enableEvents);
+ break;
+ }
+ case (FM_GET_FMAN_CTRL_EVENTS_ENABLE):
+ {
+ uint32_t tmp = FmGetFmanCtrlIntr(h_Fm, p_IpcMsg->msgBody[0]);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_GET_PHYS_MURAM_BASE):
+ {
+ t_FmPhysAddr physAddr;
+ t_FmIpcPhysAddr ipcPhysAddr;
+
+ FmGetPhysicalMuramBase(h_Fm, &physAddr);
+ ipcPhysAddr.high = physAddr.high;
+ ipcPhysAddr.low = physAddr.low;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcPhysAddr, sizeof(t_FmIpcPhysAddr));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPhysAddr);
+ break;
+ }
+ case (FM_ENABLE_RAM_ECC):
+ {
+ if (((err = FM_EnableRamsEcc(h_Fm)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, TRUE)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, TRUE)) != E_OK))
+#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0))
+ UNUSED(err);
+#else
+ REPORT_ERROR(MINOR, err, NO_MSG);
+#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */
+ break;
+ }
+ case (FM_DISABLE_RAM_ECC):
+ {
+
+ if (((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, FALSE)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, FALSE)) != E_OK) ||
+ ((err = FM_DisableRamsEcc(h_Fm)) != E_OK))
+#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0))
+ UNUSED(err);
+#else
+ REPORT_ERROR(MINOR, err, NO_MSG);
+#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */
+ break;
+ }
+ case (FM_SET_NUM_OF_FMAN_CTRL):
+ {
+ t_FmIpcPortNumOfFmanCtrls ipcPortNumOfFmanCtrls;
+
+ memcpy((uint8_t*)&ipcPortNumOfFmanCtrls, p_IpcMsg->msgBody, sizeof(t_FmIpcPortNumOfFmanCtrls));
+ err = FmSetNumOfRiscsPerPort(h_Fm,
+ ipcPortNumOfFmanCtrls.hardwarePortId,
+ ipcPortNumOfFmanCtrls.numOfFmanCtrls,
+ ipcPortNumOfFmanCtrls.orFmanCtrl);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ break;
+ }
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ case (FM_10G_TX_ECC_WA):
+ p_IpcReply->error = (uint32_t)Fm10GTxEccWorkaround(h_Fm, p_IpcMsg->msgBody[0]);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+
+/****************************************/
+/* Inter-Module functions */
+/****************************************/
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int timeout = 1000;
+ t_Error err = E_OK;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ uint8_t rxHardwarePortId, txHardwarePortId;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_10G_TX_ECC_WA;
+ msg.msgBody[0] = macId;
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+
+ SANITY_CHECK_RETURN_ERROR((macId == 0), E_NOT_SUPPORTED);
+ SANITY_CHECK_RETURN_ERROR(IsFmanCtrlCodeLoaded(p_Fm), E_INVALID_STATE);
+
+ SW_PORT_ID_TO_HW_PORT_ID(rxHardwarePortId, e_FM_PORT_TYPE_RX_10G, macId);
+ SW_PORT_ID_TO_HW_PORT_ID(txHardwarePortId, e_FM_PORT_TYPE_TX_10G, macId);
+ if ((p_Fm->p_FmStateStruct->portsTypes[rxHardwarePortId] != e_FM_PORT_TYPE_DUMMY) ||
+ (p_Fm->p_FmStateStruct->portsTypes[txHardwarePortId] != e_FM_PORT_TYPE_DUMMY))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("MAC should be initialized prior to Rx and Tx ports!"));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc, 0x40000000);
+ CORE_MemoryBarrier();
+ while ((GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc) & 0x40000000) &&
+ --timeout) ;
+ if (!timeout)
+ return ERROR_CODE(E_TIMEOUT);
+ return E_OK;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm,
+ uint32_t congestionGroupId,
+ uint8_t priorityBitMap)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ ASSERT_COND(h_Fm);
+
+ if (congestionGroupId > FM_PORT_NUM_OF_CONGESTION_GRPS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Congestion group ID bigger than %d \n!",
+ FM_PORT_NUM_OF_CONGESTION_GRPS));
+
+ if (p_Fm->guestId == NCSW_MASTER_ID)
+ {
+ uint32_t *p_Cpg = (uint32_t*)(p_Fm->baseAddr+FM_MM_CGP);
+ uint32_t tmpReg;
+ uint32_t reg_num;
+ uint32_t offset;
+
+ ASSERT_COND(p_Fm->baseAddr);
+ reg_num = (FM_PORT_NUM_OF_CONGESTION_GRPS-1-(congestionGroupId))/4;
+ offset = (congestionGroupId%4);
+
+ tmpReg = GET_UINT32(p_Cpg[reg_num]);
+
+ if (priorityBitMap)//adding priority
+ {
+ if (tmpReg & (0xFF<<(offset*8)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("PFC priority for the congestion group is already set!"));
+ }
+ tmpReg |= (uint32_t)priorityBitMap << (offset*8);
+ WRITE_UINT32(p_Cpg[reg_num], tmpReg);
+ }
+
+ else if (p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&fmIpcSetCongestionGroupPfcPriority, 0, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+ fmIpcSetCongestionGroupPfcPriority.congestionGroupId = congestionGroupId;
+ fmIpcSetCongestionGroupPfcPriority.priorityBitMap = priorityBitMap;
+
+ msg.msgId = FM_SET_CONG_GRP_PFC_PRIO;
+ memcpy(msg.msgBody, &fmIpcSetCongestionGroupPfcPriority, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("guest without IPC!"));
+
+ return E_OK;
+}
+
+uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_PRS);
+}
+
+uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_KG);
+}
+
+uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_PLCR);
+}
+
+#if (DPAA_VERSION >= 11)
+uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ return p_Fm->vspBaseAddr;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Handle FmGetMuramHandle(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL);
+
+ return (p_Fm->h_FmMuram);
+}
+
+void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *p_FmPhysAddr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (p_Fm->fmMuramPhysBaseAddr)
+ {
+ /* General FM driver initialization */
+ p_FmPhysAddr->low = (uint32_t)p_Fm->fmMuramPhysBaseAddr;
+ p_FmPhysAddr->high = (uint8_t)((p_Fm->fmMuramPhysBaseAddr & 0x000000ff00000000LL) >> 32);
+ return;
+ }
+
+ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID);
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_FmIpcPhysAddr ipcPhysAddr;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_PHYS_MURAM_BASE;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmPhysAddr);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmPhysAddr)))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE,("IPC reply length mismatch"));
+ return;
+ }
+ memcpy((uint8_t*)&ipcPhysAddr, reply.replyBody, sizeof(t_FmIpcPhysAddr));
+ p_FmPhysAddr->high = ipcPhysAddr.high;
+ p_FmPhysAddr->low = ipcPhysAddr.low;
+ }
+ else
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPAllocForPort (t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint8_t numOfVSPs)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err = E_OK;
+ uint32_t profilesFound, intFlags;
+ uint8_t first, i;
+ uint8_t log2Num;
+ uint8_t swPortIndex=0, hardwarePortId;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ if (!numOfVSPs)
+ return E_OK;
+
+ if (numOfVSPs > FM_VSP_MAX_NUM_OF_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles can not be bigger than %d.",FM_VSP_MAX_NUM_OF_ENTRIES));
+
+ if (!POWER_OF_2(numOfVSPs))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2."));
+
+ LOG2((uint64_t)numOfVSPs, log2Num);
+
+ if ((log2Num == 0) || (p_Fm->partVSPBase == 0))
+ first = 0;
+ else
+ first = 1<<log2Num;
+
+ if (first > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window"));
+
+ if (first < p_Fm->partVSPBase)
+ while (first < p_Fm->partVSPBase)
+ first = first + numOfVSPs;
+
+ if ((first + numOfVSPs) > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window"));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ profilesFound = 0;
+ for (i=first; i < p_Fm->partVSPBase + p_Fm->partNumOfVSPs; )
+ {
+ if (!p_Fm->p_FmSp->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ i++;
+ if (profilesFound == numOfVSPs)
+ break;
+ }
+ else
+ {
+ profilesFound = 0;
+ /* advance i to the next aligned address */
+ first = i = (uint8_t)(first + numOfVSPs);
+ }
+ }
+ if (profilesFound == numOfVSPs)
+ for (i = first; i<first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = TRUE;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MINOR, E_FULL, ("No profiles."));
+ }
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = numOfVSPs;
+ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = first;
+
+ if ((err = SetVSPWindow(h_Fm,hardwarePortId, first,log2Num)) != E_OK)
+ for (i = first; i < first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE;
+
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return err;
+}
+
+t_Error FmVSPFreeForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t swPortIndex=0, hardwarePortId, first, numOfVSPs, i;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ numOfVSPs = p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles;
+ first = p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase;
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ for (i = first; i < first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE;
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = 0;
+ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = 0;
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_ALLOC_FMAN_CTRL_EVENT_REG;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ *p_EventId = *(uint8_t*)(reply.replyBody);
+
+ return (t_Error)(reply.error);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ for (i=0;i<FM_NUM_OF_FMAN_CTRL_EVENT_REGS;i++)
+ if (!p_Fm->usedEventRegs[i])
+ {
+ p_Fm->usedEventRegs[i] = TRUE;
+ *p_EventId = i;
+ break;
+ }
+
+ if (i==FM_NUM_OF_FMAN_CTRL_EVENT_REGS)
+ RETURN_ERROR(MAJOR, E_BUSY, ("No resource - FMan controller event register."));
+
+ return E_OK;
+}
+
+void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_FREE_FMAN_CTRL_EVENT_REG;
+ msg.msgBody[0] = eventId;
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(eventId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+ return;
+ }
+
+ ((t_Fm*)h_Fm)->usedEventRegs[eventId] = FALSE;
+}
+
+void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcFmanEvents fmanCtrl;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ fmanCtrl.eventRegId = eventRegId;
+ fmanCtrl.enableEvents = enableEvents;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_SET_FMAN_CTRL_EVENTS_ENABLE;
+ memcpy(msg.msgBody, &fmanCtrl, sizeof(fmanCtrl));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(fmanCtrl),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return;
+ }
+
+ ASSERT_COND(eventRegId < FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[eventRegId], enableEvents);
+}
+
+uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, ctrlIntr;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_FMAN_CTRL_EVENTS_ENABLE;
+ msg.msgBody[0] = eventRegId;
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(eventRegId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return 0;
+ }
+ memcpy((uint8_t*)&ctrlIntr, reply.replyBody, sizeof(uint32_t));
+ return ctrlIntr;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return 0;
+ }
+
+ return GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[eventRegId]);
+}
+
+void FmRegisterIntr(t_Handle h_Fm,
+ e_FmEventModules module,
+ uint8_t modId,
+ e_FmIntrType intrType,
+ void (*f_Isr) (t_Handle h_Arg),
+ t_Handle h_Arg)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int event = 0;
+
+ ASSERT_COND(h_Fm);
+
+ GET_FM_MODULE_EVENT(module, modId, intrType, event);
+ ASSERT_COND(event < e_FM_EV_DUMMY_LAST);
+
+ /* register in local FM structure */
+ p_Fm->intrMng[event].f_Isr = f_Isr;
+ p_Fm->intrMng[event].h_SrcHandle = h_Arg;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcRegisterIntr fmIpcRegisterIntr;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ /* register in Master FM structure */
+ fmIpcRegisterIntr.event = (uint32_t)event;
+ fmIpcRegisterIntr.guestId = p_Fm->guestId;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_REGISTER_INTR;
+ memcpy(msg.msgBody, &fmIpcRegisterIntr, sizeof(fmIpcRegisterIntr));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(fmIpcRegisterIntr),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+}
+
+void FmUnregisterIntr(t_Handle h_Fm,
+ e_FmEventModules module,
+ uint8_t modId,
+ e_FmIntrType intrType)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int event = 0;
+
+ ASSERT_COND(h_Fm);
+
+ GET_FM_MODULE_EVENT(module, modId,intrType, event);
+ ASSERT_COND(event < e_FM_EV_DUMMY_LAST);
+
+ p_Fm->intrMng[event].f_Isr = UnimplementedIsr;
+ p_Fm->intrMng[event].h_SrcHandle = NULL;
+}
+
+void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Arg, uint32_t event), t_Handle h_Arg)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ ASSERT_COND(eventRegId<FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode"));
+ return;
+ }
+
+ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = f_Isr;
+ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = h_Arg;
+}
+
+void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ ASSERT_COND(eventRegId<FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode"));
+ return;
+ }
+
+ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = UnimplementedFmanCtrlIsr;
+ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = NULL;
+}
+
+void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (p_Fm->h_Pcd)
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("PCD already set"));
+
+ p_Fm->h_Pcd = h_FmPcd;
+}
+
+void FmUnregisterPcd(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (!p_Fm->h_Pcd)
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("PCD handle!"));
+
+ p_Fm->h_Pcd = NULL;
+}
+
+t_Handle FmGetPcdHandle(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return p_Fm->h_Pcd;
+}
+
+uint8_t FmGetId(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0xff);
+
+ return p_Fm->p_FmStateStruct->fmId;
+}
+
+t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t numOfFmanCtrls,
+ t_FmFmanCtrl orFmanCtrl)
+{
+
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((numOfFmanCtrls > 0) && (numOfFmanCtrls < 3)) , E_INVALID_HANDLE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcPortNumOfFmanCtrls params;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ params.hardwarePortId = hardwarePortId;
+ params.numOfFmanCtrls = numOfFmanCtrls;
+ params.orFmanCtrl = orFmanCtrl;
+ msg.msgId = FM_SET_NUM_OF_FMAN_CTRL;
+ memcpy(msg.msgBody, &params, sizeof(params));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(params),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ tmpReg = (uint32_t)(hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT);
+
+ /* TODO - maybe to put CTL# according to another criteria */
+ if (numOfFmanCtrls == 2)
+ tmpReg = FPM_PORT_FM_CTL2 | FPM_PORT_FM_CTL1;
+
+ /* order restoration */
+ tmpReg |= (orFmanCtrl << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | orFmanCtrl;
+
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg);
+
+ return E_OK;
+}
+
+t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ uint32_t tmpReg, intFlags;
+ uint8_t hardwarePortId = p_PortParams->hardwarePortId, macId;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_FmIpcPortInInitParams portInParams;
+ t_FmIpcPortOutInitParams portOutParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ portInParams.hardwarePortId = p_PortParams->hardwarePortId;
+ portInParams.enumPortType = (uint32_t)p_PortParams->portType;
+ portInParams.boolIndependentMode= (uint8_t)p_PortParams->independentMode;
+ portInParams.liodnOffset = p_PortParams->liodnOffset;
+ portInParams.numOfTasks = p_PortParams->numOfTasks;
+ portInParams.numOfExtraTasks = p_PortParams->numOfExtraTasks;
+ portInParams.numOfOpenDmas = p_PortParams->numOfOpenDmas;
+ portInParams.numOfExtraOpenDmas = p_PortParams->numOfExtraOpenDmas;
+ portInParams.sizeOfFifo = p_PortParams->sizeOfFifo;
+ portInParams.extraSizeOfFifo = p_PortParams->extraSizeOfFifo;
+ portInParams.deqPipelineDepth = p_PortParams->deqPipelineDepth;
+ portInParams.maxFrameLength = p_PortParams->maxFrameLength;
+ portInParams.liodnBase = p_PortParams->liodnBase;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_SET_PORT_PARAMS;
+ memcpy(msg.msgBody, &portInParams, sizeof(portInParams));
+ replyLength = (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams));
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(portInParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&portOutParams, reply.replyBody, sizeof(t_FmIpcPortOutInitParams));
+
+ p_PortParams->fmMuramPhysBaseAddr.high = portOutParams.ipcPhysAddr.high;
+ p_PortParams->fmMuramPhysBaseAddr.low = portOutParams.ipcPhysAddr.low;
+ p_PortParams->numOfTasks = portOutParams.numOfTasks;
+ p_PortParams->numOfExtraTasks = portOutParams.numOfExtraTasks;
+ p_PortParams->numOfOpenDmas = portOutParams.numOfOpenDmas;
+ p_PortParams->numOfExtraOpenDmas = portOutParams.numOfExtraOpenDmas;
+ p_PortParams->sizeOfFifo = portOutParams.sizeOfFifo;
+ p_PortParams->extraSizeOfFifo = portOutParams.extraSizeOfFifo;
+
+ return (t_Error)(reply.error);
+ }
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ if (p_PortParams->independentMode)
+ {
+ /* set port parameters */
+ p_Fm->independentMode = p_PortParams->independentMode;
+ /* disable dispatch limit */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd, 0);
+ }
+
+ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ {
+ if (p_Fm->hcPortInitialized)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Only one host command port is allowed."));
+ }
+ else
+ p_Fm->hcPortInitialized = TRUE;
+ }
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = p_PortParams->portType;
+
+ err = FmSetNumOfTasks(p_Fm, p_PortParams->hardwarePortId, &p_PortParams->numOfTasks, &p_PortParams->numOfExtraTasks, TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) &&
+ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G))
+ /* for transmit & O/H ports */
+ {
+ uint8_t enqTh;
+ uint8_t deqTh;
+ bool update = FALSE;
+
+ /* update qmi ENQ/DEQ threshold */
+ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums += p_PortParams->deqPipelineDepth;
+ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc);
+ enqTh = (uint8_t)(tmpReg>>8);
+ /* if enqTh is too big, we reduce it to the max value that is still OK */
+ if (enqTh >= (QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums))
+ {
+ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1);
+ tmpReg &= ~QMI_CFG_ENQ_MASK;
+ tmpReg |= ((uint32_t)enqTh << 8);
+ update = TRUE;
+ }
+
+ deqTh = (uint8_t)tmpReg;
+ /* if deqTh is too small, we enlarge it to the min value that is still OK.
+ deqTh may not be larger than 63 (QMI_MAX_NUM_OF_TNUMS-1). */
+ if ((deqTh <= p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums) && (deqTh < QMI_MAX_NUM_OF_TNUMS-1))
+ {
+ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1);
+ tmpReg &= ~QMI_CFG_DEQ_MASK;
+ tmpReg |= (uint32_t)deqTh;
+ update = TRUE;
+ }
+ if (update)
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, tmpReg);
+ }
+
+#ifdef FM_LOW_END_RESTRICTION
+ if ((hardwarePortId==0x1) || (hardwarePortId==0x29))
+ {
+ if (p_Fm->p_FmStateStruct->lowEndRestriction)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("OP #0 cannot work with Tx Port #1."));
+ }
+ else
+ p_Fm->p_FmStateStruct->lowEndRestriction = TRUE;
+ }
+#endif /* FM_LOW_END_RESTRICTION */
+
+ err = FmSetSizeOfFifo(p_Fm,
+ p_PortParams->hardwarePortId,
+ &p_PortParams->sizeOfFifo,
+ &p_PortParams->extraSizeOfFifo,
+ TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = FmSetNumOfOpenDmas(p_Fm,
+ p_PortParams->hardwarePortId,
+ &p_PortParams->numOfOpenDmas,
+ &p_PortParams->numOfExtraOpenDmas,
+ TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], (uint32_t)p_PortParams->liodnOffset);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ tmpReg = (uint32_t)(hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT);
+ if (p_PortParams->independentMode)
+ {
+ if ((p_PortParams->portType==e_FM_PORT_TYPE_RX) || (p_PortParams->portType==e_FM_PORT_TYPE_RX_10G))
+ tmpReg |= (FPM_PORT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) |FPM_PORT_FM_CTL1;
+ else
+ tmpReg |= (FPM_PORT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) |FPM_PORT_FM_CTL2;
+ }
+ else
+ {
+ tmpReg |= (FPM_PORT_FM_CTL2|FPM_PORT_FM_CTL1);
+
+ /* order restoration */
+ if (hardwarePortId%2)
+ tmpReg |= (FPM_PORT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+ else
+ tmpReg |= (FPM_PORT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+ }
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg);
+ }
+
+ /* set LIODN base for this port */
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2]);
+ if (hardwarePortId%2)
+ {
+ tmpReg &= ~FM_LIODN_BASE_MASK;
+ tmpReg |= (uint32_t)p_PortParams->liodnBase;
+ }
+ else
+ {
+ tmpReg &= ~(FM_LIODN_BASE_MASK<< DMA_LIODN_SHIFT);
+ tmpReg |= (uint32_t)p_PortParams->liodnBase << DMA_LIODN_SHIFT;
+ }
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], tmpReg);
+
+ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId);
+
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS);
+ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId])
+ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = p_PortParams->maxFrameLength;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU"));
+ }
+ else
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS);
+ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId])
+ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = p_PortParams->maxFrameLength;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU"));
+ }
+
+ FmGetPhysicalMuramBase(p_Fm, &p_PortParams->fmMuramPhysBaseAddr);
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return E_OK;
+}
+
+void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg, intFlags;
+ uint8_t hardwarePortId = p_PortParams->hardwarePortId;
+ uint8_t numOfTasks, macId;
+ t_Error err;
+ t_FmIpcPortFreeParams portParams;
+ t_FmIpcMsg msg;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ portParams.hardwarePortId = p_PortParams->hardwarePortId;
+ portParams.enumPortType = (uint32_t)p_PortParams->portType;
+ portParams.deqPipelineDepth = p_PortParams->deqPipelineDepth;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_FREE_PORT;
+ memcpy(msg.msgBody, &portParams, sizeof(portParams));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(portParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+
+ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ {
+ ASSERT_COND(p_Fm->hcPortInitialized);
+ p_Fm->hcPortInitialized = FALSE;
+ }
+
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = e_FM_PORT_TYPE_DUMMY;
+
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ /* free numOfTasks */
+ numOfTasks = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1);
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= numOfTasks);
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= numOfTasks;
+
+ /* free numOfOpenDmas */
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >=
+ ((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1);
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -=
+ (((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1);
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg);
+ }
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ /* free sizeOfFifo */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]);
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >=
+ (((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS));
+ p_Fm->p_FmStateStruct->accumulatedFifoSize -=
+ (((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS);
+
+ /* clear registers */
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], 0);
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], 0);
+ /* WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], 0); */
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) &&
+ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G))
+ /* for transmit & O/H ports */
+ {
+ uint8_t enqTh;
+ uint8_t deqTh;
+
+ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc);
+ /* update qmi ENQ/DEQ threshold */
+ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums -= p_PortParams->deqPipelineDepth;
+
+ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller,
+ so we can enlarge enqTh */
+ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1);
+ tmpReg &= ~QMI_CFG_ENQ_MASK;
+ tmpReg |= ((uint32_t)enqTh << QMI_CFG_ENQ_SHIFT);
+
+ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller,
+ so we can reduce deqTh */
+ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1);
+ tmpReg &= ~QMI_CFG_DEQ_MASK;
+ tmpReg |= (uint32_t)deqTh;
+
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, tmpReg);
+ }
+
+ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId);
+
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS);
+ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = 0;
+ }
+ else
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS);
+ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = 0;
+ }
+
+#ifdef FM_LOW_END_RESTRICTION
+ if ((hardwarePortId==0x1) || (hardwarePortId==0x29))
+ p_Fm->p_FmStateStruct->lowEndRestriction = FALSE;
+#endif /* FM_LOW_END_RESTRICTION */
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+}
+
+t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_IS_PORT_STALLED;
+ msg.msgBody[0] = hardwarePortId;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(hardwarePortId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ *p_IsStalled = (bool)!!(*(uint8_t*)(reply.replyBody));
+
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId]);
+ *p_IsStalled = (bool)!!(tmpReg & FPM_PS_STALLED);
+
+ return E_OK;
+}
+
+t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+ t_Error err;
+ bool isStalled;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_RESUME_STALLED_PORT;
+ msg.msgBody[0] = hardwarePortId;
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(hardwarePortId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not available for this FM revision!"));
+
+ /* Get port status */
+ err = FmIsPortStalled(h_Fm, hardwarePortId, &isStalled);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't get port status"));
+ if (!isStalled)
+ return E_OK;
+
+ tmpReg = (uint32_t)((hardwarePortId << FPM_PORT_FM_CTL_PORTID_SHIFT) | FPM_PRC_REALSE_STALLED);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_prc, tmpReg);
+
+ return E_OK;
+}
+
+t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask;
+
+#ifndef FM_MAC_RESET
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ return E_OK;
+#endif /*(FM_MAC_RESET >= 11)*/
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMacParams macParams;
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ macParams.id = macId;
+ macParams.enumType = (uint32_t)type;
+ msg.msgId = FM_RESET_MAC;
+ memcpy(msg.msgBody, &macParams, sizeof(macParams));
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ /* Get the relevant bit mask */
+ if (type == e_FM_MAC_10G)
+ {
+ switch (macId)
+ {
+ case (0):
+ bitMask = FPM_RSTC_10G0_RESET;
+ break;
+ case (1):
+ bitMask = FPM_RSTC_10G1_RESET;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Illegal MAC Id"));
+ }
+ }
+ else
+ {
+ switch (macId)
+ {
+ case (0):
+ bitMask = FPM_RSTC_1G0_RESET;
+ break;
+ case (1):
+ bitMask = FPM_RSTC_1G1_RESET;
+ break;
+ case (2):
+ bitMask = FPM_RSTC_1G2_RESET;
+ break;
+ case (3):
+ bitMask = FPM_RSTC_1G3_RESET;
+ break;
+ case (4):
+ bitMask = FPM_RSTC_1G4_RESET;
+ break;
+ case (5):
+ bitMask = FPM_RSTC_1G5_RESET;
+ break;
+ case (6):
+ bitMask = FPM_RSTC_1G6_RESET;
+ break;
+ case (7):
+ bitMask = FPM_RSTC_1G7_RESET;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Illegal MAC Id"));
+ }
+ }
+
+ /* reset */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, bitMask);
+
+ return E_OK;
+}
+
+t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMacMaxFrameParams macMaxFrameLengthParams;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ macMaxFrameLengthParams.macParams.id = macId;
+ macMaxFrameLengthParams.macParams.enumType = (uint32_t)type;
+ macMaxFrameLengthParams.maxFrameLength = (uint16_t)mtu;
+ msg.msgId = FM_SET_MAC_MAX_FRAME;
+ memcpy(msg.msgBody, &macMaxFrameLengthParams, sizeof(macMaxFrameLengthParams));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macMaxFrameLengthParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ /* if port is already initialized, check that MaxFrameLength is smaller
+ * or equal to the port's max */
+#if (defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS))
+ if (type == e_FM_MAC_10G)
+ {
+ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId])
+ || (p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] &&
+ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId])))
+ p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId] = mtu;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength"));
+
+ }
+ else
+#else
+ UNUSED(type);
+#endif /* (defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId])
+ || (p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] &&
+ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId])))
+ p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId] = mtu;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength"));
+
+ return E_OK;
+}
+
+uint16_t FmGetClockFreq(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ /* for multicore environment: this depends on the
+ * fact that fmClkFreq was properly initialized at "init". */
+ return p_Fm->p_FmStateStruct->fmClkFreq;
+}
+
+uint32_t FmGetTimeStampScale(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, timeStamp;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_TIMESTAMP_SCALE;
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&timeStamp, reply.replyBody, sizeof(uint32_t));
+ return timeStamp;
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ if (!(GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1) & FPM_TS_CTL_EN))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("timestamp is not enabled!"));
+
+ return p_Fm->p_FmStateStruct->count1MicroBit;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ DBG(WARNING, ("No IPC - can't validate FM if timestamp enabled."));
+
+ return p_Fm->p_FmStateStruct->count1MicroBit;
+}
+
+t_Error FmEnableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ p_Fm->p_FmStateStruct->ramsEccOwners++;
+ p_Fm->p_FmStateStruct->internalCall = TRUE;
+
+ return FM_EnableRamsEcc(p_Fm);
+}
+
+t_Error FmDisableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ ASSERT_COND(p_Fm->p_FmStateStruct->ramsEccOwners);
+ p_Fm->p_FmStateStruct->ramsEccOwners--;
+
+ if (p_Fm->p_FmStateStruct->ramsEccOwners==0)
+ {
+ p_Fm->p_FmStateStruct->internalCall = TRUE;
+ return FM_DisableRamsEcc(p_Fm);
+ }
+
+ return E_OK;
+}
+
+uint8_t FmGetGuestId(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return p_Fm->guestId;
+}
+
+bool FmIsMaster(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return (p_Fm->guestId == NCSW_MASTER_ID);
+}
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+t_Error FmSetSizeOfFifo(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint32_t *p_SizeOfFifo,
+ uint32_t *p_ExtraSizeOfFifo,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_Error err;
+ uint32_t tmpReg = 0, sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo;
+ uint16_t oldVal = 0;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = sizeOfFifo;
+ rsrcParams.extra = extraSizeOfFifo;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_SIZE_OF_FIFO;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No IPC - can't validate FM total-fifo size."));
+
+ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) |
+ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig)
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]);
+ /* read into oldVal the current extra fifo size */
+ oldVal = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT);
+ }
+
+ if (extraSizeOfFifo > oldVal)
+ {
+ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize)
+ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize
+ * must be initialized to 1 buffer per port
+ */
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS;
+
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo);
+ }
+
+ if (!initialConfig)
+ /* read into oldVal the current num of tasks */
+ oldVal = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS);
+
+ /* check that there are enough uncommitted fifo size */
+ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - oldVal + sizeOfFifo) >
+ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested fifo size and extra size exceed total FIFO size."));
+ else
+ {
+ /* update accumulated */
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= oldVal);
+ p_Fm->p_FmStateStruct->accumulatedFifoSize -= oldVal;
+ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo;
+ /* calculate reg */
+ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) |
+ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg);
+ }
+
+ return E_OK;
+}
+
+#else /*FM_NO_GUARANTEED_RESET_VALUES*/
+t_Error FmSetSizeOfFifo(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint32_t *p_SizeOfFifo,
+ uint32_t *p_ExtraSizeOfFifo,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_Error err;
+ uint32_t tmpReg = 0, sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo;
+ uint16_t currentVal, currentExtraVal;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || sizeOfFifo);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = sizeOfFifo;
+ rsrcParams.extra = extraSizeOfFifo;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_SIZE_OF_FIFO;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No IPC - can't validate FM total-fifo size."));
+
+ if (sizeOfFifo)
+ {
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) |
+ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg);
+ }
+ else /* first config without explicit value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]);
+ /* read into oldVal the current extra fifo size */
+ *p_ExtraSizeOfFifo = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT);
+ *p_SizeOfFifo = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS);
+ }
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig || !sizeOfFifo)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * !numOfTasks - first configuration according to values in regs.
+ * In both cases: read the current FIFO size */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1]);
+ /* read into oldVal the current extra fifo size */
+ currentExtraVal = (uint16_t)((((tmpReg & BMI_EXTRA_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS) >> BMI_EXTRA_FIFO_SIZE_SHIFT);
+ currentVal = (uint16_t)(((tmpReg & BMI_FIFO_SIZE_MASK) + 1) * BMI_FIFO_UNITS);
+ }
+ else /* first time and sizeOfFifo explicitly specified */
+ currentVal = currentExtraVal = 0;
+
+ if (!sizeOfFifo)
+ {
+ /* This is the first configuration and user did not specify value (!numOfTasks),
+ * reset values will be used and we just save these values for resource management */
+ if (currentExtraVal)
+ {
+ if (!p_Fm->p_FmStateStruct->extraFifoPoolSize)
+ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize
+ * must be initialized to 1 buffer per port
+ */
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS;
+
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo);
+ }
+ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize + currentVal) >
+ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Total port's fifo size and extra size exceed total available FIFO size."));
+
+ p_Fm->p_FmStateStruct->accumulatedFifoSize += currentVal;
+
+ *p_SizeOfFifo = currentVal;
+ *p_ExtraSizeOfFifo = currentExtraVal;
+
+ }
+ else
+ {
+ /* user requires a specific value.
+ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0",
+ * otherwise they hold the value written in the register.
+ */
+ if (extraSizeOfFifo > currentExtraVal)
+ {
+ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize)
+ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize
+ * must be initialized to 1 buffer per port
+ */
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS;
+
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo);
+ }
+
+ /* check that there are enough uncommitted fifo size */
+ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - currentVal + sizeOfFifo) >
+ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested fifo size and extra size exceed total FIFO size."));
+ else
+ {
+ /* update accumulated */
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= currentVal);
+ p_Fm->p_FmStateStruct->accumulatedFifoSize -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo;
+ /* calculate reg */
+ tmpReg = (uint32_t)((sizeOfFifo/BMI_FIFO_UNITS - 1) |
+ ((extraSizeOfFifo/BMI_FIFO_UNITS) << BMI_EXTRA_FIFO_SIZE_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], tmpReg);
+ }
+ *p_SizeOfFifo = sizeOfFifo;
+ *p_ExtraSizeOfFifo = extraSizeOfFifo;
+
+ }
+
+ return E_OK;
+}
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+t_Error FmSetNumOfTasks(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfTasks,
+ uint8_t *p_NumOfExtraTasks,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err;
+ uint32_t tmpReg = 0;
+ uint8_t oldVal = 0, numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfTasks;
+ rsrcParams.extra = numOfExtraTasks;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_TASKS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No IPC - can't validate FM total-num-of-tasks."));
+
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig)
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ /* read into oldVal the current extra tasks */
+ oldVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+ }
+
+ if (numOfExtraTasks > oldVal)
+ p_Fm->p_FmStateStruct->extraTasksPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks);
+
+ if (!initialConfig)
+ /* read into oldVal the current num of tasks */
+ oldVal = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1);
+
+ /* check that there are enough uncommitted tasks */
+ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - oldVal + numOfTasks) >
+ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.",
+ p_Fm->p_FmStateStruct->fmId));
+ else
+ {
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= oldVal);
+ /* update accumulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= oldVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks;
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg);
+ }
+
+ return E_OK;
+}
+
+#else /*FM_NO_GUARANTEED_RESET_VALUES*/
+t_Error FmSetNumOfTasks(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfTasks,
+ uint8_t *p_NumOfExtraTasks,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err;
+ uint32_t tmpReg = 0;
+ uint8_t currentVal, currentExtraVal,numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || numOfTasks);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfTasks;
+ rsrcParams.extra = numOfExtraTasks;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_TASKS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No Ipc - can't validate FM total-num-of-tasks."));
+
+ if (numOfTasks)
+ {
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg);
+ }
+ else /* first config without explicit value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ *p_NumOfTasks = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1);
+ *p_NumOfExtraTasks = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+ }
+
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig || !numOfTasks)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * !numOfTasks - first configuration according to values in regs.
+ * In both cases: read the current number of tasks */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ currentVal = (uint8_t)(((tmpReg & BMI_NUM_OF_TASKS_MASK) >> BMI_NUM_OF_TASKS_SHIFT) + 1);
+ currentExtraVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_TASKS_MASK) >> BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+ }
+ else /* first time and numOfTasks explicitly specified */
+ currentVal = currentExtraVal = 0;
+
+ if (!numOfTasks)
+ {
+ /* This is the first configuration and user did not specify value (!numOfTasks),
+ * reset values will be used and we just save these values for resource management */
+ p_Fm->p_FmStateStruct->extraTasksPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, currentExtraVal);
+ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks + currentVal) >
+ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Total ports' numOfTasks and extra tasks pool for fm%d exceed total available numOfTasks.",
+ p_Fm->p_FmStateStruct->fmId));
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += currentVal;
+ *p_NumOfTasks = currentVal;
+ *p_NumOfExtraTasks = currentExtraVal;
+ }
+ else
+ {
+ /* user requires a specific value.
+ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0",
+ * otherwise they hold the value written in the register.
+ */
+ if (numOfExtraTasks > currentExtraVal)
+ p_Fm->p_FmStateStruct->extraTasksPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks);
+
+ /* check that there are enough uncommitted tasks */
+ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - currentVal + numOfTasks) >
+ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.",
+ p_Fm->p_FmStateStruct->fmId));
+ else
+ {
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= currentVal);
+ /* update acummulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks;
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmpReg |= (uint32_t)(((numOfTasks-1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (numOfExtraTasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1],tmpReg);
+ }
+ *p_NumOfTasks = numOfTasks;
+ *p_NumOfExtraTasks = numOfExtraTasks;
+ }
+
+ return E_OK;
+}
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+t_Error FmSetNumOfOpenDmas(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfOpenDmas,
+ uint8_t *p_NumOfExtraOpenDmas,
+ bool initialConfig)
+
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t oldVal = 0, numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas;
+ uint32_t tmpReg = 0;
+ t_Error err;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfOpenDmas;
+ rsrcParams.extra = numOfExtraOpenDmas;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+#ifdef FM_HAS_TOTAL_DMAS
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+#else
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6))
+ {
+ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/
+
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ if (!initialConfig)
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ /* read into oldVal the current extra tasks */
+ oldVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+ }
+
+ if (numOfExtraOpenDmas > oldVal)
+ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas);
+
+ if (!initialConfig)
+ /* read into oldVal the current num of tasks */
+ oldVal = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1);
+
+ /* check that there are enough uncommitted open DMA's */
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= oldVal);
+#ifdef FM_HAS_TOTAL_DMAS
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) &&
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - oldVal + numOfOpenDmas >
+ p_Fm->p_FmStateStruct->maxNumOfOpenDmas))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.",
+ p_Fm->p_FmStateStruct->fmId));
+#else
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) &&
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - oldVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)",
+ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1));
+#endif /* FM_HAS_TOTAL_DMAS */
+ else
+ {
+ /* update acummulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= oldVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas;
+
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg);
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg);
+ }
+#endif /* FM_HAS_TOTAL_DMAS */
+ }
+
+
+ return E_OK;
+}
+
+#else /* FM_NO_GUARANTEED_RESET_VALUES */
+t_Error FmSetNumOfOpenDmas(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfOpenDmas,
+ uint8_t *p_NumOfExtraOpenDmas,
+ bool initialConfig)
+
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint32_t tmpReg = 0;
+ t_Error err;
+ uint8_t currentVal, currentExtraVal, numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfOpenDmas;
+ rsrcParams.extra = numOfExtraOpenDmas;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+#ifdef FM_HAS_TOTAL_DMAS
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+#else
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6))
+ {
+ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/
+
+ if (numOfOpenDmas)
+ {
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg);
+ }
+ else /* first config without explicit value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ /* read into oldVal the current extra tasks */
+ *p_NumOfOpenDmas = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+ *p_NumOfExtraOpenDmas = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1);
+ }
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || numOfOpenDmas);
+
+ if (!initialConfig || !numOfOpenDmas)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * !numOfTasks - first configuration according to values in regs.
+ * In both cases: read the current number of open Dma's */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]);
+ /* read into oldVal the current extra tasks */
+ currentExtraVal = (uint8_t)((tmpReg & BMI_NUM_OF_EXTRA_DMAS_MASK) >> BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+ currentVal = (uint8_t)(((tmpReg & BMI_NUM_OF_DMAS_MASK) >> BMI_NUM_OF_DMAS_SHIFT) + 1);
+ }
+ else /* first time and numOfTasks explicitly specified */
+ currentVal = currentExtraVal = 0;
+
+ if (!numOfOpenDmas)
+ {
+ /* This is the first configuration and user did not specify value (!numOfOpenDmas),
+ * reset values will be used and we just save these values for resource management */
+ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, currentExtraVal);
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += currentVal;
+ *p_NumOfOpenDmas = currentVal;
+ *p_NumOfExtraOpenDmas = currentExtraVal;
+ }
+ else
+ {
+ /* user requires a specific value.
+ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0",
+ * otherwise they hold the value written in the register.
+ */
+ if (numOfExtraOpenDmas > currentExtraVal)
+ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas);
+
+
+ /* read into oldVal the current num of tasks */
+#ifdef FM_HAS_TOTAL_DMAS
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) &&
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas >
+ p_Fm->p_FmStateStruct->maxNumOfOpenDmas))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.",
+ p_Fm->p_FmStateStruct->fmId));
+#else
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) &&
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)",
+ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1));
+#endif /* FM_HAS_TOTAL_DMAS */
+ else
+ {
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= currentVal);
+ /* update acummulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas;
+
+ /* calculate reg */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1]) & ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmpReg |= (uint32_t)(((numOfOpenDmas-1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (numOfExtraOpenDmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], tmpReg);
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize - 1) << BMI_CFG2_DMAS_SHIFT;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg);
+ }
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ }
+ *p_NumOfOpenDmas = numOfOpenDmas;
+ *p_NumOfExtraOpenDmas = numOfExtraOpenDmas;
+ }
+
+
+ return E_OK;
+}
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile)
+{
+ t_Fm *p_Fm;
+ t_FmSp *p_FmPcdSp;
+ uint8_t swPortIndex=0, hardwarePortId;
+
+ ASSERT_COND(h_Fm);
+ p_Fm = (t_Fm*)h_Fm;
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ ASSERT_COND(hardwarePortId);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcdSp = p_Fm->p_FmSp;
+ ASSERT_COND(p_FmPcdSp);
+
+ if (!p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Port has no allocated profiles"));
+ if (relativeProfile >= p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE , ("Profile id is out of range"));
+
+ return E_OK;
+}
+
+t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId)
+{
+ t_Fm *p_Fm;
+ t_FmSp *p_FmPcdSp;
+ uint8_t swPortIndex=0, hardwarePortId;
+ t_Error err;
+
+ ASSERT_COND(h_Fm);
+ p_Fm = (t_Fm*)h_Fm;
+
+ err = FmVSPCheckRelativeProfile(h_Fm, portType, portId, relativeProfile);
+ if (err != E_OK)
+ return err;
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ ASSERT_COND(hardwarePortId);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcdSp = p_Fm->p_FmSp;
+ ASSERT_COND(p_FmPcdSp);
+
+ *p_AbsoluteId = (uint16_t)(p_FmPcdSp->portsMapping[swPortIndex].profilesBase + relativeProfile);
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+static t_Error InitFmDma(t_Fm *p_Fm)
+{
+ t_FmDriverParam *p_FmDriverParam = NULL;
+ uint32_t tmpReg;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->p_FmDriverParam);
+
+ p_FmDriverParam = p_Fm->p_FmDriverParam;
+
+ /* clear status reg events */
+#if (DPAA_VERSION >= 11)
+ tmpReg = DMA_STATUS_FM_SPDAT_ECC;
+#else
+ tmpReg = DMA_STATUS_FM_ECC;
+#endif /* DPAA_VERSION >= 11 */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr) | tmpReg);
+
+ /* configure mode register */
+ tmpReg = 0;
+ tmpReg |= p_FmDriverParam->dmaCacheOverride << DMA_MODE_CACHE_OR_SHIFT;
+ if (p_FmDriverParam->dmaAidOverride)
+ tmpReg |= DMA_MODE_AID_OR;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_BUS_ERROR)
+ tmpReg |= DMA_MODE_BER;
+ if (p_FmDriverParam->dmaEnEmergency)
+ {
+ tmpReg |= p_FmDriverParam->dmaEmergency.emergencyBusSelect;
+ tmpReg |= p_FmDriverParam->dmaEmergency.emergencyLevel << DMA_MODE_EMERGENCY_LEVEL_SHIFT;
+ if (p_FmDriverParam->dmaEnEmergencySmoother)
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmemsr, p_FmDriverParam->dmaEmergencySwitchCounter);
+ }
+ tmpReg |= ((p_FmDriverParam->dmaCamNumOfEntries/DMA_CAM_UNITS) - 1) << DMA_MODE_CEN_SHIFT;
+ tmpReg |= p_FmDriverParam->dmaDbgCntMode << DMA_MODE_DBG_SHIFT;
+ tmpReg |= DMA_MODE_SECURE_PROT;
+ tmpReg |= p_FmDriverParam->dmaAidMode << DMA_MODE_AID_MODE_SHIFT;
+
+#if (DPAA_VERSION >= 11)
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_SINGLE_PORT_ECC)
+ tmpReg |= DMA_MODE_ECC;
+#else
+ if ((p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_SYSTEM_WRITE_ECC) | (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_READ_ECC) | (p_Fm->p_FmStateStruct->exceptions & FM_EX_DMA_FM_WRITE_ECC))
+ tmpReg |= DMA_MODE_ECC;
+ if (p_FmDriverParam->dmaStopOnBusError)
+ tmpReg |= DMA_MODE_SBER;
+ tmpReg |= (uint32_t)(p_FmDriverParam->dmaAxiDbgNumOfBeats - 1) << DMA_MODE_AXI_DBG_SHIFT;
+#ifdef FM_PEDANTIC_DMA
+ tmpReg |= DMA_MODE_EMERGENCY_READ;
+#endif /* FM_PEDANTIC_DMA */
+#endif /* DPAA_VERSION >= 11 */
+
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg);
+
+ /* configure thresholds register */
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtr);
+ tmpReg |= ((uint32_t)p_FmDriverParam->dmaCommQThresholds.assertEmergency << DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)p_FmDriverParam->dmaReadBufThresholds.assertEmergency << DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)p_FmDriverParam->dmaWriteBufThresholds.assertEmergency);
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmtr, tmpReg);
+
+ /* configure hysteresis register */
+ tmpReg = ((uint32_t)p_FmDriverParam->dmaCommQThresholds.clearEmergency << DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)p_FmDriverParam->dmaReadBufThresholds.clearEmergency << DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)p_FmDriverParam->dmaWriteBufThresholds.clearEmergency);
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmhy, tmpReg);
+
+ /* configure emergency threshold */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmsetr, p_FmDriverParam->dmaSosEmergency);
+
+ /* configure Watchdog */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmwcr, USEC_TO_CLK(p_FmDriverParam->dmaWatchdog, p_Fm->p_FmStateStruct->fmClkFreq));
+
+ /* Allocate MURAM for CAM */
+ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*DMA_CAM_SIZEOF_ENTRY),
+ DMA_CAM_ALIGN));
+ if (!p_Fm->camBaseAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr),
+ 0,
+ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*DMA_CAM_SIZEOF_ENTRY));
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 2)
+ {
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr));
+
+ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*72 + 128),
+ 64));
+ if (!p_Fm->camBaseAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr),
+ 0,
+ (uint32_t)(p_FmDriverParam->dmaCamNumOfEntries*72 + 128));
+
+ switch (p_FmDriverParam->dmaCamNumOfEntries)
+ {
+ case (8):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xff000000);
+ break;
+ case (16):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffff0000);
+ break;
+ case (24):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffff00);
+ break;
+ case (32):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffffff);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("wrong dmaCamNumOfEntries"));
+ }
+ }
+
+ /* VirtToPhys */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmebcr,
+ (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->camBaseAddr)) - p_Fm->fmMuramPhysBaseAddr));
+
+ return E_OK;
+}
+
+static t_Error InitFmFpm(t_Fm *p_Fm)
+{
+ t_FmDriverParam *p_FmDriverParam = NULL;
+ uint32_t tmpReg;
+ int i;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->p_FmDriverParam);
+
+ p_FmDriverParam = p_Fm->p_FmDriverParam;
+
+ tmpReg = (uint32_t)(p_FmDriverParam->thresholds.dispLimit << FPM_DISP_LIMIT_SHIFT);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd, tmpReg);
+
+ tmpReg = (((uint32_t)p_FmDriverParam->thresholds.prsDispTh << FPM_THR1_PRS_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.kgDispTh << FPM_THR1_KG_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.plcrDispTh << FPM_THR1_PLCR_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.bmiDispTh << FPM_THR1_BMI_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis1, tmpReg);
+
+ tmpReg = (((uint32_t)p_FmDriverParam->thresholds.qmiEnqDispTh << FPM_THR2_QMI_ENQ_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.qmiDeqDispTh << FPM_THR2_QMI_DEQ_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.fmCtl1DispTh << FPM_THR2_FM_CTL1_SHIFT) |
+ ((uint32_t)p_FmDriverParam->thresholds.fmCtl2DispTh << FPM_THR2_FM_CTL2_SHIFT));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis2, tmpReg);
+
+ /* define exceptions and error behavior */
+ tmpReg = 0;
+ /* Clear events */
+ tmpReg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_SINGLE_ECC);
+ /* enable interrupts */
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_STALL_ON_TASKS)
+ tmpReg |= FPM_EV_MASK_STALL_EN;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_SINGLE_ECC)
+ tmpReg |= FPM_EV_MASK_SINGLE_ECC_EN;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_FPM_DOUBLE_ECC)
+ tmpReg |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ tmpReg |= (p_Fm->p_FmDriverParam->catastrophicErr << FPM_EV_MASK_CAT_ERR_SHIFT);
+ tmpReg |= (p_Fm->p_FmDriverParam->dmaErr << FPM_EV_MASK_DMA_ERR_SHIFT);
+ if (!p_Fm->p_FmDriverParam->haltOnExternalActivation)
+ tmpReg |= FPM_EV_MASK_EXTERNAL_HALT;
+ if (!p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError)
+ tmpReg |= FPM_EV_MASK_ECC_ERR_HALT;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg);
+
+ /* clear all fmCtls event registers */
+ for (i=0;i<FM_NUM_OF_FMAN_CTRL_EVENT_REGS;i++)
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[i], 0xFFFFFFFF);
+
+ /* RAM ECC - enable and clear events */
+ /* first we need to clear all parser memory, as it is uninitialized and
+ may cause ECC errors
+ */
+ tmpReg = 0;
+ /* event bits */
+ tmpReg = (FPM_RAM_CTL_MURAM_ECC | FPM_RAM_CTL_IRAM_ECC);
+ /* Rams enable is not effected by the RCR bit, but by a COP configuration */
+ if (p_Fm->p_FmDriverParam->externalEccRamsEnable)
+ tmpReg |= FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL;
+
+ /* enable test mode */
+ if (p_FmDriverParam->enMuramTestMode)
+ tmpReg |= FPM_RAM_CTL_MURAM_TEST_ECC;
+ if (p_FmDriverParam->enIramTestMode)
+ tmpReg |= FPM_RAM_CTL_IRAM_TEST_ECC;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg);
+
+ tmpReg = 0;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_IRAM_ECC)
+ {
+ tmpReg |= FPM_IRAM_ECC_ERR_EX_EN;
+ FmEnableRamsEcc(p_Fm);
+ }
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_MURAM_ECC)
+ {
+ tmpReg |= FPM_MURAM_ECC_ERR_EX_EN;
+ FmEnableRamsEcc(p_Fm);
+ }
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg);
+
+ return E_OK;
+}
+
+static t_Error InitFmBmi(t_Fm *p_Fm)
+{
+ uint32_t tmpReg;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->p_FmDriverParam);
+
+ tmpReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->fifoBaseAddr)) - p_Fm->fmMuramPhysBaseAddr);
+ tmpReg = tmpReg / BMI_FIFO_ALIGN;
+
+ tmpReg |= ((p_Fm->p_FmStateStruct->totalFifoSize/BMI_FIFO_UNITS - 1) << BMI_CFG1_FIFO_SIZE_SHIFT);
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg1, tmpReg);
+
+ tmpReg = ((uint32_t)(p_Fm->p_FmStateStruct->totalNumOfTasks - 1) << BMI_CFG2_TASKS_SHIFT);
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ tmpReg |= (uint32_t)(p_Fm->p_FmStateStruct->maxNumOfOpenDmas - 1) << BMI_CFG2_DMAS_SHIFT;
+#endif /* FM_HAS_TOTAL_DMAS */
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg);
+
+ /* define unmaskable exceptions, enable and clear events */
+ tmpReg = 0;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ievr, (BMI_ERR_INTR_EN_LIST_RAM_ECC |
+ BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC |
+ BMI_ERR_INTR_EN_STATISTICS_RAM_ECC |
+ BMI_ERR_INTR_EN_DISPATCH_RAM_ECC));
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC)
+ tmpReg |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC)
+ tmpReg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC)
+ tmpReg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC)
+ tmpReg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg);
+
+ return E_OK;
+}
+
+static t_Error InitFmQmi(t_Fm *p_Fm)
+{
+ uint32_t tmpReg;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->p_FmDriverParam);
+
+ /* Clear error interrupt events */
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eie, (QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF));
+ tmpReg = 0;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)
+ tmpReg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC)
+ tmpReg |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ /* enable events */
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg);
+
+ if (p_Fm->p_FmDriverParam->tnumAgingPeriod)
+ {
+ uint16_t periodInFmClocks;
+ uint8_t remainder;
+
+ /* tnumAgingPeriod is in units of microseconds, p_FmClockFreq is in Mhz */
+ periodInFmClocks = (uint16_t)(p_Fm->p_FmDriverParam->tnumAgingPeriod*p_Fm->p_FmStateStruct->fmClkFreq);
+ /* periodInFmClocks must be a 64 multiply */
+ remainder = (uint8_t)(periodInFmClocks % 64);
+ if (remainder > 64)
+ tmpReg = (uint32_t)((periodInFmClocks/64) + 1);
+ else
+ {
+ tmpReg = (uint32_t)(periodInFmClocks/64);
+ if (!tmpReg)
+ tmpReg = 1;
+ }
+ tmpReg <<= QMI_TAPC_TAP;
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_tapc, tmpReg);
+
+ }
+
+ tmpReg = 0;
+ /* Clear interrupt events */
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ {
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ie, QMI_INTR_EN_SINGLE_ECC);
+ if (p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC)
+ tmpReg |= QMI_INTR_EN_SINGLE_ECC;
+ /* enable events */
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien, tmpReg);
+ }
+
+ return E_OK;
+}
+
+static t_Error InitGuestMode(t_Fm *p_Fm)
+{
+ t_Error err = E_OK;
+ int i;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID);
+
+ /* build the FM guest partition IPC address */
+ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, p_Fm->guestId) != (p_Fm->guestId<10 ? 6:7))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ /* build the FM master partition IPC address */
+ memset(p_Fm->fmIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_Fm->fmIpcHandlerModuleName[0], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ for (i=0;i<e_FM_EV_DUMMY_LAST;i++)
+ p_Fm->intrMng[i].f_Isr = UnimplementedIsr;
+
+ p_Fm->h_IpcSessions[0] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[0], p_Fm->fmModuleName);
+ if (p_Fm->h_IpcSessions[0])
+ {
+ uint8_t isMasterAlive;
+ t_FmIpcParams ipcParams;
+
+ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmGuestHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_MASTER_IS_ALIVE;
+ msg.msgBody[0] = p_Fm->guestId;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ do
+ {
+ blockingFlag = TRUE;
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(p_Fm->guestId),
+ (uint8_t*)&reply,
+ &replyLength,
+ IpcMsgCompletionCB,
+ p_Fm)) != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ while (blockingFlag) ;
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ isMasterAlive = *(uint8_t*)(reply.replyBody);
+ } while (!isMasterAlive);
+
+ /* read FM parameters and save */
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_PARAMS;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcParams)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&ipcParams, reply.replyBody, sizeof(t_FmIpcParams));
+
+ p_Fm->p_FmStateStruct->fmClkFreq = ipcParams.fmClkFreq;
+ p_Fm->p_FmStateStruct->revInfo.majorRev = ipcParams.majorRev;
+ p_Fm->p_FmStateStruct->revInfo.minorRev = ipcParams.minorRev;
+ }
+ else
+ {
+ uint32_t tmpReg;
+
+ DBG(WARNING, ("FM Guest mode - without IPC"));
+ if (!p_Fm->p_FmStateStruct->fmClkFreq)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No fmClkFreq configured for guest without IPC"));
+ if (p_Fm->baseAddr)
+ {
+ /* read revision register 1 */
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1);
+ p_Fm->p_FmStateStruct->revInfo.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+ p_Fm->p_FmStateStruct->revInfo.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = AllocVSPsForPartition(p_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ DBG(WARNING, ("partition VSPs allocation is FAILED"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* General FM driver initialization */
+ if (p_Fm->baseAddr)
+ p_Fm->fmMuramPhysBaseAddr =
+ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM)));
+
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+
+ if ((p_Fm->guestId == NCSW_MASTER_ID) ||
+ (p_Fm->h_IpcSessions[0]))
+ {
+ FM_DisableRamsEcc(p_Fm);
+ FmMuramClear(p_Fm->h_FmMuram);
+ FM_EnableRamsEcc(p_Fm);
+ }
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FmDumpPortRegs (t_Handle h_Fm, uint8_t hardwarePortId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) ||
+ p_Fm->baseAddr), E_INVALID_OPERATION);
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], ("fmbm_pp for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], ("fmbm_pfs for port %u", (hardwarePortId )));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], ("fmbm_spliodn for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ("fmfp_ps for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], ("fmdmplr for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], sizeof(uint32_t));
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */
+
+
+/*****************************************************************************/
+/* API Init unit functions */
+/*****************************************************************************/
+t_Handle FM_Config(t_FmParams *p_FmParam)
+{
+ t_Fm *p_Fm;
+ uint8_t i;
+ uintptr_t baseAddr;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmParam, E_NULL_POINTER, NULL);
+ SANITY_CHECK_RETURN_VALUE(((p_FmParam->firmware.p_Code && p_FmParam->firmware.size) ||
+ (!p_FmParam->firmware.p_Code && !p_FmParam->firmware.size)),
+ E_INVALID_VALUE, NULL);
+
+ baseAddr = p_FmParam->baseAddr;
+
+ /* Allocate FM structure */
+ p_Fm = (t_Fm *) XX_Malloc(sizeof(t_Fm));
+ if (!p_Fm)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver structure"));
+ return NULL;
+ }
+ memset(p_Fm, 0, sizeof(t_Fm));
+
+ p_Fm->p_FmStateStruct = (t_FmStateStruct *) XX_Malloc(sizeof(t_FmStateStruct));
+ if (!p_Fm->p_FmStateStruct)
+ {
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Status structure"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmStateStruct, 0, sizeof(t_FmStateStruct));
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId;
+ p_Fm->guestId = p_FmParam->guestId;
+
+ for (i=0; i<FM_MAX_NUM_OF_HW_PORT_IDS; i++)
+ p_Fm->p_FmStateStruct->portsTypes[i] = e_FM_PORT_TYPE_DUMMY;
+
+ /* Allocate the FM driver's parameters structure */
+ p_Fm->p_FmDriverParam = (t_FmDriverParam *)XX_Malloc(sizeof(t_FmDriverParam));
+ if (!p_Fm->p_FmDriverParam)
+ {
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver parameters"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmDriverParam, 0, sizeof(t_FmDriverParam));
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->p_FmSp = (t_FmSp *)XX_Malloc(sizeof(t_FmSp));
+ if (!p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("allocation for internal data structure failed"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmSp, 0, sizeof(t_FmSp));
+
+ for (i=0; i<FM_VSP_MAX_NUM_OF_ENTRIES; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId;
+ p_Fm->h_FmMuram = p_FmParam->h_FmMuram;
+ p_Fm->h_App = p_FmParam->h_App;
+ p_Fm->p_FmStateStruct->fmClkFreq = p_FmParam->fmClkFreq;
+ p_Fm->f_Exception = p_FmParam->f_Exception;
+ p_Fm->f_BusError = p_FmParam->f_BusError;
+ p_Fm->p_FmFpmRegs = (t_FmFpmRegs *)UINT_TO_PTR(baseAddr + FM_MM_FPM);
+ p_Fm->p_FmBmiRegs = (t_FmBmiRegs *)UINT_TO_PTR(baseAddr + FM_MM_BMI);
+ p_Fm->p_FmQmiRegs = (t_FmQmiRegs *)UINT_TO_PTR(baseAddr + FM_MM_QMI);
+ p_Fm->p_FmDmaRegs = (t_FmDmaRegs *)UINT_TO_PTR(baseAddr + FM_MM_DMA);
+ p_Fm->baseAddr = baseAddr;
+ p_Fm->p_FmStateStruct->irq = p_FmParam->irq;
+ p_Fm->p_FmStateStruct->errIrq = p_FmParam->errIrq;
+ p_Fm->hcPortInitialized = FALSE;
+ p_Fm->independentMode = FALSE;
+
+ p_Fm->h_Spinlock = XX_InitSpinlock();
+ if (!p_Fm->h_Spinlock)
+ {
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("cant allocate spinlock!"));
+ return NULL;
+ }
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = p_FmParam->partVSPBase;
+ p_Fm->partNumOfVSPs = p_FmParam->partNumOfVSPs;
+ p_Fm->vspBaseAddr = p_FmParam->vspBaseAddr;
+#endif /* (DPAA_VERSION >= 11) */
+
+
+
+ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE;
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = 0;
+ p_Fm->p_FmStateStruct->exceptions = DEFAULT_exceptions;
+ /*p_Fm->p_FmDriverParam->numOfPartitions = p_FmParam->numOfPartitions; */
+ p_Fm->p_FmDriverParam->tnumAgingPeriod = 0;
+ p_Fm->p_FmDriverParam->resetOnInit = DEFAULT_resetOnInit;
+
+ p_Fm->p_FmDriverParam->catastrophicErr = DEFAULT_catastrophicErr;
+ p_Fm->p_FmDriverParam->dmaErr = DEFAULT_dmaErr;
+ p_Fm->p_FmDriverParam->haltOnExternalActivation = DEFAULT_haltOnExternalActivation;
+ p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError = DEFAULT_haltOnUnrecoverableEccError;
+ p_Fm->p_FmDriverParam->enIramTestMode = FALSE;
+ p_Fm->p_FmDriverParam->enMuramTestMode = FALSE;
+ p_Fm->p_FmDriverParam->externalEccRamsEnable = DEFAULT_externalEccRamsEnable;
+
+ p_Fm->p_FmDriverParam->fwVerify = DEFAULT_VerifyUcode;
+ p_Fm->p_FmDriverParam->firmware.size = p_FmParam->firmware.size;
+ if (p_Fm->p_FmDriverParam->firmware.size)
+ {
+ p_Fm->p_FmDriverParam->firmware.p_Code = (uint32_t *)XX_Malloc(p_Fm->p_FmDriverParam->firmware.size);
+ if (!p_Fm->p_FmDriverParam->firmware.p_Code)
+ {
+ XX_FreeSpinlock(p_Fm->h_Spinlock);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM firmware code"));
+ return NULL;
+ }
+ memcpy(p_Fm->p_FmDriverParam->firmware.p_Code, p_FmParam->firmware.p_Code ,p_Fm->p_FmDriverParam->firmware.size);
+ }
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ return p_Fm;
+
+ /* read revision register 1 */
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_ip_rev_1);
+ p_Fm->p_FmStateStruct->revInfo.majorRev = (uint8_t)((tmpReg & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+ p_Fm->p_FmStateStruct->revInfo.minorRev = (uint8_t)((tmpReg & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+ /* Chip dependent, will be configured in Init */
+
+ p_Fm->p_FmDriverParam->dmaAidOverride = DEFAULT_aidOverride;
+ p_Fm->p_FmDriverParam->dmaAidMode = DEFAULT_aidMode;
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ p_Fm->p_FmDriverParam->dmaAidMode = e_FM_DMA_AID_OUT_PORT_ID;
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+
+ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ p_Fm->p_FmStateStruct->totalFifoSize = 0;
+ p_Fm->p_FmStateStruct->totalNumOfTasks = BMI_MAX_NUM_OF_TASKS;
+ p_Fm->p_FmStateStruct->maxNumOfOpenDmas = BMI_MAX_NUM_OF_DMAS;
+ p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency = DEFAULT_dmaCommQLow;
+ p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency = DEFAULT_dmaCommQHigh;
+ p_Fm->p_FmDriverParam->dmaReadBufThresholds.clearEmergency = DEFAULT_dmaReadIntBufLow;
+ p_Fm->p_FmDriverParam->dmaReadBufThresholds.assertEmergency = DEFAULT_dmaReadIntBufHigh;
+ p_Fm->p_FmDriverParam->dmaWriteBufThresholds.clearEmergency = DEFAULT_dmaWriteIntBufLow;
+ p_Fm->p_FmDriverParam->dmaWriteBufThresholds.assertEmergency = DEFAULT_dmaWriteIntBufHigh;
+ p_Fm->p_FmDriverParam->dmaCacheOverride = DEFAULT_cacheOverride;
+ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = DEFAULT_dmaCamNumOfEntries;
+ p_Fm->p_FmDriverParam->dmaDbgCntMode = DEFAULT_dmaDbgCntMode;
+ p_Fm->p_FmDriverParam->dmaEnEmergency = FALSE;
+ p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats = DEFAULT_axiDbgNumOfBeats;
+ p_Fm->p_FmDriverParam->dmaSosEmergency = DEFAULT_dmaSosEmergency;
+ p_Fm->p_FmDriverParam->dmaWatchdog = DEFAULT_dmaWatchdog;
+ p_Fm->p_FmDriverParam->thresholds.dispLimit = DEFAULT_dispLimit;
+ p_Fm->p_FmDriverParam->thresholds.prsDispTh = DEFAULT_prsDispTh;
+ p_Fm->p_FmDriverParam->thresholds.plcrDispTh = DEFAULT_plcrDispTh;
+ p_Fm->p_FmDriverParam->thresholds.kgDispTh = DEFAULT_kgDispTh;
+ p_Fm->p_FmDriverParam->thresholds.bmiDispTh = DEFAULT_bmiDispTh;
+ p_Fm->p_FmDriverParam->thresholds.qmiEnqDispTh = DEFAULT_qmiEnqDispTh;
+ p_Fm->p_FmDriverParam->thresholds.qmiDeqDispTh = DEFAULT_qmiDeqDispTh;
+ p_Fm->p_FmDriverParam->thresholds.fmCtl1DispTh = DEFAULT_fmCtl1DispTh;
+ p_Fm->p_FmDriverParam->thresholds.fmCtl2DispTh = DEFAULT_fmCtl2DispTh;
+ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = FALSE;
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ /* read the values from the registers as they are initialized by the HW with
+ * the required values.
+ */
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg1);
+ p_Fm->p_FmStateStruct->totalFifoSize =
+ (((tmpReg & BMI_TOTAL_FIFO_SIZE_MASK) >> BMI_CFG1_FIFO_SIZE_SHIFT) + 1) * BMI_FIFO_UNITS;
+
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+ tmpReg = 0x007B0000;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, tmpReg);
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2);
+ p_Fm->p_FmStateStruct->totalNumOfTasks =
+ (uint8_t)(((tmpReg & BMI_TOTAL_NUM_OF_TASKS_MASK) >> BMI_CFG2_TASKS_SHIFT) + 1);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmtr);
+ p_Fm->p_FmDriverParam->dmaCommQThresholds.assertEmergency =
+ (uint8_t)(tmpReg >> DMA_THRESH_COMMQ_SHIFT);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmhy);
+ p_Fm->p_FmDriverParam->dmaCommQThresholds.clearEmergency =
+ (uint8_t)(tmpReg >> DMA_THRESH_COMMQ_SHIFT);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr);
+ p_Fm->p_FmDriverParam->dmaCacheOverride = (e_FmDmaCacheOverride)((tmpReg & DMA_MODE_CACHE_OR_MASK) >> DMA_MODE_CACHE_OR_SHIFT);
+ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = (uint8_t)((((tmpReg & DMA_MODE_CEN_MASK) >> DMA_MODE_CEN_SHIFT) +1)*DMA_CAM_UNITS);
+ p_Fm->p_FmDriverParam->dmaDbgCntMode = (e_FmDmaDbgCntMode)((tmpReg & DMA_MODE_DBG_MASK) >> DMA_MODE_DBG_SHIFT);
+ p_Fm->p_FmDriverParam->dmaEnEmergency = (bool)((tmpReg & DMA_MODE_EB)? TRUE : FALSE);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_mxd);
+ p_Fm->p_FmDriverParam->thresholds.dispLimit = (uint8_t)((tmpReg & FPM_DISP_LIMIT_MASK) << FPM_DISP_LIMIT_SHIFT);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis1);
+ p_Fm->p_FmDriverParam->thresholds.prsDispTh = (uint8_t)((tmpReg & FPM_THR1_PRS_MASK ) << FPM_THR1_PRS_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.plcrDispTh = (uint8_t)((tmpReg & FPM_THR1_KG_MASK ) << FPM_THR1_KG_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.kgDispTh = (uint8_t)((tmpReg & FPM_THR1_PLCR_MASK ) << FPM_THR1_PLCR_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.bmiDispTh = (uint8_t)((tmpReg & FPM_THR1_BMI_MASK ) << FPM_THR1_BMI_SHIFT);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_dis2);
+ p_Fm->p_FmDriverParam->thresholds.qmiEnqDispTh = (uint8_t)((tmpReg & FPM_THR2_QMI_ENQ_MASK ) << FPM_THR2_QMI_ENQ_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.qmiDeqDispTh = (uint8_t)((tmpReg & FPM_THR2_QMI_DEQ_MASK ) << FPM_THR2_QMI_DEQ_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.fmCtl1DispTh = (uint8_t)((tmpReg & FPM_THR2_FM_CTL1_MASK ) << FPM_THR2_FM_CTL1_SHIFT);
+ p_Fm->p_FmDriverParam->thresholds.fmCtl2DispTh = (uint8_t)((tmpReg & FPM_THR2_FM_CTL2_MASK ) << FPM_THR2_FM_CTL2_SHIFT);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsetr);
+ p_Fm->p_FmDriverParam->dmaSosEmergency = tmpReg;
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmwcr);
+ p_Fm->p_FmDriverParam->dmaWatchdog = tmpReg/p_Fm->p_FmStateStruct->fmClkFreq;
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmemsr);
+ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = (bool)((tmpReg & DMA_EMSR_EMSTR_MASK)? TRUE : FALSE);
+ p_Fm->p_FmDriverParam->dmaEmergencySwitchCounter = (tmpReg & DMA_EMSR_EMSTR_MASK);
+ }
+
+ return p_Fm;
+}
+
+/**************************************************************************//**
+ @Function FM_Init
+
+ @Description Initializes the FM module
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Init(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmDriverParam *p_FmDriverParam = NULL;
+ t_Error err = E_OK;
+ uint32_t cfgReg = 0;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+
+ p_Fm->p_FmStateStruct->count1MicroBit = FM_TIMESTAMP_1_USEC_BIT;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ return InitGuestMode(p_Fm);
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ /* if user didn't configured totalFifoSize - (totalFifoSize=0) we configure default
+ * according to chip. otherwise, we use user's configuration.
+ */
+ if (p_Fm->p_FmStateStruct->totalFifoSize == 0)
+ p_Fm->p_FmStateStruct->totalFifoSize = DEFAULT_totalFifoSize(p_Fm->p_FmStateStruct->revInfo.majorRev);
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+ CHECK_INIT_PARAMETERS(p_Fm, CheckFmParameters);
+
+ p_FmDriverParam = p_Fm->p_FmDriverParam;
+
+ /* clear revision-dependent non existing exception */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_BMI_DISPATCH_RAM_ECC;
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4)
+ p_Fm->p_FmStateStruct->exceptions &= ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC);
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_QMI_SINGLE_ECC;
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ FmMuramClear(p_Fm->h_FmMuram);
+
+ /* clear CPG */
+ IOMemSet32(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_CGP), 0, FM_PORT_NUM_OF_CONGESTION_GRPS);
+
+ /* add to the default exceptions the user's definitions */
+ p_Fm->p_FmStateStruct->exceptions |= p_FmDriverParam->userSetExceptions;
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ if (p_FmDriverParam->resetOnInit)
+ {
+ if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else
+ {
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+ /* Reset the FM if required. */
+ if (p_FmDriverParam->resetOnInit)
+ {
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+
+ if (GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY)
+ {
+ uint32_t tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ /* clear tmpReg event bits in order not to clear standing events */
+ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ }
+ }
+
+ /*************************************/
+ /* Load FMan-Controller code to IRAM */
+ /*************************************/
+ if (ClearIRam(p_Fm) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ if (p_Fm->p_FmDriverParam->firmware.p_Code &&
+ (LoadFmanCtrlCode(p_Fm) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ }
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+#ifdef FM_CAPWAP_SUPPORT
+ /* save first 256 byte in MURAM */
+ p_Fm->resAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, 256, 0));
+ if (!p_Fm->resAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for reserved Area failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->resAddr), 0, 256);
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = AllocVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ DBG(WARNING, ("partition VSPs allocation is FAILED"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* General FM driver initialization */
+ p_Fm->fmMuramPhysBaseAddr =
+ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM)));
+
+ for (i=0;i<e_FM_EV_DUMMY_LAST;i++)
+ p_Fm->intrMng[i].f_Isr = UnimplementedIsr;
+ for (i=0;i<FM_NUM_OF_FMAN_CTRL_EVENT_REGS;i++)
+ p_Fm->fmanCtrlIntr[i].f_Isr = UnimplementedFmanCtrlIsr;
+
+ /**********************/
+ /* Init DMA Registers */
+ /**********************/
+ err = InitFmDma(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /**********************/
+ /* Init FPM Registers */
+ /**********************/
+ err = InitFmFpm(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* define common resources */
+ /* allocate MURAM for FIFO according to total size */
+ p_Fm->fifoBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ p_Fm->p_FmStateStruct->totalFifoSize,
+ BMI_FIFO_ALIGN));
+ if (!p_Fm->fifoBaseAddr)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for BMI FIFO failed"));
+ }
+
+ /**********************/
+ /* Init BMI Registers */
+ /**********************/
+ err = InitFmBmi(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /**********************/
+ /* Init QMI Registers */
+ /**********************/
+ err = InitFmQmi(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* build the FM master partition IPC address */
+ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ }
+
+ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE);
+ if (err)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* Register the FM interrupts handlers */
+ if (p_Fm->p_FmStateStruct->irq != NO_IRQ)
+ {
+ XX_SetIntr(p_Fm->p_FmStateStruct->irq, FM_EventIsr, p_Fm);
+ XX_EnableIntr(p_Fm->p_FmStateStruct->irq);
+ }
+
+ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ)
+ {
+ XX_SetIntr(p_Fm->p_FmStateStruct->errIrq, (void (*) (t_Handle))FM_ErrorIsr, p_Fm);
+ XX_EnableIntr(p_Fm->p_FmStateStruct->errIrq);
+ }
+
+ /**********************/
+ /* Enable all modules */
+ /**********************/
+ /* clear & enable global counters - calculate reg and save for later,
+ because it's the same reg for QMI enable */
+ cfgReg = QMI_CFG_EN_COUNTERS;
+#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+ cfgReg |= (uint32_t)(((QMI_DEF_TNUMS_THRESH) << 8) | (uint32_t)QMI_DEF_TNUMS_THRESH);
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_init, BMI_INIT_START);
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, cfgReg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN);
+
+ EnableTimeStamp(p_Fm);
+
+ if (p_Fm->p_FmDriverParam->firmware.p_Code)
+ {
+ XX_Free(p_Fm->p_FmDriverParam->firmware.p_Code);
+ p_Fm->p_FmDriverParam->firmware.p_Code = NULL;
+ }
+
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+
+ return E_OK;
+}
+
+/**************************************************************************//**
+ @Function FM_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Free(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+#if (DPAA_VERSION >= 11)
+ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+
+ if (p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmSp);
+ p_Fm->p_FmSp = NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->fmModuleName)
+ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName);
+
+ if (!p_Fm->recoveryMode)
+ XX_Free(p_Fm->p_FmStateStruct);
+
+ XX_Free(p_Fm);
+
+ return E_OK;
+ }
+
+ /* disable BMI and QMI */
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_init, 0);
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc, 0);
+
+ if ((p_Fm->guestId == NCSW_MASTER_ID) && (p_Fm->fmModuleName[0] != 0))
+ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName);
+
+ if (p_Fm->p_FmStateStruct)
+ {
+ if (p_Fm->p_FmStateStruct->irq != NO_IRQ)
+ {
+ XX_DisableIntr(p_Fm->p_FmStateStruct->irq);
+ XX_FreeIntr(p_Fm->p_FmStateStruct->irq);
+ }
+ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ)
+ {
+ XX_DisableIntr(p_Fm->p_FmStateStruct->errIrq);
+ XX_FreeIntr(p_Fm->p_FmStateStruct->errIrq);
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+
+ if (p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmSp);
+ p_Fm->p_FmSp = NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->h_Spinlock)
+ XX_FreeSpinlock(p_Fm->h_Spinlock);
+
+ if (p_Fm->p_FmDriverParam)
+ {
+ if (p_Fm->p_FmDriverParam->firmware.p_Code)
+ XX_Free(p_Fm->p_FmDriverParam->firmware.p_Code);
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+ }
+
+ FreeInitResources(p_Fm);
+
+ if (!p_Fm->recoveryMode && p_Fm->p_FmStateStruct)
+ XX_Free(p_Fm->p_FmStateStruct);
+
+ XX_Free(p_Fm);
+
+ return E_OK;
+}
+
+/*************************************************/
+/* API Advanced Init unit functions */
+/*************************************************/
+
+t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable)
+{
+
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->resetOnInit = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmStateStruct->totalFifoSize = totalFifoSize;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaCacheOverride = cacheOverride;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaAidOverride = aidOverride;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaAidMode = aidMode;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif
+ p_Fm->p_FmDriverParam->dmaAxiDbgNumOfBeats = axiDbgNumOfBeats;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaCamNumOfEntries = numOfEntries;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaDbgCntMode = fmDmaDbgCntMode;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaStopOnBusError = stop;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaEnEmergency = TRUE;
+ memcpy(&p_Fm->p_FmDriverParam->dmaEmergency, p_Emergency, sizeof(t_FmDmaEmergency));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaEnEmergencySmoother = TRUE;
+ p_Fm->p_FmDriverParam->dmaEmergencySwitchCounter = emergencyCnt;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaErr = dmaErr;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->catastrophicErr = catastrophicErr;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->enMuramTestMode = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE );
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->enIramTestMode = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->haltOnExternalActivation = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->haltOnUnrecoverableEccError = enable;
+ return E_OK;
+}
+
+t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Fm->p_FmDriverParam->userSetExceptions |= bitMask;
+ else
+ p_Fm->p_FmStateStruct->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->externalEccRamsEnable = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->tnumAgingPeriod = tnumAgingPeriod;
+
+ return E_OK;
+}
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ memcpy(&p_Fm->p_FmDriverParam->thresholds, p_FmThresholds, sizeof(t_FmThresholds));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaSosEmergency = dmaSosEmergency;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif
+ memcpy(&p_Fm->p_FmDriverParam->dmaWriteBufThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ memcpy(&p_Fm->p_FmDriverParam->dmaCommQThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif
+ memcpy(&p_Fm->p_FmDriverParam->dmaReadBufThresholds, p_FmDmaThresholds, sizeof(t_FmDmaThresholds));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchdogValue)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dmaWatchdog = watchdogValue;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableCounters(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+UNUSED(p_Fm);
+
+ return E_OK;
+}
+
+/****************************************************/
+/* API Run-time Control uint functions */
+/****************************************************/
+void FM_EventIsr(t_Handle h_Fm)
+{
+#define FM_M_CALL_1G_MAC_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\
+ }
+#define FM_M_CALL_10G_MAC_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\
+ }
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t pending, event;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ /* normal interrupts */
+ pending = GET_UINT32(p_Fm->p_FmFpmRegs->fm_npi);
+ if (!pending)
+ return;
+
+ if (pending & INTR_EN_QMI)
+ QmiEvent(p_Fm);
+ if (pending & INTR_EN_PRS)
+ p_Fm->intrMng[e_FM_EV_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_PRS].h_SrcHandle);
+ if (pending & INTR_EN_PLCR)
+ p_Fm->intrMng[e_FM_EV_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_PLCR].h_SrcHandle);
+ if (pending & INTR_EN_TMR)
+ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & INTR_EN_1G_MAC0)
+ FM_M_CALL_1G_MAC_ISR(0);
+ if (pending & INTR_EN_1G_MAC1)
+ FM_M_CALL_1G_MAC_ISR(1);
+ if (pending & INTR_EN_1G_MAC2)
+ FM_M_CALL_1G_MAC_ISR(2);
+ if (pending & INTR_EN_1G_MAC3)
+ FM_M_CALL_1G_MAC_ISR(3);
+ if (pending & INTR_EN_1G_MAC4)
+ FM_M_CALL_1G_MAC_ISR(4);
+ if (pending & INTR_EN_1G_MAC5)
+ FM_M_CALL_1G_MAC_ISR(5);
+ if (pending & INTR_EN_1G_MAC6)
+ FM_M_CALL_1G_MAC_ISR(6);
+ if (pending & INTR_EN_1G_MAC7)
+ FM_M_CALL_1G_MAC_ISR(7);
+ if (pending & INTR_EN_10G_MAC0)
+ FM_M_CALL_10G_MAC_ISR(0);
+ if (pending & INTR_EN_10G_MAC1)
+ FM_M_CALL_10G_MAC_ISR(1);
+
+ /* IM port events may belong to different partitions */
+ if (pending & INTR_EN_REV0)
+ {
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[0]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[0]);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[0], event);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_0].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_0, pending); */
+ else
+ p_Fm->fmanCtrlIntr[0].f_Isr(p_Fm->fmanCtrlIntr[0].h_SrcHandle, event);
+
+ }
+ if (pending & INTR_EN_REV1)
+ {
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[1]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[1]);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[1], event);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_1].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_1, pending); */
+ else
+ p_Fm->fmanCtrlIntr[1].f_Isr(p_Fm->fmanCtrlIntr[1].h_SrcHandle, event);
+ }
+ if (pending & INTR_EN_REV2)
+ {
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[2]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[2]);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[2], event);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_2].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pending); */
+ else
+ p_Fm->fmanCtrlIntr[2].f_Isr(p_Fm->fmanCtrlIntr[2].h_SrcHandle, event);
+ }
+ if (pending & INTR_EN_REV3)
+ {
+ event = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_fcev[3]) & GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_cee[3]);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_cev[3], event);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_3].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pendin3); */
+ else
+ p_Fm->fmanCtrlIntr[3].f_Isr(p_Fm->fmanCtrlIntr[3].h_SrcHandle, event);
+ }
+#ifdef FM_MACSEC_SUPPORT
+ if (pending & INTR_EN_MACSEC_MAC0)
+ {
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].guestId)
+ SendIpcIsr(p_Fm, e_FM_EV_MACSEC_MAC0, pending);
+ else
+ p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].h_SrcHandle);
+ }
+#endif /* FM_MACSEC_SUPPORT */
+}
+
+t_Error FM_ErrorIsr(t_Handle h_Fm)
+{
+#define FM_M_CALL_1G_MAC_ERR_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\
+ }
+#define FM_M_CALL_10G_MAC_ERR_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\
+ }
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t pending;
+
+ SANITY_CHECK_RETURN_ERROR(h_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ /* error interrupts */
+ pending = GET_UINT32(p_Fm->p_FmFpmRegs->fm_epi);
+ if (!pending)
+ return ERROR_CODE(E_EMPTY);
+
+ if (pending & ERR_INTR_EN_BMI)
+ BmiErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_QMI)
+ QmiErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_FPM)
+ FpmErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_DMA)
+ DmaErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_IRAM)
+ IramErrIntr(p_Fm);
+ if (pending & ERR_INTR_EN_MURAM)
+ MuramErrIntr(p_Fm);
+ if (pending & ERR_INTR_EN_PRS)
+ p_Fm->intrMng[e_FM_EV_ERR_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PRS].h_SrcHandle);
+ if (pending & ERR_INTR_EN_PLCR)
+ p_Fm->intrMng[e_FM_EV_ERR_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PLCR].h_SrcHandle);
+ if (pending & ERR_INTR_EN_KG)
+ p_Fm->intrMng[e_FM_EV_ERR_KG].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_KG].h_SrcHandle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & ERR_INTR_EN_1G_MAC0)
+ FM_M_CALL_1G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_1G_MAC1)
+ FM_M_CALL_1G_MAC_ERR_ISR(1);
+ if (pending & ERR_INTR_EN_1G_MAC2)
+ FM_M_CALL_1G_MAC_ERR_ISR(2);
+ if (pending & ERR_INTR_EN_1G_MAC3)
+ FM_M_CALL_1G_MAC_ERR_ISR(3);
+ if (pending & ERR_INTR_EN_1G_MAC4)
+ FM_M_CALL_1G_MAC_ERR_ISR(4);
+ if (pending & ERR_INTR_EN_1G_MAC5)
+ FM_M_CALL_1G_MAC_ERR_ISR(5);
+ if (pending & ERR_INTR_EN_1G_MAC6)
+ FM_M_CALL_1G_MAC_ERR_ISR(6);
+ if (pending & ERR_INTR_EN_1G_MAC7)
+ FM_M_CALL_1G_MAC_ERR_ISR(7);
+ if (pending & ERR_INTR_EN_10G_MAC0)
+ FM_M_CALL_10G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_10G_MAC1)
+ FM_M_CALL_10G_MAC_ERR_ISR(1);
+
+#ifdef FM_MACSEC_SUPPORT
+ if (pending & ERR_INTR_EN_MACSEC_MAC0)
+ {
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].guestId)
+ SendIpcIsr(p_Fm, e_FM_EV_ERR_MACSEC_MAC0, pending);
+ else
+ p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].h_SrcHandle);
+ }
+#endif /* FM_MACSEC_SUPPORT */
+
+ return E_OK;
+}
+
+t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int i;
+ uint8_t sum;
+ uint8_t hardwarePortId;
+ uint32_t tmpRegs[8] = {0,0,0,0,0,0,0,0};
+ uint8_t relativePortId, shift, weight, maxPercent = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ /* check that all ports add up to 100% */
+ sum = 0;
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ sum +=p_PortsBandwidth->portsBandwidths[i].bandwidth;
+ if (sum != 100)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Sum of ports bandwidth differ from 100%"));
+
+ /* find highest percent */
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ {
+ if (p_PortsBandwidth->portsBandwidths[i].bandwidth > maxPercent)
+ maxPercent = p_PortsBandwidth->portsBandwidths[i].bandwidth;
+ }
+
+ /* calculate weight for each port */
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ {
+ weight = (uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT )/maxPercent);
+ /* we want even division between 1-to-PORT_MAX_WEIGHT. so if exect division
+ is not reached, we round up so that:
+ 0 until maxPercent/PORT_MAX_WEIGHT get "1"
+ maxPercent/PORT_MAX_WEIGHT+1 until (maxPercent/PORT_MAX_WEIGHT)*2 get "2"
+ ...
+ maxPercent - maxPercent/PORT_MAX_WEIGHT until maxPercent get "PORT_MAX_WEIGHT: */
+ if ((uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) % maxPercent))
+ weight++;
+
+ /* find the location of this port within the register */
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId,
+ p_PortsBandwidth->portsBandwidths[i].type,
+ p_PortsBandwidth->portsBandwidths[i].relativePortId);
+ relativePortId = (uint8_t)(hardwarePortId % 8);
+ shift = (uint8_t)(32-4*(relativePortId+1));
+
+
+ if (weight > 1)
+ /* Add this port to tmpReg */
+ /* (each 8 ports result in one register)*/
+ tmpRegs[hardwarePortId/8] |= ((weight-1) << shift);
+ }
+
+ for (i=0;i<8;i++)
+ if (tmpRegs[i])
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_arb[i], tmpRegs[i]);
+
+ return E_OK;
+}
+
+t_Error FM_EnableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ /*SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);*/
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_FmIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_ENABLE_RAM_ECC;
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+
+ if (!p_Fm->p_FmStateStruct->internalCall)
+ p_Fm->p_FmStateStruct->explicitEnable = TRUE;
+ p_Fm->p_FmStateStruct->internalCall = FALSE;
+
+ if (p_Fm->p_FmStateStruct->ramsEccEnable)
+ return E_OK;
+ else
+ {
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr);
+ if (tmpReg & FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL)
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg | FPM_RAM_CTL_IRAM_ECC_EN);
+ else
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg | (FPM_RAM_CTL_RAMS_ECC_EN | FPM_RAM_CTL_IRAM_ECC_EN));
+ p_Fm->p_FmStateStruct->ramsEccEnable = TRUE;
+ }
+
+ return E_OK;
+}
+
+t_Error FM_DisableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+ bool explicitDisable = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ /*SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);*/
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_DISABLE_RAM_ECC;
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+
+ if (!p_Fm->p_FmStateStruct->internalCall)
+ explicitDisable = TRUE;
+ p_Fm->p_FmStateStruct->internalCall = FALSE;
+
+ /* if rams are already disabled, or if rams were explicitly enabled and are
+ currently called indirectly (not explicitly), ignore this call. */
+ if (!p_Fm->p_FmStateStruct->ramsEccEnable ||
+ (p_Fm->p_FmStateStruct->explicitEnable && !explicitDisable))
+ return E_OK;
+ else
+ {
+ if (p_Fm->p_FmStateStruct->explicitEnable)
+ /* This is the case were both explicit are TRUE.
+ Turn off this flag for cases were following ramsEnable
+ routines are called */
+ p_Fm->p_FmStateStruct->explicitEnable = FALSE;
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr);
+ if (tmpReg & FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL)
+ {
+ DBG(WARNING, ("Rams ECC is configured to be controlled through JTAG"));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg & ~FPM_RAM_CTL_IRAM_ECC_EN);
+ }
+ else
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, tmpReg & ~(FPM_RAM_CTL_RAMS_ECC_EN | FPM_RAM_CTL_IRAM_ECC_EN));
+ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE;
+ }
+
+ return E_OK;
+}
+
+t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask = 0;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Fm->p_FmStateStruct->exceptions |= bitMask;
+ else
+ p_Fm->p_FmStateStruct->exceptions &= ~bitMask;
+
+ switch (exception)
+ {
+ case (e_FM_EX_DMA_BUS_ERROR):
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr);
+ if (enable)
+ tmpReg |= DMA_MODE_BER;
+ else
+ tmpReg &= ~DMA_MODE_BER;
+ /* disable bus error */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg);
+ break;
+ case (e_FM_EX_DMA_READ_ECC):
+ case (e_FM_EX_DMA_SYSTEM_WRITE_ECC):
+ case (e_FM_EX_DMA_FM_WRITE_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr);
+ if (enable)
+ tmpReg |= DMA_MODE_ECC;
+ else
+ tmpReg &= ~DMA_MODE_ECC;
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, tmpReg);
+ break;
+ case (e_FM_EX_FPM_STALL_ON_TASKS):
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ if (enable)
+ tmpReg |= FPM_EV_MASK_STALL_EN;
+ else
+ tmpReg &= ~FPM_EV_MASK_STALL_EN;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg);
+ break;
+ case (e_FM_EX_FPM_SINGLE_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ if (enable)
+ tmpReg |= FPM_EV_MASK_SINGLE_ECC_EN;
+ else
+ tmpReg &= ~FPM_EV_MASK_SINGLE_ECC_EN;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg);
+ break;
+ case ( e_FM_EX_FPM_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ if (enable)
+ tmpReg |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ else
+ tmpReg &= ~FPM_EV_MASK_DOUBLE_ECC_EN;
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg);
+ break;
+ case ( e_FM_EX_QMI_SINGLE_ECC):
+#if defined(FM_QMI_NO_ECC_EXCEPTIONS) || defined(FM_QMI_NO_SINGLE_ECC_EXCEPTION)
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 4) ||
+ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6))
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC"));
+ return E_OK;
+ }
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien);
+ if (enable)
+ tmpReg |= QMI_INTR_EN_SINGLE_ECC;
+ else
+ tmpReg &= ~QMI_INTR_EN_SINGLE_ECC;
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_ien, tmpReg);
+ break;
+ case (e_FM_EX_QMI_DOUBLE_ECC):
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_DOUBLE_ECC"));
+ return E_OK;
+ }
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien);
+ if (enable)
+ tmpReg |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ else
+ tmpReg &= ~QMI_ERR_INTR_EN_DOUBLE_ECC;
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg);
+ break;
+ case (e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID):
+ tmpReg = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien);
+ if (enable)
+ tmpReg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ else
+ tmpReg &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eien, tmpReg);
+ break;
+ case (e_FM_EX_BMI_LIST_RAM_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier);
+ if (enable)
+ tmpReg |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ else
+ tmpReg &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg);
+ break;
+ case (e_FM_EX_BMI_STORAGE_PROFILE_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier);
+ if (enable)
+ tmpReg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ else
+ tmpReg &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg);
+ break;
+ case (e_FM_EX_BMI_STATISTICS_RAM_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier);
+ if (enable)
+ tmpReg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ else
+ tmpReg &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg);
+ break;
+ case (e_FM_EX_BMI_DISPATCH_RAM_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier);
+ if (enable)
+ {
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("e_FM_EX_BMI_DISPATCH_RAM_ECC"));
+ return E_OK;
+ }
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+ tmpReg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ }
+ else
+ tmpReg &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ier, tmpReg);
+ break;
+ case (e_FM_EX_IRAM_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie);
+ if (enable)
+ {
+ /* enable ECC if not enabled */
+ FmEnableRamsEcc(p_Fm);
+ /* enable ECC interrupts */
+ tmpReg |= FPM_IRAM_ECC_ERR_EX_EN;
+ }
+ else
+ {
+ /* ECC mechanism may be disabled, depending on driver status */
+ FmDisableRamsEcc(p_Fm);
+ tmpReg &= ~FPM_IRAM_ECC_ERR_EX_EN;
+ }
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg);
+ break;
+
+ case (e_FM_EX_MURAM_ECC):
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rie);
+ if (enable)
+ {
+ /* enable ECC if not enabled */
+ FmEnableRamsEcc(p_Fm);
+ /* enable ECC interrupts */
+ tmpReg |= FPM_MURAM_ECC_ERR_EX_EN;
+ }
+ else
+ {
+ /* ECC mechanism may be disabled, depending on driver status */
+ FmDisableRamsEcc(p_Fm);
+ tmpReg &= ~FPM_MURAM_ECC_ERR_EX_EN;
+ }
+
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rie, tmpReg);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ p_FmRevisionInfo->majorRev = p_Fm->p_FmStateStruct->revInfo.majorRev;
+ p_FmRevisionInfo->minorRev = p_Fm->p_FmStateStruct->revInfo.minorRev;
+
+ return E_OK;
+}
+
+t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FMIramRegs *p_Iram;
+ uint32_t revInfo;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_RevisionInfo, E_NULL_POINTER);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_FMAN_CTRL_CODE_REV;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_FmCtrlCodeRevisionInfo));
+ p_RevisionInfo->packageRev = ipcRevInfo.packageRev;
+ p_RevisionInfo->majorRev = ipcRevInfo.majorRev;
+ p_RevisionInfo->minorRev = ipcRevInfo.minorRev;
+ return (t_Error)(reply.error);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+ WRITE_UINT32(p_Iram->iadd, 0x4);
+ while (GET_UINT32(p_Iram->iadd) != 0x4) ;
+ revInfo = GET_UINT32(p_Iram->idata);
+ p_RevisionInfo->packageRev = (uint16_t)((revInfo & 0xFFFF0000) >> 16);
+ p_RevisionInfo->majorRev = (uint8_t)((revInfo & 0x0000FF00) >> 8);
+ p_RevisionInfo->minorRev = (uint8_t)(revInfo & 0x000000FF);
+
+ return E_OK;
+}
+
+uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ uint32_t counterValue;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, outCounter;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_COUNTER;
+ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(counterValue),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return 0;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return 0;
+ }
+
+ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t));
+ return outCounter;
+ }
+ else if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!"));
+ return 0;
+ }
+
+ /* When applicable (when there is an 'enable counters' bit,
+ check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_COUNTERS_DEQ_1):
+ case (e_FM_COUNTERS_DEQ_2):
+ case (e_FM_COUNTERS_DEQ_3):
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested counter not supported"));
+ return 0;
+ }
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_0):
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (counter)
+ {
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_etfc);
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dtfc);
+ case (e_FM_COUNTERS_DEQ_0):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc0);
+ case (e_FM_COUNTERS_DEQ_1):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc1);
+ case (e_FM_COUNTERS_DEQ_2):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc2);
+ case (e_FM_COUNTERS_DEQ_3):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc3);
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfdc);
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfcc);
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dffc);
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ return GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_dcc);
+ break;
+ }
+ /* should never get here */
+ ASSERT_COND(FALSE);
+ return 0;
+}
+
+t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ /* When applicable (when there is an 'enable counters' bit,
+ check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_COUNTERS_DEQ_1):
+ case (e_FM_COUNTERS_DEQ_2):
+ case (e_FM_COUNTERS_DEQ_3):
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Requested counter not supported"));
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_0):
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ default:
+ break;
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_etfc, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dtfc, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_0):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc0, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_1):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc1, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_2):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc2, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_3):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dc3, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfdc, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dfcc, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dffc, val);
+ break;
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_dcc, val);
+ break;
+ default:
+ break;
+ }
+
+ return E_OK;
+}
+
+void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ bitMask = (uint32_t)((muramPort==e_FM_DMA_MURAM_PORT_WRITE) ? DMA_MODE_EMERGENCY_WRITE : DMA_MODE_EMERGENCY_READ);
+
+ if (enable)
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) | bitMask);
+ else /* disable */
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) & ~bitMask);
+
+ return;
+}
+
+void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ WRITE_UINT32(p_Fm->p_FmDmaRegs->fmdmmr, GET_UINT32(p_Fm->p_FmDmaRegs->fmdmmr) | ((uint32_t)pri << DMA_MODE_BUS_PRI_SHIFT) );
+
+ return;
+}
+
+void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcDmaStatus ipcDmaStatus;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_DMA_STAT;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return;
+ }
+ memcpy((uint8_t*)&ipcDmaStatus, reply.replyBody, sizeof(t_FmIpcDmaStatus));
+
+ p_FmDmaStatus->cmqNotEmpty = (bool)ipcDmaStatus.boolCmqNotEmpty; /**< Command queue is not empty */
+ p_FmDmaStatus->busError = (bool)ipcDmaStatus.boolBusError; /**< Bus error occurred */
+ p_FmDmaStatus->readBufEccError = (bool)ipcDmaStatus.boolReadBufEccError; /**< Double ECC error on buffer Read */
+ p_FmDmaStatus->writeBufEccSysError =(bool)ipcDmaStatus.boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */
+ p_FmDmaStatus->writeBufEccFmError = (bool)ipcDmaStatus.boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */
+ p_FmDmaStatus->singlePortEccError = (bool)ipcDmaStatus.boolSinglePortEccError; /**< Double ECC error on buffer write from FM side */
+ return;
+ }
+ else if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return;
+ }
+
+ tmpReg = GET_UINT32(p_Fm->p_FmDmaRegs->fmdmsr);
+
+ p_FmDmaStatus->cmqNotEmpty = (bool)(tmpReg & DMA_STATUS_CMD_QUEUE_NOT_EMPTY);
+ p_FmDmaStatus->busError = (bool)(tmpReg & DMA_STATUS_BUS_ERR);
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ p_FmDmaStatus->singlePortEccError = (bool)(tmpReg & DMA_STATUS_FM_SPDAT_ECC);
+ else
+ {
+ p_FmDmaStatus->readBufEccError = (bool)(tmpReg & DMA_STATUS_READ_ECC);
+ p_FmDmaStatus->writeBufEccSysError = (bool)(tmpReg & DMA_STATUS_SYSTEM_WRITE_ECC);
+ p_FmDmaStatus->writeBufEccFmError = (bool)(tmpReg & DMA_STATUS_FM_WRITE_ECC);
+ }
+}
+
+void FM_Resume(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ tmpReg = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee);
+ /* clear tmpReg event bits in order not to clear standing events */
+ tmpReg &= ~(FPM_EV_MASK_DOUBLE_ECC | FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC);
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_ee, tmpReg | FPM_EV_MASK_RELEASE_FM);
+}
+
+t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm,
+ fmSpecialOperations_t spOper,
+ uint8_t *p_SpOperCoding)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmCtrlCodeRevisionInfo revInfo;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_SpOperCoding, E_NULL_POINTER);
+
+ if (!spOper)
+ {
+ *p_SpOperCoding = 0;
+ return E_OK;
+ }
+
+ if ((err = FM_GetFmanCtrlCodeRevision(p_Fm, &revInfo)) != E_OK)
+ {
+ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision."));
+ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER;
+ }
+ else if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package"));
+
+ if (revInfo.packageRev == IP_OFFLOAD_PACKAGE_NUMBER)
+ {
+ switch (spOper)
+ {
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP):
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD):
+ *p_SpOperCoding = 5;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP):
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD):
+ *p_SpOperCoding = 6;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_RPD):
+ *p_SpOperCoding = 3;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN):
+ *p_SpOperCoding = 1;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_RPD):
+ *p_SpOperCoding = 4;
+ break;
+ case (FM_SP_OP_IPSEC):
+ *p_SpOperCoding = 2;
+ break;
+ case (FM_SP_OP_DCL4C):
+ *p_SpOperCoding = 7;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+ }
+ }
+ return E_OK;
+}
+
+t_Error FM_CtrlMonStart(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ for (i = 0; i < FM_NUM_OF_CTRL; i++)
+ {
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i));
+
+ /* Reset control registers */
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_RESET);
+ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET);
+
+ /* Configure: counter #1 counts all stalls in risc - ldsched stall
+ counter #2 counts all stalls in risc - other stall*/
+ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET | TRB_TCRL_UTIL);
+
+ /* Enable monitoring */
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_ENABLE_COUNTERS);
+ }
+
+ return E_OK;
+}
+
+t_Error FM_CtrlMonStop(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ for (i = 0; i < FM_NUM_OF_CTRL; i++)
+ {
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i));
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_DISABLE_COUNTERS);
+ }
+
+ return E_OK;
+}
+
+t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint64_t clkCnt, utilValue, effValue;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+ SANITY_CHECK_RETURN_ERROR(p_Mon, E_NULL_POINTER);
+
+ if (fmCtrlIndex >= FM_NUM_OF_CTRL)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FM Controller index"));
+
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(fmCtrlIndex));
+
+ clkCnt = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpcch) << 32 | GET_UINT32(p_MonRegs->tpccl));
+
+ utilValue = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpc1h) << 32 | GET_UINT32(p_MonRegs->tpc1l));
+
+ effValue = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpc2h) << 32 | GET_UINT32(p_MonRegs->tpc2l));
+
+ p_Mon->percentCnt[0] = (uint8_t)((clkCnt - utilValue) * 100 / clkCnt);
+ if (clkCnt != utilValue)
+ p_Mon->percentCnt[1] = (uint8_t)(((clkCnt - utilValue) - effValue) * 100 / (clkCnt - utilValue));
+ else
+ p_Mon->percentCnt[1] = 0;
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_DumpRegs(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t i,j = 0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) ||
+ p_Fm->baseAddr), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+
+ DUMP_TITLE(p_Fm->p_FmFpmRegs, ("FM-FPM Regs"));
+
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tnc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_prc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_brkc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_mxd);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dis1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dis2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_epi);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rie);
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_fcev, ("fmfp_fcev"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_fcev[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cee, ("fmfp_cee"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cee[i], sizeof(uint32_t));
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsp);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsf);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rcr);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_extc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext2);
+
+ DUMP_SUBTITLE(("\n"));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dra, 0);
+ CORE_MemoryBarrier();
+ for (j=0; j<128; j++)
+ {
+ DUMP_TITLE(j, ("fmfp_dra"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_drd[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(j, ("fmfp_ts"));
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ts[j], sizeof(uint32_t));
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rstc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_cld);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_npi);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ee);
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cev, ("fmfp_cev"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cev[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps, ("fmfp_ps"));
+ DUMP_SUBSTRUCT_ARRAY(i, 64)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmDmaRegs, ("FM-DMA Regs"));
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmemsr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmmr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmhy);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsetr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtah);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtal);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtcid);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmra);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmrd);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmwcr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmebcr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmdcr);
+
+ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr, ("fmdmplr"));
+
+ DUMP_SUBSTRUCT_ARRAY(i, FM_MAX_NUM_OF_HW_PORT_IDS/2)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmBmiRegs, ("FM-BMI COMMON Regs"));
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_init);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg1);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg2);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ievr);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ier);
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_arb, ("fmbm_arb"));
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_arb[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmQmiRegs, ("FM-QMI COMMON Regs"));
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gc);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eie);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eien);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eif);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ie);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ien);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_if);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gs);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_etfc);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ switch (exception)
+ {
+ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, QMI_ERR_INTR_EN_DEQ_FROM_DEF);
+ break;
+ case e_FM_EX_QMI_SINGLE_ECC:
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC not supported on this integration."));
+
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_if, QMI_INTR_EN_SINGLE_ECC);
+ break;
+ case e_FM_EX_QMI_DOUBLE_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmQmiRegs->fmqm_eif, QMI_ERR_INTR_EN_DOUBLE_ECC);
+ break;
+ case e_FM_EX_BMI_LIST_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_LIST_RAM_ECC);
+ break;
+ case e_FM_EX_BMI_STORAGE_PROFILE_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC);
+ break;
+ case e_FM_EX_BMI_STATISTICS_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_STATISTICS_RAM_ECC);
+ break;
+ case e_FM_EX_BMI_DISPATCH_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_ifr, BMI_ERR_INTR_EN_DISPATCH_RAM_ECC);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced"));
+ }
+
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h
new file mode 100644
index 0000000..4f3ad00
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h
@@ -0,0 +1,897 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm.h
+
+ @Description FM internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_H
+#define __FM_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_ext.h"
+#include "fm_ipc.h"
+
+
+#define __ERR_MODULE__ MODULE_FM
+
+#define FM_MAX_NUM_OF_HW_PORT_IDS 64
+#define FM_MAX_NUM_OF_GUESTS 100
+
+/**************************************************************************//**
+ @Description Exceptions
+*//***************************************************************************/
+#define FM_EX_DMA_BUS_ERROR 0x80000000 /**< DMA bus error. */
+#define FM_EX_DMA_READ_ECC 0x40000000
+#define FM_EX_DMA_SYSTEM_WRITE_ECC 0x20000000
+#define FM_EX_DMA_FM_WRITE_ECC 0x10000000
+#define FM_EX_FPM_STALL_ON_TASKS 0x08000000 /**< Stall of tasks on FPM */
+#define FM_EX_FPM_SINGLE_ECC 0x04000000 /**< Single ECC on FPM */
+#define FM_EX_FPM_DOUBLE_ECC 0x02000000
+#define FM_EX_QMI_SINGLE_ECC 0x01000000 /**< Single ECC on FPM */
+#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 /**< Dequeu from default queue id */
+#define FM_EX_QMI_DOUBLE_ECC 0x00400000
+#define FM_EX_BMI_LIST_RAM_ECC 0x00200000
+#define FM_EX_BMI_STORAGE_PROFILE_ECC 0x00100000
+#define FM_EX_BMI_STATISTICS_RAM_ECC 0x00080000
+#define FM_EX_IRAM_ECC 0x00040000
+#define FM_EX_MURAM_ECC 0x00020000
+#define FM_EX_BMI_DISPATCH_RAM_ECC 0x00010000
+#define FM_EX_DMA_SINGLE_PORT_ECC 0x00008000
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) \
+switch (exception){ \
+ case e_FM_EX_DMA_BUS_ERROR: \
+ bitMask = FM_EX_DMA_BUS_ERROR; break; \
+ case e_FM_EX_DMA_SINGLE_PORT_ECC: \
+ bitMask = FM_EX_DMA_SINGLE_PORT_ECC; break; \
+ case e_FM_EX_DMA_READ_ECC: \
+ bitMask = FM_EX_DMA_READ_ECC; break; \
+ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: \
+ bitMask = FM_EX_DMA_SYSTEM_WRITE_ECC; break; \
+ case e_FM_EX_DMA_FM_WRITE_ECC: \
+ bitMask = FM_EX_DMA_FM_WRITE_ECC; break; \
+ case e_FM_EX_FPM_STALL_ON_TASKS: \
+ bitMask = FM_EX_FPM_STALL_ON_TASKS; break; \
+ case e_FM_EX_FPM_SINGLE_ECC: \
+ bitMask = FM_EX_FPM_SINGLE_ECC; break; \
+ case e_FM_EX_FPM_DOUBLE_ECC: \
+ bitMask = FM_EX_FPM_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_SINGLE_ECC: \
+ bitMask = FM_EX_QMI_SINGLE_ECC; break; \
+ case e_FM_EX_QMI_DOUBLE_ECC: \
+ bitMask = FM_EX_QMI_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \
+ bitMask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; break; \
+ case e_FM_EX_BMI_LIST_RAM_ECC: \
+ bitMask = FM_EX_BMI_LIST_RAM_ECC; break; \
+ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: \
+ bitMask = FM_EX_BMI_STORAGE_PROFILE_ECC; break; \
+ case e_FM_EX_BMI_STATISTICS_RAM_ECC: \
+ bitMask = FM_EX_BMI_STATISTICS_RAM_ECC; break; \
+ case e_FM_EX_BMI_DISPATCH_RAM_ECC: \
+ bitMask = FM_EX_BMI_DISPATCH_RAM_ECC; break; \
+ case e_FM_EX_IRAM_ECC: \
+ bitMask = FM_EX_IRAM_ECC; break; \
+ case e_FM_EX_MURAM_ECC: \
+ bitMask = FM_EX_MURAM_ECC; break; \
+ default: bitMask = 0;break; \
+}
+
+#define GET_FM_MODULE_EVENT(_mod, _id, _intrType, _event) \
+ switch (_mod) { \
+ case e_FM_MOD_PRS: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PRS : e_FM_EV_PRS; \
+ break; \
+ case e_FM_MOD_KG: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_KG : e_FM_EV_DUMMY_LAST; \
+ break; \
+ case e_FM_MOD_PLCR: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PLCR : e_FM_EV_PLCR; \
+ break; \
+ case e_FM_MOD_TMR: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_DUMMY_LAST : e_FM_EV_TMR; \
+ break; \
+ case e_FM_MOD_10G_MAC: \
+ if (_id >= FM_MAX_NUM_OF_10G_MACS) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_10G_MAC0 + _id) : (e_FM_EV_10G_MAC0 + _id); \
+ break; \
+ case e_FM_MOD_1G_MAC: \
+ if (_id >= FM_MAX_NUM_OF_1G_MACS) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_1G_MAC0 + _id) : (e_FM_EV_1G_MAC0 + _id); \
+ break; \
+ case e_FM_MOD_MACSEC: \
+ switch (_id){ \
+ case (0): _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_MACSEC_MAC0:e_FM_EV_MACSEC_MAC0; \
+ break; \
+ } \
+ break; \
+ case e_FM_MOD_FMAN_CTRL: \
+ if (_intrType == e_FM_INTR_TYPE_ERR) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (e_FM_EV_FMAN_CTRL_0 + _id); \
+ break; \
+ default: _event = e_FM_EV_DUMMY_LAST; \
+ break; \
+ }
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_exceptions (FM_EX_DMA_BUS_ERROR |\
+ FM_EX_DMA_READ_ECC |\
+ FM_EX_DMA_SYSTEM_WRITE_ECC |\
+ FM_EX_DMA_FM_WRITE_ECC |\
+ FM_EX_FPM_STALL_ON_TASKS |\
+ FM_EX_FPM_SINGLE_ECC |\
+ FM_EX_FPM_DOUBLE_ECC |\
+ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID|\
+ FM_EX_BMI_LIST_RAM_ECC |\
+ FM_EX_BMI_STORAGE_PROFILE_ECC |\
+ FM_EX_BMI_STATISTICS_RAM_ECC |\
+ FM_EX_IRAM_ECC |\
+ FM_EX_MURAM_ECC |\
+ FM_EX_BMI_DISPATCH_RAM_ECC |\
+ FM_EX_QMI_DOUBLE_ECC |\
+ FM_EX_QMI_SINGLE_ECC)
+
+
+#define DEFAULT_totalFifoSize(major) \
+ (((major == 2) || (major == 5)) ? \
+ (100*KILOBYTE) : ((major == 6) ? \
+ (288*KILOBYTE) : ((major == 4) ? \
+ (46*KILOBYTE) : (122*KILOBYTE))))
+
+#define DEFAULT_eccEnable FALSE
+#define DEFAULT_dispLimit 0
+#define DEFAULT_prsDispTh 16
+#define DEFAULT_plcrDispTh 16
+#define DEFAULT_kgDispTh 16
+#define DEFAULT_bmiDispTh 16
+#define DEFAULT_qmiEnqDispTh 16
+#define DEFAULT_qmiDeqDispTh 16
+#define DEFAULT_fmCtl1DispTh 16
+#define DEFAULT_fmCtl2DispTh 16
+#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR
+#ifdef FM_PEDANTIC_DMA
+#define DEFAULT_aidOverride TRUE
+#else
+#define DEFAULT_aidOverride FALSE
+#endif /* FM_PEDANTIC_DMA */
+#define DEFAULT_aidMode e_FM_DMA_AID_OUT_TNUM
+#define DEFAULT_dmaStopOnBusError FALSE
+#define DEFAULT_stopAtBusError FALSE
+#define DEFAULT_axiDbgNumOfBeats 1
+#define DEFAULT_dmaCamNumOfEntries 32
+#define DEFAULT_dmaCommQLow ((DMA_THRESH_MAX_COMMQ+1)/2)
+#define DEFAULT_dmaCommQHigh ((DMA_THRESH_MAX_COMMQ+1)*3/4)
+#define DEFAULT_dmaReadIntBufLow ((DMA_THRESH_MAX_BUF+1)/2)
+#define DEFAULT_dmaReadIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4)
+#define DEFAULT_dmaWriteIntBufLow ((DMA_THRESH_MAX_BUF+1)/2)
+#define DEFAULT_dmaWriteIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4)
+#define DEFAULT_dmaSosEmergency 0
+#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT
+#define DEFAULT_catastrophicErr e_FM_CATASTROPHIC_ERR_STALL_PORT
+#define DEFAULT_dmaErr e_FM_DMA_ERR_CATASTROPHIC
+#define DEFAULT_resetOnInit FALSE
+#define DEFAULT_haltOnExternalActivation FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_haltOnUnrecoverableEccError FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_externalEccRamsEnable FALSE
+#define DEFAULT_VerifyUcode FALSE
+#define DEFAULT_tnumAgingPeriod 0
+#define DEFAULT_dmaWatchdog 0 /* disabled */
+
+#define FM_TIMESTAMP_1_USEC_BIT 8
+
+/**************************************************************************//**
+ @Collection Defines used for enabling/disabling FM interrupts
+ @{
+*//***************************************************************************/
+#define ERR_INTR_EN_DMA 0x00010000
+#define ERR_INTR_EN_FPM 0x80000000
+#define ERR_INTR_EN_BMI 0x00800000
+#define ERR_INTR_EN_QMI 0x00400000
+#define ERR_INTR_EN_PRS 0x00200000
+#define ERR_INTR_EN_KG 0x00100000
+#define ERR_INTR_EN_PLCR 0x00080000
+#define ERR_INTR_EN_MURAM 0x00040000
+#define ERR_INTR_EN_IRAM 0x00020000
+#define ERR_INTR_EN_10G_MAC0 0x00008000
+#define ERR_INTR_EN_10G_MAC1 0x00000040
+#define ERR_INTR_EN_1G_MAC0 0x00004000
+#define ERR_INTR_EN_1G_MAC1 0x00002000
+#define ERR_INTR_EN_1G_MAC2 0x00001000
+#define ERR_INTR_EN_1G_MAC3 0x00000800
+#define ERR_INTR_EN_1G_MAC4 0x00000400
+#define ERR_INTR_EN_1G_MAC5 0x00000200
+#define ERR_INTR_EN_1G_MAC6 0x00000100
+#define ERR_INTR_EN_1G_MAC7 0x00000080
+#define ERR_INTR_EN_MACSEC_MAC0 0x00000001
+
+#define INTR_EN_QMI 0x40000000
+#define INTR_EN_PRS 0x20000000
+#define INTR_EN_PLCR 0x08000000
+#define INTR_EN_1G_MAC0 0x00080000
+#define INTR_EN_1G_MAC1 0x00040000
+#define INTR_EN_1G_MAC2 0x00020000
+#define INTR_EN_1G_MAC3 0x00010000
+#define INTR_EN_1G_MAC4 0x00000040
+#define INTR_EN_1G_MAC5 0x00000020
+#define INTR_EN_1G_MAC6 0x00000008
+#define INTR_EN_1G_MAC7 0x00000002
+#define INTR_EN_10G_MAC0 0x00200000
+#define INTR_EN_10G_MAC1 0x00100000
+#define INTR_EN_REV0 0x00008000
+#define INTR_EN_REV1 0x00004000
+#define INTR_EN_REV2 0x00002000
+#define INTR_EN_REV3 0x00001000
+#define INTR_EN_BRK 0x00000080
+#define INTR_EN_TMR 0x01000000
+#define INTR_EN_MACSEC_MAC0 0x00000001
+/* @} */
+
+/**************************************************************************//**
+ @Description Modules registers offsets
+*//***************************************************************************/
+#define FM_MM_MURAM 0x00000000
+#define FM_MM_BMI 0x00080000
+#define FM_MM_QMI 0x00080400
+#define FM_MM_PRS 0x000c7000
+#define FM_MM_KG 0x000C1000
+#define FM_MM_DMA 0x000C2000
+#define FM_MM_FPM 0x000C3000
+#define FM_MM_PLCR 0x000C0000
+#define FM_MM_IMEM 0x000C4000
+#define FM_MM_CGP 0x000DB000
+#define FM_MM_TRB(i) (0x000D0200 + 0x400 * (i))
+#if (DPAA_VERSION >= 11)
+#define FM_MM_SP 0x000dc000
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/**************************************************************************//**
+ @Description Memory Mapped Registers
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct
+{
+ volatile uint32_t fmfp_tnc; /**< FPM TNUM Control */
+ volatile uint32_t fmfp_prc; /**< FPM Port_ID FmCtl Association */
+ volatile uint32_t fmfp_brkc; /**< FPM Breakpoint Control */
+ volatile uint32_t fmfp_mxd; /**< FPM Maximum dispatch */
+ volatile uint32_t fmfp_dis1; /**< FPM Dispatch Thresholds1 */
+ volatile uint32_t fmfp_dis2; /**< FPM Dispatch Thresholds2 */
+ volatile uint32_t fm_epi; /**< FM Error Pending Interrupts */
+ volatile uint32_t fm_rie; /**< FM Error Interrupt Enable */
+ volatile uint32_t fmfp_fcev[4]; /**< FPM FMan-Controller Event 1-4 */
+ volatile uint8_t res1[16]; /**< reserved */
+ volatile uint32_t fmfp_cee[4]; /**< PM FMan-Controller Event 1-4 */
+ volatile uint8_t res2[16]; /**< reserved */
+ volatile uint32_t fmfp_tsc1; /**< FPM TimeStamp Control1 */
+ volatile uint32_t fmfp_tsc2; /**< FPM TimeStamp Control2 */
+ volatile uint32_t fmfp_tsp; /**< FPM Time Stamp */
+ volatile uint32_t fmfp_tsf; /**< FPM Time Stamp Fraction */
+ volatile uint32_t fm_rcr; /**< FM Rams Control */
+ volatile uint32_t fmfp_extc; /**< FPM External Requests Control */
+ volatile uint32_t fmfp_ext1; /**< FPM External Requests Config1 */
+ volatile uint32_t fmfp_ext2; /**< FPM External Requests Config2 */
+ volatile uint32_t fmfp_drd[4]; /**< FPM Data_Ram Data 0-3 */
+ volatile uint8_t res3[48]; /**< reserved */
+ volatile uint32_t fmfp_dra; /**< FPM Data Ram Access */
+ volatile uint32_t fm_ip_rev_1; /**< FM IP Block Revision 1 */
+ volatile uint32_t fm_ip_rev_2; /**< FM IP Block Revision 2 */
+ volatile uint32_t fm_rstc; /**< FM Reset Command */
+ volatile uint32_t fm_cld; /**< FM Classifier Debug */
+ volatile uint32_t fm_npi; /**< FM Normal Pending Interrupts */
+ volatile uint32_t fmfp_exte; /**< FPM External Requests Enable */
+ volatile uint32_t fmfp_ee; /**< FPM Event & Enable */
+ volatile uint32_t fmfp_cev[4]; /**< FPM CPU Event 1-4 */
+ volatile uint8_t res4[16]; /**< reserved */
+ volatile uint32_t fmfp_ps[0x40]; /**< FPM Port Status */
+ volatile uint8_t reserved1[0x200];
+ volatile uint32_t fmfp_ts[128]; /**< 0x400: FPM Task Status */
+} _PackedType t_FmFpmRegs;
+
+#define NUM_OF_DBG_TRAPS 3
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_init; /**< BMI Initialization */
+ volatile uint32_t fmbm_cfg1; /**< BMI Configuration 1 */
+ volatile uint32_t fmbm_cfg2; /**< BMI Configuration 2 */
+ volatile uint32_t reserved[5];
+ volatile uint32_t fmbm_ievr; /**< Interrupt Event Register */
+ volatile uint32_t fmbm_ier; /**< Interrupt Enable Register */
+ volatile uint32_t fmbm_ifr; /**< Interrupt Force Register */
+ volatile uint32_t reserved1[5];
+ volatile uint32_t fmbm_arb[8]; /**< BMI Arbitration */
+ volatile uint32_t reserved2[12];
+ volatile uint32_t fmbm_dtc[NUM_OF_DBG_TRAPS]; /**< BMI Debug Trap Counter */
+ volatile uint32_t reserved3;
+ volatile uint32_t fmbm_dcv[NUM_OF_DBG_TRAPS][4]; /**< BMI Debug Compare Value */
+ volatile uint32_t fmbm_dcm[NUM_OF_DBG_TRAPS][4]; /**< BMI Debug Compare Mask */
+ volatile uint32_t fmbm_gde; /**< BMI Global Debug Enable */
+ volatile uint32_t fmbm_pp[63]; /**< BMI Port Parameters */
+ volatile uint32_t reserved4;
+ volatile uint32_t fmbm_pfs[63]; /**< BMI Port FIFO Size */
+ volatile uint32_t reserved5;
+ volatile uint32_t fmbm_spliodn[63]; /**< Port Partition ID */
+} _PackedType t_FmBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmqm_gc; /**< General Configuration Register */
+ volatile uint32_t reserved0;
+ volatile uint32_t fmqm_eie; /**< Error Interrupt Event Register */
+ volatile uint32_t fmqm_eien; /**< Error Interrupt Enable Register */
+ volatile uint32_t fmqm_eif; /**< Error Interrupt Force Register */
+ volatile uint32_t fmqm_ie; /**< Interrupt Event Register */
+ volatile uint32_t fmqm_ien; /**< Interrupt Enable Register */
+ volatile uint32_t fmqm_if; /**< Interrupt Force Register */
+ volatile uint32_t fmqm_gs; /**< Global Status Register */
+ volatile uint32_t reserved1;
+ volatile uint32_t fmqm_etfc; /**< Enqueue Total Frame Counter */
+ volatile uint32_t fmqm_dtfc; /**< Dequeue Total Frame Counter */
+ volatile uint32_t fmqm_dc0; /**< Dequeue Counter 0 */
+ volatile uint32_t fmqm_dc1; /**< Dequeue Counter 1 */
+ volatile uint32_t fmqm_dc2; /**< Dequeue Counter 2 */
+ volatile uint32_t fmqm_dc3; /**< Dequeue Counter 3 */
+ volatile uint32_t fmqm_dfdc; /**< Dequeue FQID from Default Counter */
+ volatile uint32_t fmqm_dfcc; /**< Dequeue FQID from Context Counter */
+ volatile uint32_t fmqm_dffc; /**< Dequeue FQID from FD Counter */
+ volatile uint32_t fmqm_dcc; /**< Dequeue Confirm Counter */
+ volatile uint32_t reserved1a[7];
+ volatile uint32_t fmqm_tapc; /**< Tnum Aging Period Control */
+ volatile uint32_t fmqm_dmcvc; /**< Dequeue MAC Command Valid Counter */
+ volatile uint32_t fmqm_difdcc; /**< Dequeue Invalid FD Command Counter */
+ volatile uint32_t fmqm_da1v; /**< Dequeue A1 Valid Counter */
+ volatile uint32_t reserved1b;
+ volatile uint32_t fmqm_dtc; /**< 0x0080 Debug Trap Counter */
+ volatile uint32_t fmqm_efddd; /**< 0x0084 Enqueue Frame Descriptor Dynamic Debug */
+ volatile uint32_t reserved3[2];
+ _Packed struct {
+ volatile uint32_t fmqm_dtcfg1; /**< 0x0090 Debug Trap Configuration 1 Register */
+ volatile uint32_t fmqm_dtval1; /**< Debug Trap Value 1 Register */
+ volatile uint32_t fmqm_dtm1; /**< Debug Trap Mask 1 Register */
+ volatile uint32_t fmqm_dtc1; /**< Debug Trap Counter 1 Register */
+ volatile uint32_t fmqm_dtcfg2; /**< Debug Trap Configuration 2 Register */
+ volatile uint32_t fmqm_dtval2; /**< Debug Trap Value 2 Register */
+ volatile uint32_t fmqm_dtm2; /**< Debug Trap Mask 2 Register */
+ volatile uint32_t reserved1;
+ } _PackedType dbgTraps[NUM_OF_DBG_TRAPS];
+} _PackedType t_FmQmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmdmsr; /**< FM DMA status register 0x04 */
+ volatile uint32_t fmdmmr; /**< FM DMA mode register 0x08 */
+ volatile uint32_t fmdmtr; /**< FM DMA bus threshold register 0x0c */
+ volatile uint32_t fmdmhy; /**< FM DMA bus hysteresis register 0x10 */
+ volatile uint32_t fmdmsetr; /**< FM DMA SOS emergency Threshold Register 0x14 */
+ volatile uint32_t fmdmtah; /**< FM DMA transfer bus address high register 0x18 */
+ volatile uint32_t fmdmtal; /**< FM DMA transfer bus address low register 0x1C */
+ volatile uint32_t fmdmtcid; /**< FM DMA transfer bus communication ID register 0x20 */
+ volatile uint32_t fmdmra; /**< FM DMA bus internal ram address register 0x24 */
+ volatile uint32_t fmdmrd; /**< FM DMA bus internal ram data register 0x28 */
+ volatile uint32_t fmdmwcr; /**< FM DMA CAM watchdog counter value 0x2C */
+ volatile uint32_t fmdmebcr; /**< FM DMA CAM base in MURAM register 0x30 */
+ volatile uint32_t fmdmccqdr; /**< FM DMA CAM and CMD Queue Debug register 0x34 */
+ volatile uint32_t fmdmccqvr1; /**< FM DMA CAM and CMD Queue Value register #1 0x38 */
+ volatile uint32_t fmdmccqvr2; /**< FM DMA CAM and CMD Queue Value register #2 0x3C */
+ volatile uint32_t fmdmcqvr3; /**< FM DMA CMD Queue Value register #3 0x40 */
+ volatile uint32_t fmdmcqvr4; /**< FM DMA CMD Queue Value register #4 0x44 */
+ volatile uint32_t fmdmcqvr5; /**< FM DMA CMD Queue Value register #5 0x48 */
+ volatile uint32_t fmdmsefrc; /**< FM DMA Semaphore Entry Full Reject Counter 0x50 */
+ volatile uint32_t fmdmsqfrc; /**< FM DMA Semaphore Queue Full Reject Counter 0x54 */
+ volatile uint32_t fmdmssrc; /**< FM DMA Semaphore SYNC Reject Counter 0x54 */
+ volatile uint32_t fmdmdcr; /**< FM DMA Debug Counter */
+ volatile uint32_t fmdmemsr; /**< FM DMA Emrgency Smoother Register */
+ volatile uint32_t reserved;
+ volatile uint32_t fmdmplr[FM_MAX_NUM_OF_HW_PORT_IDS/2];
+ /**< FM DMA PID-LIODN # register */
+} _PackedType t_FmDmaRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t iadd; /**< FM IRAM instruction address register */
+ volatile uint32_t idata; /**< FM IRAM instruction data register */
+ volatile uint32_t itcfg; /**< FM IRAM timing config register */
+ volatile uint32_t iready; /**< FM IRAM ready register */
+ volatile uint8_t res[0x80000-0x10];
+} _PackedType t_FMIramRegs;
+
+/* Trace buffer registers -
+ each FM Controller has its own trace buffer residing at FM_MM_TRB(fmCtrlIndex) offset */
+typedef _Packed struct t_FmTrbRegs
+{
+ volatile uint32_t tcrh;
+ volatile uint32_t tcrl;
+ volatile uint32_t tesr;
+ volatile uint32_t tecr0h;
+ volatile uint32_t tecr0l;
+ volatile uint32_t terf0h;
+ volatile uint32_t terf0l;
+ volatile uint32_t tecr1h;
+ volatile uint32_t tecr1l;
+ volatile uint32_t terf1h;
+ volatile uint32_t terf1l;
+ volatile uint32_t tpcch;
+ volatile uint32_t tpccl;
+ volatile uint32_t tpc1h;
+ volatile uint32_t tpc1l;
+ volatile uint32_t tpc2h;
+ volatile uint32_t tpc2l;
+ volatile uint32_t twdimr;
+ volatile uint32_t twicvr;
+ volatile uint32_t tar;
+ volatile uint32_t tdr;
+ volatile uint32_t tsnum1;
+ volatile uint32_t tsnum2;
+ volatile uint32_t tsnum3;
+ volatile uint32_t tsnum4;
+} _PackedType t_FmTrbRegs;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/**************************************************************************//**
+ @Description General defines
+*//***************************************************************************/
+#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL
+#define FM_FW_DEBUG_INSTRUCTION 0x6ffff805UL
+
+/**************************************************************************//**
+ @Description DMA definitions
+*//***************************************************************************/
+/* masks */
+#define DMA_MODE_AID_OR 0x20000000
+#define DMA_MODE_SBER 0x10000000
+#define DMA_MODE_BER 0x00200000
+#define DMA_MODE_EB 0x00100000
+#define DMA_MODE_ECC 0x00000020
+#define DMA_MODE_PRIVILEGE_PROT 0x00001000
+#define DMA_MODE_SECURE_PROT 0x00000800
+#define DMA_MODE_EMERGENCY_READ 0x00080000
+#define DMA_MODE_EMERGENCY_WRITE 0x00040000
+#define DMA_MODE_CACHE_OR_MASK 0xC0000000
+#define DMA_MODE_CEN_MASK 0x0000E000
+#define DMA_MODE_DBG_MASK 0x00000380
+
+#define DMA_TRANSFER_PORTID_MASK 0xFF000000
+#define DMA_TRANSFER_TNUM_MASK 0x00FF0000
+#define DMA_TRANSFER_LIODN_MASK 0x00000FFF
+
+#define DMA_HIGH_LIODN_MASK 0x0FFF0000
+#define DMA_LOW_LIODN_MASK 0x00000FFF
+
+#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY 0x10000000
+#define DMA_STATUS_BUS_ERR 0x08000000
+#define DMA_STATUS_READ_ECC 0x04000000
+#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000
+#define DMA_STATUS_FM_WRITE_ECC 0x01000000
+#define DMA_STATUS_SYSTEM_DPEXT_ECC 0x00800000
+#define DMA_STATUS_FM_DPEXT_ECC 0x00400000
+#define DMA_STATUS_SYSTEM_DPDAT_ECC 0x00200000
+#define DMA_STATUS_FM_DPDAT_ECC 0x00100000
+#define DMA_STATUS_FM_SPDAT_ECC 0x00080000
+
+#define DMA_STATUS_FM_ECC (DMA_STATUS_READ_ECC | \
+ DMA_STATUS_SYSTEM_WRITE_ECC | \
+ DMA_STATUS_FM_WRITE_ECC | \
+ DMA_STATUS_SYSTEM_DPEXT_ECC | \
+ DMA_STATUS_FM_DPEXT_ECC | \
+ DMA_STATUS_SYSTEM_DPDAT_ECC | \
+ DMA_STATUS_FM_DPDAT_ECC | \
+ DMA_STATUS_FM_SPDAT_ECC)
+
+#define FM_LIODN_BASE_MASK 0x00000FFF
+
+#define DMA_EMSR_EMSTR_MASK 0x0000FFFF
+
+/* shifts */
+#define DMA_MODE_CACHE_OR_SHIFT 30
+#define DMA_MODE_BUS_PRI_SHIFT 16
+#define DMA_MODE_AXI_DBG_SHIFT 24
+#define DMA_MODE_CEN_SHIFT 13
+#define DMA_MODE_BUS_PROT_SHIFT 10
+#define DMA_MODE_DBG_SHIFT 7
+#define DMA_MODE_EMERGENCY_LEVEL_SHIFT 6
+#define DMA_MODE_AID_MODE_SHIFT 4
+#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS 16
+#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES 64
+
+#define DMA_THRESH_COMMQ_SHIFT 24
+#define DMA_THRESH_READ_INT_BUF_SHIFT 16
+
+#define DMA_LIODN_SHIFT 16
+
+#define DMA_TRANSFER_PORTID_SHIFT 24
+#define DMA_TRANSFER_TNUM_SHIFT 16
+
+/* sizes */
+#define DMA_MAX_WATCHDOG 0xffffffff
+
+/* others */
+#define DMA_CAM_SIZEOF_ENTRY 0x40
+#define DMA_CAM_ALIGN 0x1000
+#define DMA_CAM_UNITS 8
+
+
+/**************************************************************************//**
+ @Description FPM defines
+*//***************************************************************************/
+/* masks */
+#define FPM_EV_MASK_DOUBLE_ECC 0x80000000
+#define FPM_EV_MASK_STALL 0x40000000
+#define FPM_EV_MASK_SINGLE_ECC 0x20000000
+#define FPM_EV_MASK_RELEASE_FM 0x00010000
+#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000
+#define FPM_EV_MASK_STALL_EN 0x00004000
+#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000
+#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008
+#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004
+
+#define FPM_RAM_CTL_RAMS_ECC_EN 0x80000000
+#define FPM_RAM_CTL_IRAM_ECC_EN 0x40000000
+#define FPM_RAM_CTL_MURAM_ECC 0x00008000
+#define FPM_RAM_CTL_IRAM_ECC 0x00004000
+#define FPM_RAM_CTL_MURAM_TEST_ECC 0x20000000
+#define FPM_RAM_CTL_IRAM_TEST_ECC 0x10000000
+#define FPM_RAM_CTL_RAMS_ECC_EN_SRC_SEL 0x08000000
+
+#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000
+#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000
+
+#define FPM_REV1_MAJOR_MASK 0x0000FF00
+#define FPM_REV1_MINOR_MASK 0x000000FF
+
+#define FPM_REV2_INTEG_MASK 0x00FF0000
+#define FPM_REV2_ERR_MASK 0x0000FF00
+#define FPM_REV2_CFG_MASK 0x000000FF
+
+#define FPM_TS_FRACTION_MASK 0x0000FFFF
+#define FPM_TS_CTL_EN 0x80000000
+
+#define FPM_PRC_REALSE_STALLED 0x00800000
+
+#define FPM_PS_STALLED 0x00800000
+#define FPM_PS_FM_CTL1_SEL 0x80000000
+#define FPM_PS_FM_CTL2_SEL 0x40000000
+#define FPM_PS_FM_CTL_SEL_MASK (FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL)
+
+#define FPM_RSTC_FM_RESET 0x80000000
+#define FPM_RSTC_1G0_RESET 0x40000000
+#define FPM_RSTC_1G1_RESET 0x20000000
+#define FPM_RSTC_1G2_RESET 0x10000000
+#define FPM_RSTC_1G3_RESET 0x08000000
+#define FPM_RSTC_10G0_RESET 0x04000000
+#define FPM_RSTC_1G4_RESET 0x02000000
+#define FPM_RSTC_1G5_RESET 0x01000000
+#define FPM_RSTC_1G6_RESET 0x00800000
+#define FPM_RSTC_1G7_RESET 0x00400000
+#define FPM_RSTC_10G1_RESET 0x00200000
+
+
+#define FPM_DISP_LIMIT_MASK 0x1F000000
+#define FPM_THR1_PRS_MASK 0xFF000000
+#define FPM_THR1_KG_MASK 0x00FF0000
+#define FPM_THR1_PLCR_MASK 0x0000FF00
+#define FPM_THR1_BMI_MASK 0x000000FF
+
+#define FPM_THR2_QMI_ENQ_MASK 0xFF000000
+#define FPM_THR2_QMI_DEQ_MASK 0x000000FF
+#define FPM_THR2_FM_CTL1_MASK 0x00FF0000
+#define FPM_THR2_FM_CTL2_MASK 0x0000FF00
+
+/* shifts */
+#define FPM_DISP_LIMIT_SHIFT 24
+
+#define FPM_THR1_PRS_SHIFT 24
+#define FPM_THR1_KG_SHIFT 16
+#define FPM_THR1_PLCR_SHIFT 8
+#define FPM_THR1_BMI_SHIFT 0
+
+#define FPM_THR2_QMI_ENQ_SHIFT 24
+#define FPM_THR2_QMI_DEQ_SHIFT 0
+#define FPM_THR2_FM_CTL1_SHIFT 16
+#define FPM_THR2_FM_CTL2_SHIFT 8
+
+#define FPM_EV_MASK_CAT_ERR_SHIFT 1
+#define FPM_EV_MASK_DMA_ERR_SHIFT 0
+
+#define FPM_REV1_MAJOR_SHIFT 8
+#define FPM_REV1_MINOR_SHIFT 0
+
+#define FPM_REV2_INTEG_SHIFT 16
+#define FPM_REV2_ERR_SHIFT 8
+#define FPM_REV2_CFG_SHIFT 0
+
+#define FPM_TS_INT_SHIFT 16
+
+#define FPM_PORT_FM_CTL_PORTID_SHIFT 24
+
+#define FPM_PS_FM_CTL_SEL_SHIFT 30
+#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16
+
+/* Interrupts defines */
+#define FPM_EVENT_FM_CTL_0 0x00008000
+#define FPM_EVENT_FM_CTL 0x0000FF00
+#define FPM_EVENT_FM_CTL_BRK 0x00000080
+
+/* others */
+#define FPM_MAX_DISP_LIMIT 31
+
+/**************************************************************************//**
+ @Description BMI defines
+*//***************************************************************************/
+/* masks */
+#define BMI_INIT_START 0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000
+
+#define BMI_NUM_OF_TASKS_MASK 0x3F000000 /* port */
+#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000
+#define BMI_NUM_OF_DMAS_MASK 0x00000F00
+#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F
+#define BMI_FIFO_SIZE_MASK 0x000003FF /* port */
+#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000
+#define BMI_CFG2_DMAS_MASK 0x0000003F
+
+#define BMI_TOTAL_FIFO_SIZE_MASK 0x07FF0000
+#define BMI_TOTAL_NUM_OF_TASKS_MASK 0x007F0000
+/* shifts */
+#define BMI_CFG2_TASKS_SHIFT 16
+#define BMI_CFG2_DMAS_SHIFT 0
+#define BMI_CFG1_FIFO_SIZE_SHIFT 16
+#define BMI_FIFO_SIZE_SHIFT 0
+#define BMI_EXTRA_FIFO_SIZE_SHIFT 16
+#define BMI_NUM_OF_TASKS_SHIFT 24
+#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16
+#define BMI_NUM_OF_DMAS_SHIFT 8
+#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0
+
+/* others */
+#define BMI_FIFO_ALIGN 0x100
+
+/**************************************************************************//**
+ @Description QMI defines
+*//***************************************************************************/
+/* masks */
+#define QMI_CFG_ENQ_EN 0x80000000
+#define QMI_CFG_DEQ_EN 0x40000000
+#define QMI_CFG_EN_COUNTERS 0x10000000
+#define QMI_CFG_SOFT_RESET 0x01000000
+#define QMI_CFG_DEQ_MASK 0x0000003F
+#define QMI_CFG_ENQ_MASK 0x00003F00
+
+#define QMI_GS_HALT_NOT_BUSY 0x00000002
+
+#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000
+#define QMI_INTR_EN_SINGLE_ECC 0x80000000
+
+/* shifts */
+#define QMI_CFG_ENQ_SHIFT 8
+#define QMI_TAPC_TAP 22
+
+/**************************************************************************//**
+ @Description IRAM defines
+*//***************************************************************************/
+/* masks */
+#define IRAM_IADD_AIE 0x80000000
+#define IRAM_READY 0x80000000
+
+/**************************************************************************//**
+ @Description TRB defines
+*//***************************************************************************/
+/* masks */
+#define TRB_TCRH_RESET 0x04000000
+#define TRB_TCRH_ENABLE_COUNTERS 0x84008000
+#define TRB_TCRH_DISABLE_COUNTERS 0x8400C000
+#define TRB_TCRL_RESET 0x20000000
+#define TRB_TCRL_UTIL 0x00000460
+
+typedef struct {
+ void (*f_Isr) (t_Handle h_Arg, uint32_t event);
+ t_Handle h_SrcHandle;
+} t_FmanCtrlIntrSrc;
+
+typedef struct
+{
+ /* uint8_t numOfPartitions; */
+ bool resetOnInit;
+ t_FmThresholds thresholds;
+ e_FmDmaCacheOverride dmaCacheOverride;
+ e_FmDmaAidMode dmaAidMode;
+ bool dmaAidOverride;
+ uint8_t dmaAxiDbgNumOfBeats;
+ uint8_t dmaCamNumOfEntries;
+ uint32_t dmaWatchdog;
+ t_FmDmaThresholds dmaCommQThresholds;
+ t_FmDmaThresholds dmaWriteBufThresholds;
+ t_FmDmaThresholds dmaReadBufThresholds;
+ uint32_t dmaSosEmergency;
+ e_FmDmaDbgCntMode dmaDbgCntMode;
+ bool dmaStopOnBusError;
+ bool dmaEnEmergency;
+ t_FmDmaEmergency dmaEmergency;
+ bool dmaEnEmergencySmoother;
+ uint32_t dmaEmergencySwitchCounter;
+ bool haltOnExternalActivation;
+ bool haltOnUnrecoverableEccError;
+ e_FmCatastrophicErr catastrophicErr;
+ e_FmDmaErr dmaErr;
+ bool enMuramTestMode;
+ bool enIramTestMode;
+ bool externalEccRamsEnable;
+ uint16_t tnumAgingPeriod;
+ t_FmFirmwareParams firmware;
+ bool fwVerify;
+ uint32_t userSetExceptions;
+} t_FmDriverParam;
+
+typedef void (t_FmanCtrlIsr)( t_Handle h_Fm, uint32_t event);
+
+typedef struct
+{
+/***************************/
+/* Master/Guest parameters */
+ uint8_t fmId;
+ e_FmPortType portsTypes[FM_MAX_NUM_OF_HW_PORT_IDS];
+ uint16_t fmClkFreq;
+ t_FmRevisionInfo revInfo;
+/**************************/
+/* Master Only parameters */
+/**************************/
+ bool enabledTimeStamp;
+ uint8_t count1MicroBit;
+ uint8_t totalNumOfTasks;
+ uint32_t totalFifoSize;
+ uint8_t maxNumOfOpenDmas;
+ uint8_t accumulatedNumOfTasks;
+ uint32_t accumulatedFifoSize;
+ uint8_t accumulatedNumOfOpenDmas;
+ uint8_t accumulatedNumOfDeqTnums;
+#ifdef FM_LOW_END_RESTRICTION
+ bool lowEndRestriction;
+#endif /* FM_LOW_END_RESTRICTION */
+ uint32_t exceptions;
+ int irq;
+ int errIrq;
+ bool ramsEccEnable;
+ bool explicitEnable;
+ bool internalCall;
+ uint8_t ramsEccOwners;
+ uint32_t extraFifoPoolSize;
+ uint8_t extraTasksPoolSize;
+ uint8_t extraOpenDmasPoolSize;
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ uint16_t portMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS];
+ uint16_t macMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS];
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ uint16_t portMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS];
+ uint16_t macMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS];
+} t_FmStateStruct;
+
+#if (DPAA_VERSION >= 11)
+typedef struct t_FmMapParam {
+ uint16_t profilesBase;
+ uint16_t numOfProfiles;
+ t_Handle h_FmPort;
+} t_FmMapParam;
+
+typedef struct t_FmAllocMng {
+ bool allocated;
+ uint8_t ownerId; /* guestId for KG in multi-partition only,
+ portId for PLCR in any environment */
+} t_FmAllocMng;
+
+typedef struct t_FmPcdSpEntry {
+ bool valid;
+ t_FmAllocMng profilesMng;
+} t_FmPcdSpEntry;
+
+typedef struct t_FmSp {
+ void *p_FmPcdStoragePrflRegs;
+ t_FmPcdSpEntry profiles[FM_VSP_MAX_NUM_OF_ENTRIES];
+ t_FmMapParam portsMapping[FM_MAX_NUM_OF_PORTS];
+} t_FmSp;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+
+typedef struct t_Fm
+{
+/***************************/
+/* Master/Guest parameters */
+/***************************/
+/* locals for recovery */
+ uintptr_t baseAddr;
+
+/* un-needed for recovery */
+ t_Handle h_Pcd;
+ char fmModuleName[MODULE_NAME_SIZE];
+ char fmIpcHandlerModuleName[FM_MAX_NUM_OF_GUESTS][MODULE_NAME_SIZE];
+ t_Handle h_IpcSessions[FM_MAX_NUM_OF_GUESTS];
+ t_FmIntrSrc intrMng[e_FM_EV_DUMMY_LAST]; /* FM exceptions user callback */
+ uint8_t guestId;
+/**************************/
+/* Master Only parameters */
+/**************************/
+/* locals for recovery */
+ t_FmFpmRegs *p_FmFpmRegs;
+ t_FmBmiRegs *p_FmBmiRegs;
+ t_FmQmiRegs *p_FmQmiRegs;
+ t_FmDmaRegs *p_FmDmaRegs;
+ t_FmExceptionsCallback *f_Exception;
+ t_FmBusErrorCallback *f_BusError;
+ t_Handle h_App; /* Application handle */
+ t_Handle h_Spinlock;
+ bool recoveryMode;
+ t_FmStateStruct *p_FmStateStruct;
+#if (DPAA_VERSION >= 11)
+ t_FmSp *p_FmSp;
+ uint8_t partNumOfVSPs;
+ uint8_t partVSPBase;
+ uintptr_t vspBaseAddr;
+#endif /* (DPAA_VERSION >= 11) */
+
+/* un-needed for recovery */
+ t_Handle h_FmMuram;
+ uint64_t fmMuramPhysBaseAddr;
+ bool independentMode;
+ bool hcPortInitialized;
+ uintptr_t camBaseAddr; /* save for freeing */
+ uintptr_t resAddr;
+ uintptr_t fifoBaseAddr; /* save for freeing */
+ t_FmanCtrlIntrSrc fmanCtrlIntr[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; /* FM exceptions user callback */
+ bool usedEventRegs[FM_NUM_OF_FMAN_CTRL_EVENT_REGS];
+
+ t_FmDriverParam *p_FmDriverParam;
+} t_Fm;
+
+
+#endif /* __FM_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h
new file mode 100644
index 0000000..f39d5d9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_ipc.h
+
+ @Description FM Inter-Partition prototypes, structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_IPC_H
+#define __FM_IPC_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_IPC_grp FM Inter-Partition messaging Unit
+
+ @Description FM Inter-Partition messaging unit API definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description enum for defining MAC types
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description A structure of parameters for specifying a MAC.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint8_t id;
+ uint32_t enumType;
+} _PackedType t_FmIpcMacParams;
+
+/**************************************************************************//**
+ @Description A structure of parameters for specifying a MAC.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ t_FmIpcMacParams macParams;
+ uint16_t maxFrameLength;
+} _PackedType t_FmIpcMacMaxFrameParams;
+
+/**************************************************************************//**
+ @Description FM physical Address
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPhysAddr
+{
+ volatile uint8_t high;
+ volatile uint32_t low;
+} _PackedType t_FmIpcPhysAddr;
+
+
+typedef _Packed struct t_FmIpcPortOutInitParams {
+ uint8_t numOfTasks; /**< OUT */
+ uint8_t numOfExtraTasks; /**< OUT */
+ uint8_t numOfOpenDmas; /**< OUT */
+ uint8_t numOfExtraOpenDmas; /**< OUT */
+ uint32_t sizeOfFifo; /**< OUT */
+ uint32_t extraSizeOfFifo; /**< OUT */
+ t_FmIpcPhysAddr ipcPhysAddr; /**< OUT */
+} _PackedType t_FmIpcPortOutInitParams;
+
+/**************************************************************************//**
+ @Description Structure for IPC communication during FM_PORT_Init.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortInInitParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t enumPortType; /**< IN. Port type */
+ uint8_t boolIndependentMode;/**< IN. TRUE if FM Port operates in independent mode */
+ uint16_t liodnOffset; /**< IN. Port's requested resource */
+ uint8_t numOfTasks; /**< IN. Port's requested resource */
+ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */
+ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */
+ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */
+ uint32_t sizeOfFifo; /**< IN. Port's requested resource */
+ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+ uint16_t maxFrameLength; /**< IN. Port's max frame length. */
+ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1.
+ LIODN base for this port, to be
+ used together with LIODN offset. */
+} _PackedType t_FmIpcPortInInitParams;
+
+
+/**************************************************************************//**
+ @Description Structure for IPC communication between port and FM
+ regarding tasks and open DMA resources management.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortRsrcParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t val; /**< IN. Port's requested resource */
+ uint32_t extra; /**< IN. Port's requested resource */
+ uint8_t boolInitialConfig;
+} _PackedType t_FmIpcPortRsrcParams;
+
+
+/**************************************************************************//**
+ @Description Structure for IPC communication between port and FM
+ regarding tasks and open DMA resources management.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortFifoParams {
+ t_FmIpcPortRsrcParams rsrcParams;
+ uint32_t enumPortType;
+ uint8_t boolIndependentMode;
+ uint8_t deqPipelineDepth;
+ uint8_t numOfPools;
+ uint16_t secondLargestBufSize;
+ uint16_t largestBufSize;
+ uint8_t boolInitialConfig;
+} _PackedType t_FmIpcPortFifoParams;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Free.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortFreeParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t enumPortType; /**< IN. Port type */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+} _PackedType t_FmIpcPortFreeParams;
+
+/**************************************************************************//**
+ @Description Structure for defining DMA status
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcDmaStatus {
+ uint8_t boolCmqNotEmpty; /**< Command queue is not empty */
+ uint8_t boolBusError; /**< Bus error occurred */
+ uint8_t boolReadBufEccError; /**< Double ECC error on buffer Read */
+ uint8_t boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */
+ uint8_t boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */
+ uint8_t boolSinglePortEccError; /**< Single port ECC error from FM side */
+} _PackedType t_FmIpcDmaStatus;
+
+typedef _Packed struct t_FmIpcRegisterIntr
+{
+ uint8_t guestId; /* IN */
+ uint32_t event; /* IN */
+} _PackedType t_FmIpcRegisterIntr;
+
+typedef _Packed struct t_FmIpcIsr
+{
+ uint8_t boolErr; /* IN */
+ uint32_t pendingReg; /* IN */
+} _PackedType t_FmIpcIsr;
+
+/**************************************************************************//**
+ @Description structure for returning FM parameters
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcParams {
+ uint16_t fmClkFreq; /**< OUT: FM Clock frequency */
+ uint8_t majorRev; /**< OUT: FM Major revision */
+ uint8_t minorRev; /**< OUT: FM Minor revision */
+} _PackedType t_FmIpcParams;
+
+
+/**************************************************************************//**
+ @Description structure for returning Fman Ctrl Code revision information
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcFmanCtrlCodeRevisionInfo {
+ uint16_t packageRev; /**< OUT: Package revision */
+ uint8_t majorRev; /**< OUT: Major revision */
+ uint8_t minorRev; /**< OUT: Minor revision */
+} _PackedType t_FmIpcFmanCtrlCodeRevisionInfo;
+
+/**************************************************************************//**
+ @Description Structure for defining Fm number of Fman controlers
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortNumOfFmanCtrls {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint8_t numOfFmanCtrls; /**< IN. Port type */
+ t_FmFmanCtrl orFmanCtrl; /**< IN. fman controller for order restoration*/
+} t_FmIpcPortNumOfFmanCtrls;
+
+/**************************************************************************//**
+ @Description structure for setting Fman contriller events
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcFmanEvents {
+ uint8_t eventRegId; /**< IN: Fman controller event register id */
+ uint32_t enableEvents; /**< IN/OUT: required enabled events mask */
+} _PackedType t_FmIpcFmanEvents;
+
+typedef _Packed struct t_FmIpcResourceAllocParams {
+ uint8_t guestId;
+ uint16_t base;
+ uint16_t num;
+}_PackedType t_FmIpcResourceAllocParams;
+
+typedef _Packed struct t_FmIpcVspSetPortWindow {
+ uint8_t hardwarePortId;
+ uint8_t baseStorageProfile;
+ uint8_t log2NumOfProfiles;
+}_PackedType t_FmIpcVspSetPortWindow;
+
+typedef _Packed struct t_FmIpcSetCongestionGroupPfcPriority {
+ uint32_t congestionGroupId;
+ uint8_t priorityBitMap;
+}_PackedType t_FmIpcSetCongestionGroupPfcPriority;
+
+#define FM_IPC_MAX_REPLY_BODY_SIZE 20
+#define FM_IPC_MAX_REPLY_SIZE (FM_IPC_MAX_REPLY_BODY_SIZE + sizeof(uint32_t))
+#define FM_IPC_MAX_MSG_SIZE 30
+
+typedef _Packed struct t_FmIpcMsg
+{
+ uint32_t msgId;
+ uint8_t msgBody[FM_IPC_MAX_MSG_SIZE];
+} _PackedType t_FmIpcMsg;
+
+typedef _Packed struct t_FmIpcReply
+{
+ uint32_t error;
+ uint8_t replyBody[FM_IPC_MAX_REPLY_BODY_SIZE];
+} _PackedType t_FmIpcReply;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***************************************************************************/
+/************************ FRONT-END-TO-BACK-END*****************************/
+/***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_GET_TIMESTAMP_SCALE
+
+ @Description Used by FM front-end.
+
+ @Param[out] uint32_t Pointer
+*//***************************************************************************/
+#define FM_GET_TIMESTAMP_SCALE 1
+
+/**************************************************************************//**
+ @Function FM_GET_COUNTER
+
+ @Description Used by FM front-end.
+
+ @Param[in/out] t_FmIpcGetCounter Pointer
+*//***************************************************************************/
+#define FM_GET_COUNTER 2
+
+/**************************************************************************//**
+ @Function FM_GET_SET_PORT_PARAMS
+
+ @Description Used by FM front-end for the PORT module in order to set and get
+ parameters in/from master FM module on FM PORT initialization time.
+
+ @Param[in/out] t_FmIcPortInitParams Pointer
+*//***************************************************************************/
+#define FM_GET_SET_PORT_PARAMS 4
+
+/**************************************************************************//**
+ @Function FM_FREE_PORT
+
+ @Description Used by FM front-end for the PORT module when a port is freed
+ to free all FM PORT resources.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_FREE_PORT 5
+
+/**************************************************************************//**
+ @Function FM_RESET_MAC
+
+ @Description Used by front-end for the MAC module to reset the MAC registers
+
+ @Param[in] t_FmIpcMacParams Pointer .
+*//***************************************************************************/
+#define FM_RESET_MAC 6
+
+/**************************************************************************//**
+ @Function FM_RESUME_STALLED_PORT
+
+ @Description Used by FM front-end for the PORT module in order to
+ release a stalled FM Port.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_RESUME_STALLED_PORT 7
+
+/**************************************************************************//**
+ @Function FM_IS_PORT_STALLED
+
+ @Description Used by FM front-end for the PORT module in order to check whether
+ an FM port is stalled.
+
+ @Param[in/out] t_FmIcPortIsStalled Pointer
+*//***************************************************************************/
+#define FM_IS_PORT_STALLED 8
+
+/**************************************************************************//**
+ @Function FM_GET_PARAMS
+
+ @Description Used by FM front-end for the PORT module in order to dump
+ return FM parameters.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_GET_PARAMS 10
+
+/**************************************************************************//**
+ @Function FM_REGISTER_INTR
+
+ @Description Used by FM front-end to register an interrupt handler to
+ be called upon interrupt for guest.
+
+ @Param[out] t_FmIpcRegisterIntr Pointer
+*//***************************************************************************/
+#define FM_REGISTER_INTR 11
+
+/**************************************************************************//**
+ @Function FM_DMA_STAT
+
+ @Description Used by FM front-end to read the FM DMA status.
+
+ @Param[out] t_FmIpcDmaStatus Pointer
+*//***************************************************************************/
+#define FM_DMA_STAT 13
+
+/**************************************************************************//**
+ @Function FM_ALLOC_FMAN_CTRL_EVENT_REG
+
+ @Description Used by FM front-end to allocate event register.
+
+ @Param[out] Event register id Pointer
+*//***************************************************************************/
+#define FM_ALLOC_FMAN_CTRL_EVENT_REG 14
+
+/**************************************************************************//**
+ @Function FM_FREE_FMAN_CTRL_EVENT_REG
+
+ @Description Used by FM front-end to free locate event register.
+
+ @Param[in] uint8_t Pointer - Event register id
+*//***************************************************************************/
+#define FM_FREE_FMAN_CTRL_EVENT_REG 15
+
+/**************************************************************************//**
+ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE
+
+ @Description Used by FM front-end to enable events in the FPM
+ Fman controller event register.
+
+ @Param[in] t_FmIpcFmanEvents Pointer
+*//***************************************************************************/
+#define FM_SET_FMAN_CTRL_EVENTS_ENABLE 16
+
+/**************************************************************************//**
+ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE
+
+ @Description Used by FM front-end to enable events in the FPM
+ Fman controller event register.
+
+ @Param[in/out] t_FmIpcFmanEvents Pointer
+*//***************************************************************************/
+#define FM_GET_FMAN_CTRL_EVENTS_ENABLE 17
+
+/**************************************************************************//**
+ @Function FM_SET_MAC_MAX_FRAME
+
+ @Description Used by FM front-end to set MAC's MTU/RTU's in
+ back-end.
+
+ @Param[in/out] t_FmIpcMacMaxFrameParams Pointer
+*//***************************************************************************/
+#define FM_SET_MAC_MAX_FRAME 18
+
+/**************************************************************************//**
+ @Function FM_GET_PHYS_MURAM_BASE
+
+ @Description Used by FM front-end in order to get MURAM base address
+
+ @Param[in/out] t_FmIpcPhysAddr Pointer
+*//***************************************************************************/
+#define FM_GET_PHYS_MURAM_BASE 19
+
+/**************************************************************************//**
+ @Function FM_MASTER_IS_ALIVE
+
+ @Description Used by FM front-end in order to verify Master is up
+
+ @Param[in/out] bool
+*//***************************************************************************/
+#define FM_MASTER_IS_ALIVE 20
+
+#define FM_ENABLE_RAM_ECC 21
+#define FM_DISABLE_RAM_ECC 22
+#define FM_SET_NUM_OF_FMAN_CTRL 23
+#define FM_SET_SIZE_OF_FIFO 24
+#define FM_SET_NUM_OF_TASKS 25
+#define FM_SET_NUM_OF_OPEN_DMAS 26
+#define FM_VSP_ALLOC 27
+#define FM_VSP_FREE 28
+#define FM_VSP_SET_PORT_WINDOW 29
+#define FM_GET_FMAN_CTRL_CODE_REV 30
+#define FM_SET_CONG_GRP_PFC_PRIO 31
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+#define FM_10G_TX_ECC_WA 100
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/***************************************************************************/
+/************************ BACK-END-TO-FRONT-END*****************************/
+/***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_GUEST_ISR
+
+ @Description Used by FM back-end to report an interrupt to the front-end.
+
+ @Param[out] t_FmIpcIsr Pointer
+*//***************************************************************************/
+#define FM_GUEST_ISR 1
+
+
+
+/** @} */ /* end of FM_IPC_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_IPC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c
new file mode 100644
index 0000000..a1cbe3f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 FM_muram.c
+
+ @Description FM MURAM ...
+*//***************************************************************************/
+#include "error_ext.h"
+#include "std_ext.h"
+#include "mm_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_MURAM
+
+
+typedef struct
+{
+ t_Handle h_Mem;
+ uintptr_t baseAddr;
+ uint32_t size;
+} t_FmMuram;
+
+
+void FmMuramClear(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN(h_FmMuram, E_INVALID_HANDLE);
+ IOMemSet32(UINT_TO_PTR(p_FmMuram->baseAddr), 0, p_FmMuram->size);
+}
+
+
+t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size)
+{
+ t_Handle h_Mem;
+ t_FmMuram *p_FmMuram;
+
+ if (!baseAddress)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress 0 is not supported"));
+ return NULL;
+ }
+
+ if (baseAddress%4)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress not 4 bytes aligned!"));
+ return NULL;
+ }
+
+ /* Allocate FM MURAM structure */
+ p_FmMuram = (t_FmMuram *) XX_Malloc(sizeof(t_FmMuram));
+ if (!p_FmMuram)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MURAM driver structure"));
+ return NULL;
+ }
+ memset(p_FmMuram, 0, sizeof(t_FmMuram));
+
+
+ if ((MM_Init(&h_Mem, baseAddress, size) != E_OK) || (!h_Mem))
+ {
+ XX_Free(p_FmMuram);
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM partition!!!"));
+ return NULL;
+ }
+
+ /* Initialize FM MURAM parameters which will be kept by the driver */
+ p_FmMuram->baseAddr = baseAddress;
+ p_FmMuram->size = size;
+ p_FmMuram->h_Mem = h_Mem;
+
+ return p_FmMuram;
+}
+
+t_Error FM_MURAM_Free(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ if (p_FmMuram->h_Mem)
+ MM_Free(p_FmMuram->h_Mem);
+
+ XX_Free(h_FmMuram);
+
+ return E_OK;
+}
+
+void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+ uintptr_t addr;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL);
+
+ addr = (uintptr_t)MM_Get(p_FmMuram->h_Mem, size, align ,"FM MURAM");
+
+ if (addr == ILLEGAL_BASE)
+ return NULL;
+
+ return UINT_TO_PTR(addr);
+}
+
+void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+ uintptr_t addr;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL);
+
+ addr = (uintptr_t)MM_GetForce(p_FmMuram->h_Mem, base, size, "FM MURAM");
+
+ if (addr == ILLEGAL_BASE)
+ return NULL;
+
+ return UINT_TO_PTR(addr);
+}
+
+t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmMuram, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmMuram->h_Mem, E_INVALID_HANDLE);
+
+ if (MM_Put(p_FmMuram->h_Mem, PTR_TO_UINT(ptr)) == 0)
+ RETURN_ERROR(MINOR, E_INVALID_ADDRESS, ("memory pointer!!!"));
+
+ return E_OK;
+}
+
+uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, 0);
+
+ return MM_GetFreeMemSize(p_FmMuram->h_Mem);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h
new file mode 100644
index 0000000..6476c7a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h
@@ -0,0 +1,1103 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_common.h
+
+ @Description FM internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_COMMON_H
+#define __FM_COMMON_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_ext.h"
+#include "fm_port_ext.h"
+
+
+#define e_FM_PORT_TYPE_OH_HOST_COMMAND e_FM_PORT_TYPE_DUMMY
+
+#define CLS_PLAN_NUM_PER_GRP 8
+
+#define IP_OFFLOAD_PACKAGE_NUMBER 106
+
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+typedef enum e_FmEventModules{
+ e_FM_MOD_PRS, /**< Parser event */
+ e_FM_MOD_KG, /**< Keygen event */
+ e_FM_MOD_PLCR, /**< Policer event */
+ e_FM_MOD_10G_MAC, /**< 10G MAC event */
+ e_FM_MOD_1G_MAC, /**< 1G MAC event */
+ e_FM_MOD_TMR, /**< Timer event */
+ e_FM_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */
+ e_FM_MOD_MACSEC,
+ e_FM_MOD_DUMMY_LAST
+} e_FmEventModules;
+
+/**************************************************************************//**
+ @Description Enum for interrupts types
+*//***************************************************************************/
+typedef enum e_FmIntrType {
+ e_FM_INTR_TYPE_ERR,
+ e_FM_INTR_TYPE_NORMAL
+} e_FmIntrType;
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+typedef enum e_FmInterModuleEvent
+{
+ e_FM_EV_PRS = 0, /**< Parser event */
+ e_FM_EV_ERR_PRS, /**< Parser error event */
+ e_FM_EV_KG, /**< Keygen event */
+ e_FM_EV_ERR_KG, /**< Keygen error event */
+ e_FM_EV_PLCR, /**< Policer event */
+ e_FM_EV_ERR_PLCR, /**< Policer error event */
+ e_FM_EV_ERR_10G_MAC0, /**< 10G MAC 0 error event */
+ e_FM_EV_ERR_10G_MAC1, /**< 10G MAC 1 error event */
+ e_FM_EV_ERR_1G_MAC0, /**< 1G MAC 0 error event */
+ e_FM_EV_ERR_1G_MAC1, /**< 1G MAC 1 error event */
+ e_FM_EV_ERR_1G_MAC2, /**< 1G MAC 2 error event */
+ e_FM_EV_ERR_1G_MAC3, /**< 1G MAC 3 error event */
+ e_FM_EV_ERR_1G_MAC4, /**< 1G MAC 4 error event */
+ e_FM_EV_ERR_1G_MAC5, /**< 1G MAC 5 error event */
+ e_FM_EV_ERR_1G_MAC6, /**< 1G MAC 6 error event */
+ e_FM_EV_ERR_1G_MAC7, /**< 1G MAC 7 error event */
+ e_FM_EV_ERR_MACSEC_MAC0,
+ e_FM_EV_TMR, /**< Timer event */
+ e_FM_EV_10G_MAC0, /**< 10G MAC 0 event (Magic packet detection)*/
+ e_FM_EV_10G_MAC1, /**< 10G MAC 1 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC0, /**< 1G MAC 0 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC1, /**< 1G MAC 1 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC2, /**< 1G MAC 2 (Magic packet detection)*/
+ e_FM_EV_1G_MAC3, /**< 1G MAC 3 (Magic packet detection)*/
+ e_FM_EV_1G_MAC4, /**< 1G MAC 4 (Magic packet detection)*/
+ e_FM_EV_1G_MAC5, /**< 1G MAC 5 (Magic packet detection)*/
+ e_FM_EV_1G_MAC6, /**< 1G MAC 6 (Magic packet detection)*/
+ e_FM_EV_1G_MAC7, /**< 1G MAC 7 (Magic packet detection)*/
+ e_FM_EV_MACSEC_MAC0, /**< MACSEC MAC 0 event */
+ e_FM_EV_FMAN_CTRL_0, /**< Fman controller event 0 */
+ e_FM_EV_FMAN_CTRL_1, /**< Fman controller event 1 */
+ e_FM_EV_FMAN_CTRL_2, /**< Fman controller event 2 */
+ e_FM_EV_FMAN_CTRL_3, /**< Fman controller event 3 */
+ e_FM_EV_DUMMY_LAST
+} e_FmInterModuleEvent;
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description PCD KG scheme registers
+*//***************************************************************************/
+typedef _Packed struct t_FmPcdPlcrProfileRegs {
+ volatile uint32_t fmpl_pemode; /* 0x090 FMPL_PEMODE - FM Policer Profile Entry Mode*/
+ volatile uint32_t fmpl_pegnia; /* 0x094 FMPL_PEGNIA - FM Policer Profile Entry GREEN Next Invoked Action*/
+ volatile uint32_t fmpl_peynia; /* 0x098 FMPL_PEYNIA - FM Policer Profile Entry YELLOW Next Invoked Action*/
+ volatile uint32_t fmpl_pernia; /* 0x09C FMPL_PERNIA - FM Policer Profile Entry RED Next Invoked Action*/
+ volatile uint32_t fmpl_pecir; /* 0x0A0 FMPL_PECIR - FM Policer Profile Entry Committed Information Rate*/
+ volatile uint32_t fmpl_pecbs; /* 0x0A4 FMPL_PECBS - FM Policer Profile Entry Committed Burst Size*/
+ volatile uint32_t fmpl_pepepir_eir; /* 0x0A8 FMPL_PEPIR_EIR - FM Policer Profile Entry Peak/Excess Information Rate*/
+ volatile uint32_t fmpl_pepbs_ebs; /* 0x0AC FMPL_PEPBS_EBS - FM Policer Profile Entry Peak/Excess Information Rate*/
+ volatile uint32_t fmpl_pelts; /* 0x0B0 FMPL_PELTS - FM Policer Profile Entry Last TimeStamp*/
+ volatile uint32_t fmpl_pects; /* 0x0B4 FMPL_PECTS - FM Policer Profile Entry Committed Token Status*/
+ volatile uint32_t fmpl_pepts_ets; /* 0x0B8 FMPL_PEPTS_ETS - FM Policer Profile Entry Peak/Excess Token Status*/
+ volatile uint32_t fmpl_pegpc; /* 0x0BC FMPL_PEGPC - FM Policer Profile Entry GREEN Packet Counter*/
+ volatile uint32_t fmpl_peypc; /* 0x0C0 FMPL_PEYPC - FM Policer Profile Entry YELLOW Packet Counter*/
+ volatile uint32_t fmpl_perpc; /* 0x0C4 FMPL_PERPC - FM Policer Profile Entry RED Packet Counter */
+ volatile uint32_t fmpl_perypc; /* 0x0C8 FMPL_PERYPC - FM Policer Profile Entry Recolored YELLOW Packet Counter*/
+ volatile uint32_t fmpl_perrpc; /* 0x0CC FMPL_PERRPC - FM Policer Profile Entry Recolored RED Packet Counter*/
+ volatile uint32_t fmpl_res1[12]; /* 0x0D0-0x0FF Reserved */
+} _PackedType t_FmPcdPlcrProfileRegs;
+
+
+typedef _Packed struct t_FmPcdCcCapwapReassmTimeoutParams {
+ volatile uint32_t portIdAndCapwapReassmTbl;
+ volatile uint32_t fqidForTimeOutFrames;
+ volatile uint32_t timeoutRequestTime;
+}_PackedType t_FmPcdCcCapwapReassmTimeoutParams;
+
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/
+typedef uint32_t t_FmFmanCtrl;
+
+#define FPM_PORT_FM_CTL1 0x00000001
+#define FPM_PORT_FM_CTL2 0x00000002
+
+
+
+typedef struct t_FmPcdCcFragScratchPoolCmdParams {
+ uint32_t numOfBuffers;
+ uint8_t bufferPoolId;
+} t_FmPcdCcFragScratchPoolCmdParams;
+
+typedef struct t_FmPcdCcIpReassmTimeoutParams {
+ bool activate;
+ uint8_t tsbs;
+ uint32_t iprcpt;
+} t_FmPcdCcIpReassmTimeoutParams;
+
+typedef struct {
+ uint8_t baseEntry;
+ uint16_t numOfClsPlanEntries;
+ uint32_t vectors[FM_PCD_MAX_NUM_OF_CLS_PLANS];
+} t_FmPcdKgInterModuleClsPlanSet;
+
+/**************************************************************************//**
+ @Description Structure for binding a port to keygen schemes.
+*//***************************************************************************/
+typedef struct t_FmPcdKgInterModuleBindPortToSchemes {
+ uint8_t hardwarePortId;
+ uint8_t netEnvId;
+ bool useClsPlan; /**< TRUE if this port uses the clsPlan mechanism */
+ uint8_t numOfSchemes;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+} t_FmPcdKgInterModuleBindPortToSchemes;
+
+typedef struct {
+ uint32_t nextCcNodeInfo;
+ t_List node;
+} t_CcNodeInfo;
+
+typedef struct
+{
+ t_Handle h_CcNode;
+ uint16_t index;
+ t_List node;
+}t_CcNodeInformation;
+#define CC_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInformation, node)
+
+typedef struct
+{
+ t_Handle h_Manip;
+ t_List node;
+}t_ManipInfo;
+#define CC_NEXT_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInfo, node)
+
+typedef struct {
+ uint32_t type;
+ uint8_t prOffset;
+ uint16_t dataOffset;
+ // uint8_t poolIndex;
+ // uint8_t poolIdForManip;
+ uint8_t numOfTasks;
+ uint8_t numOfExtraTasks;
+ uint8_t hardwarePortId;
+ t_FmRevisionInfo revInfo;
+ uint32_t nia;
+} t_GetCcParams;
+
+typedef struct {
+ uint32_t type;
+ int psoSize;
+ uint32_t nia;
+ t_FmFmanCtrl orFmanCtrl;
+ bool overwrite;
+} t_SetCcParams;
+
+typedef struct {
+ t_GetCcParams getCcParams;
+ t_SetCcParams setCcParams;
+} t_FmPortGetSetCcParams;
+
+
+static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag)
+{
+ uint32_t intFlags;
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+ else
+ intFlags = XX_DisableAllIntr();
+
+ if (*p_Flag)
+ {
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ else
+ XX_RestoreAllIntr(intFlags);
+ return FALSE;
+ }
+ *p_Flag = TRUE;
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ else
+ XX_RestoreAllIntr(intFlags);
+
+ return TRUE;
+}
+
+#define RELEASE_LOCK(_flag) _flag = FALSE;
+
+/**************************************************************************//**
+ @Collection Defines used for manipulation CC and BMI
+ @{
+*//***************************************************************************/
+#define INTERNAL_CONTEXT_OFFSET 0x80000000
+#define OFFSET_OF_PR 0x40000000
+//#define BUFFER_POOL_ID_FOR_MANIP 0x20000000
+#define NUM_OF_TASKS 0x10000000
+#define OFFSET_OF_DATA 0x08000000
+#define HW_PORT_ID 0x04000000
+#define FM_REV 0x02000000
+#define GET_NIA_FPNE 0x01000000
+#define GET_NIA_PNDN 0x00800000
+#define NUM_OF_EXTRA_TASKS 0x00400000
+
+#define UPDATE_NIA_PNEN 0x80000000
+#define UPDATE_PSO 0x40000000
+#define UPDATE_NIA_PNDN 0x20000000
+#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY 0x10000000
+#define UPDATE_NIA_FENE 0x04000000
+#define UPDATE_NIA_CMNE 0x02000000
+#define UPDATE_NIA_FPNE 0x01000000
+/* @} */
+
+/**************************************************************************//**
+ @Collection Defines used for manipulation CC and CC
+ @{
+*//***************************************************************************/
+#define UPDATE_NIA_ENQ_WITHOUT_DMA 0x80000000
+#define UPDATE_CC_WITH_TREE 0x40000000
+#define UPDATE_CC_WITH_DELETE_TREE 0x20000000
+#define UPDATE_KG_NIA_CC_WA 0x10000000
+#define UPDATE_KG_OPT_MODE 0x08000000
+#define UPDATE_KG_NIA 0x04000000
+/* @} */
+
+#define FM_MAX_NUM_OF_PORTS (FM_MAX_NUM_OF_OH_PORTS + \
+ FM_MAX_NUM_OF_1G_RX_PORTS + \
+ FM_MAX_NUM_OF_10G_RX_PORTS + \
+ FM_MAX_NUM_OF_1G_TX_PORTS + \
+ FM_MAX_NUM_OF_10G_TX_PORTS)
+
+#define MODULE_NAME_SIZE 30
+#define DUMMY_PORT_ID 0
+
+#define FM_LIODN_OFFSET_MASK 0x3FF
+
+/**************************************************************************//**
+ @Description NIA Description
+*//***************************************************************************/
+#define NIA_ENG_MASK 0x007C0000
+#define NIA_AC_MASK 0x0003ffff
+
+#define NIA_ORDER_RESTOR 0x00800000
+#define NIA_ENG_FM_CTL 0x00000000
+#define NIA_ENG_PRS 0x00440000
+#define NIA_ENG_KG 0x00480000
+#define NIA_ENG_PLCR 0x004C0000
+#define NIA_ENG_BMI 0x00500000
+#define NIA_ENG_QMI_ENQ 0x00540000
+#define NIA_ENG_QMI_DEQ 0x00580000
+
+#define NIA_FM_CTL_AC_CC 0x00000006
+#define NIA_FM_CTL_AC_HC 0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A
+#define NIA_FM_CTL_AC_FRAG 0x0000000e
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER 0x00000010
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME 0x00000018
+#define NIA_FM_CTL_AC_POST_BMI_FETCH 0x00000012
+#define NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME 0x0000001A
+#define NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME 0x0000001E
+#define NIA_FM_CTL_AC_POST_BMI_ENQ_ORR 0x00000014
+#define NIA_FM_CTL_AC_POST_BMI_ENQ 0x00000022
+#define NIA_FM_CTL_AC_PRE_CC 0x00000020
+#define NIA_FM_CTL_AC_POST_TX 0x00000024
+
+#define NIA_BMI_AC_ENQ_FRAME 0x00000002
+#define NIA_BMI_AC_TX_RELEASE 0x000002C0
+#define NIA_BMI_AC_RELEASE 0x000000C0
+#define NIA_BMI_AC_DISCARD 0x000000C1
+#define NIA_BMI_AC_TX 0x00000274
+#define NIA_BMI_AC_FETCH 0x00000208
+#define NIA_BMI_AC_MASK 0x000003FF
+#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c
+
+#define NIA_KG_DIRECT 0x00000100
+#define NIA_KG_CC_EN 0x00000200
+#define NIA_PLCR_ABSOLUTE 0x00008000
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202
+
+#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \
+ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
+#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \
+ (NIA_ENG_BMI | NIA_BMI_AC_DISCARD))
+
+#define NIA_IPR_DIRECT_SCHEME_IPV4_OFFSET 0x10
+#define NIA_IPR_DIRECT_SCHEME_IPV6_OFFSET 0x14
+
+/**************************************************************************//**
+ @Description Port Id defines
+*//***************************************************************************/
+#if (DPAA_VERSION == 10)
+#define BASE_OH_PORTID 1
+#else
+#define BASE_OH_PORTID 2
+#endif /* (DPAA_VERSION == 10) */
+#define BASE_1G_RX_PORTID 8
+#define BASE_10G_RX_PORTID 0x10
+#define BASE_1G_TX_PORTID 0x28
+#define BASE_10G_TX_PORTID 0x30
+
+#define FM_PCD_PORT_OH_BASE_INDX 0
+#define FM_PCD_PORT_1G_RX_BASE_INDX (FM_PCD_PORT_OH_BASE_INDX+FM_MAX_NUM_OF_OH_PORTS)
+#define FM_PCD_PORT_10G_RX_BASE_INDX (FM_PCD_PORT_1G_RX_BASE_INDX+FM_MAX_NUM_OF_1G_RX_PORTS)
+#define FM_PCD_PORT_1G_TX_BASE_INDX (FM_PCD_PORT_10G_RX_BASE_INDX+FM_MAX_NUM_OF_10G_RX_PORTS)
+#define FM_PCD_PORT_10G_TX_BASE_INDX (FM_PCD_PORT_1G_TX_BASE_INDX+FM_MAX_NUM_OF_1G_TX_PORTS)
+
+#if (FM_MAX_NUM_OF_OH_PORTS > 0)
+#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_OH_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id"))
+#else
+#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_1G_RX_PORTS > 0)
+#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_RX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id"))
+#else
+#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_10G_RX_PORTS > 0)
+#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_RX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id"))
+#else
+#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_1G_TX_PORTS > 0)
+#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_TX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id"))
+#else
+#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_10G_TX_PORTS > 0)
+#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_TX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id"))
+#else
+#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id"))
+#endif
+
+
+#define SW_PORT_ID_TO_HW_PORT_ID(_port, _type, _relativePortId) \
+switch (_type) { \
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): \
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): \
+ CHECK_PORT_ID_OH_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_OH_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_RX): \
+ CHECK_PORT_ID_1G_RX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_1G_RX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_RX_10G): \
+ CHECK_PORT_ID_10G_RX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_10G_RX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_TX): \
+ CHECK_PORT_ID_1G_TX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_1G_TX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_TX_10G): \
+ CHECK_PORT_ID_10G_TX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_10G_TX_PORTID + (_relativePortId)); \
+ break; \
+ default: \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); \
+ _port = 0; \
+ break; \
+}
+
+#define HW_PORT_ID_TO_SW_PORT_ID(_relativePortId, hardwarePortId) \
+{ if (((hardwarePortId) >= BASE_OH_PORTID) && \
+ ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_OH_PORTID); \
+ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID); \
+ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID); \
+ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID); \
+ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID); \
+ else { \
+ _relativePortId = (uint8_t)DUMMY_PORT_ID; \
+ ASSERT_COND(TRUE); \
+ } \
+}
+
+#define HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId) \
+do { \
+ if (((hardwarePortId) >= BASE_OH_PORTID) && ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_OH_PORTID+FM_PCD_PORT_OH_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID+FM_PCD_PORT_1G_RX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID+FM_PCD_PORT_10G_RX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID+FM_PCD_PORT_1G_TX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID+FM_PCD_PORT_10G_TX_BASE_INDX); \
+ else ASSERT_COND(FALSE); \
+} while (0)
+
+#define SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, swPortIndex) \
+do { \
+ if (((swPortIndex) >= FM_PCD_PORT_OH_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_1G_RX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_OH_BASE_INDX+BASE_OH_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_1G_RX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_RX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_RX_BASE_INDX+BASE_1G_RX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_10G_RX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_RX_BASE_INDX+BASE_10G_RX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_1G_TX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_TX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_TX_BASE_INDX+BASE_1G_TX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_10G_TX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_TX_BASE_INDX+BASE_10G_TX_PORTID); \
+ else ASSERT_COND(FALSE); \
+} while (0)
+
+#define BMI_FIFO_UNITS 0x100
+
+typedef struct {
+ void (*f_Isr) (t_Handle h_Arg);
+ t_Handle h_SrcHandle;
+ uint8_t guestId;
+} t_FmIntrSrc;
+
+#define ILLEGAL_HDR_NUM 0xFF
+#define NO_HDR_NUM FM_PCD_PRS_NUM_OF_HDRS
+
+#define IS_PRIVATE_HEADER(hdr) (((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \
+ ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2))
+#define IS_SPECIAL_HEADER(hdr) ((hdr) == HEADER_TYPE_MACSEC)
+
+#define GET_PRS_HDR_NUM(num, hdr) \
+switch (hdr) \
+{ case (HEADER_TYPE_ETH): num = 0; break; \
+ case (HEADER_TYPE_LLC_SNAP): num = 1; break; \
+ case (HEADER_TYPE_VLAN): num = 2; break; \
+ case (HEADER_TYPE_PPPoE): num = 3; break; \
+ case (HEADER_TYPE_MPLS): num = 4; break; \
+ case (HEADER_TYPE_IPv4): num = 5; break; \
+ case (HEADER_TYPE_IPv6): num = 6; break; \
+ case (HEADER_TYPE_GRE): num = 7; break; \
+ case (HEADER_TYPE_MINENCAP): num = 8; break; \
+ case (HEADER_TYPE_USER_DEFINED_L3): num = 9; break; \
+ case (HEADER_TYPE_TCP): num = 10; break; \
+ case (HEADER_TYPE_UDP): num = 11; break; \
+ case (HEADER_TYPE_IPSEC_AH): \
+ case (HEADER_TYPE_IPSEC_ESP): num = 12; break; \
+ case (HEADER_TYPE_SCTP): num = 13; break; \
+ case (HEADER_TYPE_DCCP): num = 14; break; \
+ case (HEADER_TYPE_USER_DEFINED_L4): num = 15; break; \
+ case (HEADER_TYPE_USER_DEFINED_SHIM1): \
+ case (HEADER_TYPE_USER_DEFINED_SHIM2): \
+ case (HEADER_TYPE_MACSEC): \
+ num = NO_HDR_NUM; break; \
+ default: \
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header for parser"));\
+ num = ILLEGAL_HDR_NUM; break; \
+}
+
+#define FM_PCD_MAX_NUM_OF_OPTIONS(clsPlanEntries) ((clsPlanEntries==256)? 8:((clsPlanEntries==128)? 7: ((clsPlanEntries==64)? 6: ((clsPlanEntries==32)? 5:0))))
+
+
+/**************************************************************************//**
+ @Description A structure for initializing a keygen classification plan group
+*//***************************************************************************/
+typedef struct t_FmPcdKgInterModuleClsPlanGrpParams {
+ uint8_t netEnvId; /* IN */
+ bool grpExists; /* OUT (unused in FmPcdKgBuildClsPlanGrp)*/
+ uint8_t clsPlanGrpId; /* OUT */
+ bool emptyClsPlanGrp; /* OUT */
+ uint8_t numOfOptions; /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+ protocolOpt_t options[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+ uint32_t optVectors[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+} t_FmPcdKgInterModuleClsPlanGrpParams;
+
+typedef struct t_FmPcdLock {
+ t_Handle h_Spinlock;
+ volatile bool flag;
+ t_List node;
+} t_FmPcdLock;
+#define FM_PCD_LOCK_OBJ(ptr) LIST_OBJECT(ptr, t_FmPcdLock, node)
+
+
+typedef t_Error (t_FmPortGetSetCcParamsCallback) (t_Handle h_FmPort,
+ t_FmPortGetSetCcParams *p_FmPortGetSetCcParams);
+
+
+/***********************************************************************/
+/* Common API for FM-PCD module */
+/***********************************************************************/
+t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd);
+uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr);
+uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum);
+uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId);
+void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId);
+void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId);
+uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv);
+void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId);
+uint32_t FmPcdLock(t_Handle h_FmPcd);
+void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags);
+bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+t_Error FmPcdFragHcScratchPoolInit(t_Handle h_FmPcd, uint8_t scratchBpid);
+t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl);
+t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl);
+bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd);
+bool FmPcdLockTryLockAll(t_Handle h_FmPcd);
+void FmPcdLockUnlockAll(t_Handle h_FmPcd);
+
+/***********************************************************************/
+/* Common API for FM-PCD KG module */
+/***********************************************************************/
+uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp);
+uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp);
+t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet);
+
+uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme);
+#if (DPAA_VERSION >= 11)
+bool FmPcdKgGetVspe(t_Handle h_Scheme);
+#endif /* (DPAA_VERSION >= 11) */
+uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId);
+void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId);
+t_Error FmPcdKgCheckInvalidateSchemeSw(t_Handle h_Scheme);
+t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPortToSchemes, uint32_t *p_SpReg, bool add);
+bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg);
+uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter);
+uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId);
+uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId);
+uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId);
+uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId);
+uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId);
+bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme);
+
+t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind);
+t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind);
+uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId);
+uint32_t FmPcdKgGetPointedOwners(t_Handle h_FmPcd, uint8_t schemeId);
+e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId);
+e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t schemeId);
+void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction);
+bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId);
+bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId);
+uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId);
+t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value);
+t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp);
+t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId);
+
+/***********************************************************************/
+/* Common API for FM-PCD parser module */
+/***********************************************************************/
+t_Error FmPcdPrsIncludePortInStatistics(t_Handle p_FmPcd, uint8_t hardwarePortId, bool include);
+
+/***********************************************************************/
+/* Common API for FM-PCD policer module */
+/***********************************************************************/
+t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles);
+t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId);
+bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId);
+uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId);
+uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter);
+uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId);
+uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile);
+t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,
+ e_FmPcdProfileTypeSelection profileType,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg);
+uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrGetPointedOwners(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+void FmPcdPlcrUpatePointedOwner(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool add);
+uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red);
+void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction);
+t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx,uint32_t requiredAction);
+
+/***********************************************************************/
+/* Common API for FM-PCD CC module */
+/***********************************************************************/
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode);
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode);
+uint32_t FmPcdCcGetNodeAddrOffset(t_Handle h_FmPcd, t_Handle h_Pointer);
+t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex);
+t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPCdCcKeyParams);
+t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask);
+t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPcdCcKeyParams);
+t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+t_Error FmPcdCcModiyNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, uint16_t keyIndex,t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer);
+t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree);
+void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams);
+t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree, t_Handle h_NetEnv, t_Handle h_IpReassemblyManip, bool schemes);
+t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_CcTree, uint32_t *p_Offset,t_Handle h_FmPort);
+t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_CcTree);
+
+/***********************************************************************/
+/* Common API for FM-PCD Manip module */
+/***********************************************************************/
+t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree, bool modify);
+uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip);
+
+/***********************************************************************/
+/* Common API for FM-Port module */
+/***********************************************************************/
+#if (DPAA_VERSION >= 11)
+typedef enum e_FmPortGprFuncType
+{
+ e_FM_PORT_GPR_EMPTY = 0,
+ e_FM_PORT_GPR_MURAM_PAGE
+} e_FmPortGprFuncType;
+
+t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value);
+#endif /* DPAA_VERSION >= 11) */
+t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_FmPortGetSetCcParams);
+uint8_t FmPortGetNetEnvId(t_Handle h_FmPort);
+uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort);
+uint32_t FmPortGetPcdEngines(t_Handle h_FmPort);
+void FmPortPcdKgSwUnbindClsPlanGrp (t_Handle h_FmPort);
+
+
+#if (DPAA_VERSION >= 11)
+t_Error FmPcdFrmReplicUpdate(t_Handle h_FmPcd, t_Handle h_FmPort, t_Handle h_FrmReplic);
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Function FmRegisterIntr
+
+ @Description Used to register an inter-module event handler to be processed by FM
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] mod The module that causes the event
+ @Param[in] modId Module id - if more than 1 instansiation of this
+ mode exists,0 otherwise.
+ @Param[in] intrType Interrupt type (error/normal) selection.
+ @Param[in] f_Isr The interrupt service routine.
+ @Param[in] h_Arg Argument to be passed to f_Isr.
+
+ @Return None.
+*//***************************************************************************/
+void FmRegisterIntr(t_Handle h_Fm,
+ e_FmEventModules mod,
+ uint8_t modId,
+ e_FmIntrType intrType,
+ void (*f_Isr) (t_Handle h_Arg),
+ t_Handle h_Arg);
+
+/**************************************************************************//**
+ @Function FmUnregisterIntr
+
+ @Description Used to un-register an inter-module event handler that was processed by FM
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] mod The module that causes the event
+ @Param[in] modId Module id - if more than 1 instansiation of this
+ mode exists,0 otherwise.
+ @Param[in] intrType Interrupt type (error/normal) selection.
+
+ @Return None.
+*//***************************************************************************/
+void FmUnregisterIntr(t_Handle h_Fm,
+ e_FmEventModules mod,
+ uint8_t modId,
+ e_FmIntrType intrType);
+
+/**************************************************************************//**
+ @Function FmRegisterFmCtlIntr
+
+ @Description Used to register to one of the fmCtl events in the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] eventRegId FmCtl event id (0-7).
+ @Param[in] f_Isr The interrupt service routine.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+void FmRegisterFmCtlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event));
+
+
+/**************************************************************************//**
+ @Description enum for defining MAC types
+*//***************************************************************************/
+typedef enum e_FmMacType {
+ e_FM_MAC_10G = 0, /**< 10G MAC */
+ e_FM_MAC_1G /**< 1G MAC */
+} e_FmMacType;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Init.
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+ Some fields are optional (depending on configuration) and
+ will be analized by the port and FM modules accordingly.
+*//***************************************************************************/
+typedef struct t_FmInterModulePortInitParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ e_FmPortType portType; /**< IN. Port type */
+ bool independentMode; /**< IN. TRUE if FM Port operates in independent mode */
+ uint16_t liodnOffset; /**< IN. Port's requested resource */
+ uint8_t numOfTasks; /**< IN. Port's requested resource */
+ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */
+ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */
+ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */
+ uint32_t sizeOfFifo; /**< IN. Port's requested resource */
+ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+ uint16_t maxFrameLength; /**< IN. Port's max frame length. */
+ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1.
+ LIODN base for this port, to be
+ used together with LIODN offset. */
+ t_FmPhysAddr fmMuramPhysBaseAddr;/**< OUT. FM-MURAM physical address*/
+} t_FmInterModulePortInitParams;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Free.
+*//***************************************************************************/
+typedef struct t_FmInterModulePortFreeParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ e_FmPortType portType; /**< IN. Port type */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+} t_FmInterModulePortFreeParams;
+
+/**************************************************************************//**
+ @Function FmGetPcdPrsBaseAddr
+
+ @Description Get the base address of the Parser from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPcdKgBaseAddr
+
+ @Description Get the base address of the Keygen from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPcdPlcrBaseAddr
+
+ @Description Get the base address of the Policer from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetMuramHandle
+
+ @Description Get the handle of the MURAM from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return MURAM module handle.
+*//***************************************************************************/
+t_Handle FmGetMuramHandle(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPhysicalMuramBase
+
+ @Description Get the physical base address of the MURAM from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] fmPhysAddr Physical MURAM base
+
+ @Return Physical base address.
+*//***************************************************************************/
+void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *fmPhysAddr);
+
+/**************************************************************************//**
+ @Function FmGetTimeStampScale
+
+ @Description Used internally by other modules in order to get the timeStamp
+ period as requested by the application.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return TimeStamp period in nanoseconds.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint32_t FmGetTimeStampScale(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmResumeStalledPort
+
+ @Description Used internally by FM port to release a stalled port.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId);
+
+/**************************************************************************//**
+ @Function FmIsPortStalled
+
+ @Description Used internally by FM port to read the port's status.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+ @Param[in] p_IsStalled A pointer to the boolean port stalled state
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled);
+
+/**************************************************************************//**
+ @Function FmResetMac
+
+ @Description Used by MAC driver to reset the MAC registers
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] type MAC type.
+ @Param[in] macId MAC id - according to type.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId);
+
+/**************************************************************************//**
+ @Function FmGetClockFreq
+
+ @Description Used by MAC driver to get the FM clock frequency
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return clock-freq on success; 0 otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint16_t FmGetClockFreq(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetId
+
+ @Description Used by PCD driver to read rhe FM id
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint8_t FmGetId(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetSetPortParams
+
+ @Description Used by FM-PORT driver to pass and receive parameters between
+ PORT and FM modules.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in,out] p_PortParams A structure of FM Port parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams);
+
+/**************************************************************************//**
+ @Function FmFreePortParams
+
+ @Description Used by FM-PORT driver to free port's resources within the FM.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in,out] p_PortParams A structure of FM Port parameters.
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams);
+
+/**************************************************************************//**
+ @Function FmSetNumOfRiscsPerPort
+
+ @Description Used by FM-PORT driver to pass parameter between
+ PORT and FM modules for working with number of RISC..
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId hardware port Id.
+ @Param[in] numOfFmanCtrls number of Fman Controllers.
+ @Param[in] orFmanCtrl Fman Controller for order restoration.
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t numOfFmanCtrls, t_FmFmanCtrl orFmanCtrl);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//*
+ @Function FmDumpPortRegs
+
+ @Description Dumps FM port registers which are part of FM common registers
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only FM_Init().
+*//***************************************************************************/
+t_Error FmDumpPortRegs(t_Handle h_Fm,uint8_t hardwarePortId);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd);
+void FmUnregisterPcd(t_Handle h_Fm);
+t_Handle FmGetPcdHandle(t_Handle h_Fm);
+t_Error FmEnableRamsEcc(t_Handle h_Fm);
+t_Error FmDisableRamsEcc(t_Handle h_Fm);
+void FmGetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo);
+t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId);
+void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId);
+void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents);
+uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId);
+void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event), t_Handle h_Arg);
+void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId);
+t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu);
+bool FmIsMaster(t_Handle h_Fm);
+uint8_t FmGetGuestId(t_Handle h_Fm);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+void FmMuramClear(t_Handle h_FmMuram);
+t_Error FmSetNumOfOpenDmas(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfOpenDmas,
+ uint8_t *p_NumOfExtraOpenDmas,
+ bool initialConfig);
+t_Error FmSetNumOfTasks(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfTasks,
+ uint8_t *p_NumOfExtraTasks,
+ bool initialConfig);
+t_Error FmSetSizeOfFifo(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint32_t *p_SizeOfFifo,
+ uint32_t *p_ExtraSizeOfFifo,
+ bool initialConfig);
+
+t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm,
+ uint32_t congestionGroupId,
+ uint8_t priorityBitMap);
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPAllocForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint8_t numOfStorageProfiles);
+
+t_Error FmVSPFreeForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId);
+
+t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile);
+
+uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm);
+#endif /* (DPAA_VERSION >= 11) */
+
+
+#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h
new file mode 100644
index 0000000..db2d60b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+#ifndef __FM_HC_H
+#define __FM_HC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "fsl_fman_kg.h"
+
+#define __ERR_MODULE__ MODULE_FM_PCD
+
+
+typedef struct t_FmHcParams {
+ t_Handle h_Fm;
+ t_Handle h_FmPcd;
+ t_FmPcdHcParams params;
+} t_FmHcParams;
+
+
+t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams);
+t_Handle FmGcGetHcPortDevH(t_Handle h_FmHc);
+void FmHcFree(t_Handle h_FmHc);
+t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc,
+ uint8_t memId);
+t_Error FmHcDumpRegs(t_Handle h_FmHc);
+
+void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd);
+
+t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc,
+ t_Handle h_Scheme,
+ struct fman_kg_scheme_regs *p_SchemeRegs,
+ bool updateCounter);
+t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme);
+t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams );
+t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams);
+t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result);
+t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set);
+t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t clsPlanGrpId);
+
+t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value);
+uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme);
+
+t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset);
+
+t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs);
+t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile);
+
+t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value);
+uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter);
+
+t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add);
+t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg);
+
+t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value);
+t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction);
+
+
+
+#endif /* __FM_HC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h
new file mode 100644
index 0000000..0675444
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * 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 fm_sp_common.h
+
+ @Description FM SP ...
+*//***************************************************************************/
+#ifndef __FM_SP_COMMON_H
+#define __FM_SP_COMMON_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_ext.h"
+#include "fm_pcd_ext.h"
+
+
+/* sizes */
+#define CAPWAP_FRAG_EXTRA_SPACE 32
+#define OFFSET_UNITS 16
+#define MAX_INT_OFFSET 240
+#define MAX_IC_SIZE 256
+#define MAX_EXT_OFFSET 496
+#define MAX_EXT_BUFFER_OFFSET 511
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_FM_SP_bufferPrefixContent_privDataSize 0
+#define DEFAULT_FM_SP_bufferPrefixContent_passPrsResult FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_dataAlign 64
+#define DEFAULT_FM_SP_dmaSwapData e_FM_DMA_NO_SWP
+#define DEFAULT_FM_SP_dmaIntContextCacheAttr e_FM_DMA_NO_STASH
+#define DEFAULT_FM_SP_dmaHeaderCacheAttr e_FM_DMA_NO_STASH
+#define DEFAULT_FM_SP_dmaScatterGatherCacheAttr e_FM_DMA_NO_STASH
+#define DEFAULT_FM_SP_dmaWriteOptimize TRUE
+#define DEFAULT_FM_SP_noScatherGather FALSE
+
+/**************************************************************************//**
+ @Description Registers bit fields
+*//***************************************************************************/
+#define FM_SP_EXT_BUF_POOL_EN_COUNTER 0x40000000
+#define FM_SP_EXT_BUF_POOL_VALID 0x80000000
+#define FM_SP_EXT_BUF_POOL_BACKUP 0x20000000
+#define FM_SP_DMA_ATTR_WRITE_OPTIMIZE 0x00100000
+#define FM_SP_SG_DISABLE 0x80000000
+
+/* shifts */
+#define FM_SP_EXT_BUF_POOL_ID_SHIFT 16
+#define FM_SP_POOL_DEP_NUM_OF_POOLS_SHIFT 16
+#define FM_SP_EXT_BUF_MARG_START_SHIFT 16
+#define FM_SP_EXT_BUF_MARG_END_SHIFT 0
+#define FM_SP_DMA_ATTR_SWP_SHIFT 30
+#define FM_SP_DMA_ATTR_IC_CACHE_SHIFT 28
+#define FM_SP_DMA_ATTR_HDR_CACHE_SHIFT 26
+#define FM_SP_DMA_ATTR_SG_CACHE_SHIFT 24
+#define FM_SP_IC_TO_EXT_SHIFT 16
+#define FM_SP_IC_FROM_INT_SHIFT 8
+#define FM_SP_IC_SIZE_SHIFT 0
+
+
+/**************************************************************************//**
+ @Description structure for defining internal context copying
+*//***************************************************************************/
+typedef struct
+{
+ uint16_t extBufOffset; /**< Offset in External buffer to which internal
+ context is copied to (Rx) or taken from (Tx, Op). */
+ uint8_t intContextOffset; /**< Offset within internal context to copy from
+ (Rx) or to copy to (Tx, Op). */
+ uint16_t size; /**< Internal offset size to be copied */
+} t_FmSpIntContextDataCopy;
+
+/**************************************************************************//**
+ @Description struct for defining external buffer margins
+*//***************************************************************************/
+typedef struct {
+ uint16_t startMargins; /**< Number of bytes to be left at the beginning
+ of the external buffer (must be divisible by 16) */
+ uint16_t endMargins; /**< number of bytes to be left at the end
+ of the external buffer(must be divisible by 16) */
+} t_FmSpBufMargins;
+
+typedef struct {
+ uint32_t dataOffset;
+ uint32_t prsResultOffset;
+ uint32_t timeStampOffset;
+ uint32_t hashResultOffset;
+ uint32_t pcdInfoOffset;
+ uint32_t manipOffset;
+} t_FmSpBufferOffsets;
+
+
+t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmPortIntContextDataCopy,
+ t_FmBufferPrefixContent *p_BufferPrefixContent,
+ t_FmSpBufMargins *p_FmPortBufMargins,
+ t_FmSpBufferOffsets *p_FmPortBufferOffsets,
+ uint8_t *internalBufferOffset);
+
+t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy);
+t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools,
+ t_FmBackupBmPools *p_FmBackupBmPools,
+ t_FmBufPoolDepletion *p_FmBufPoolDepletion);
+t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins);
+void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, uint8_t *orderedArray, uint16_t *sizesArray);
+
+t_Error FmPcdSpAllocProfiles(t_Handle h_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfStorageProfiles,
+ uint16_t *base,
+ uint8_t *log2Num);
+t_Error FmPcdSpGetAbsoluteProfileId(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+void SpInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+void SpValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+
+
+#endif /* __FM_SP_COMMON_H */