1/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above copyright
9 *       notice, this list of conditions and the following disclaimer in the
10 *       documentation and/or other materials provided with the distribution.
11 *     * Neither the name of Freescale Semiconductor nor the
12 *       names of its contributors may be used to endorse or promote products
13 *       derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/******************************************************************************
34 @File          fm_port.c
35
36 @Description   FM driver routines implementation.
37*//***************************************************************************/
38#include "error_ext.h"
39#include "std_ext.h"
40#include "string_ext.h"
41#include "sprint_ext.h"
42#include "debug_ext.h"
43#include "fm_pcd_ext.h"
44
45#include "fm_port.h"
46
47
48/****************************************/
49/*       static functions               */
50/****************************************/
51
52static t_Error CheckInitParameters(t_FmPort *p_FmPort)
53{
54    t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
55    t_Error             ans = E_OK;
56    uint32_t            unusedMask;
57    uint8_t             i;
58    uint8_t             j;
59    bool                found;
60
61    if (p_FmPort->imEn)
62    {
63        if ((ans = FmPortImCheckInitParameters(p_FmPort)) != E_OK)
64            return ERROR_CODE(ans);
65    }
66    else
67    {
68        /****************************************/
69        /*   Rx only                            */
70        /****************************************/
71        if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
72        {
73            /* external buffer pools */
74            if(!p_Params->extBufPools.numOfPoolsUsed)
75                 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.numOfPoolsUsed=0. At least one buffer pool must be defined"));
76
77            if(p_Params->extBufPools.numOfPoolsUsed > FM_PORT_MAX_NUM_OF_EXT_POOLS)
78                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfPoolsUsed can't be larger than %d", FM_PORT_MAX_NUM_OF_EXT_POOLS));
79
80            for(i=0;i<p_Params->extBufPools.numOfPoolsUsed;i++)
81            {
82                if(p_Params->extBufPools.extBufPool[i].id >= BM_MAX_NUM_OF_POOLS)
83                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].id can't be larger than %d", i, BM_MAX_NUM_OF_POOLS));
84                if(!p_Params->extBufPools.extBufPool[i].size)
85                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].size is 0", i));
86            }
87
88            /* backup BM pools indication is valid only for some chip deriviatives
89               (limited by the config routine) */
90            if(p_Params->p_BackupBmPools)
91            {
92                if(p_Params->p_BackupBmPools->numOfBackupPools >= p_Params->extBufPools.numOfPoolsUsed)
93                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_BackupBmPools must be smaller than extBufPools.numOfPoolsUsed"));
94                found = FALSE;
95                for(i = 0;i<p_Params->p_BackupBmPools->numOfBackupPools;i++)
96                    for(j=0;j<p_Params->extBufPools.numOfPoolsUsed;j++)
97                        if(p_Params->p_BackupBmPools->poolIds[i] == p_Params->extBufPools.extBufPool[j].id)
98                            found = TRUE;
99                if (!found)
100                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("All p_BackupBmPools.poolIds must be included in extBufPools.extBufPool[n].id"));
101            }
102
103            /* up to extBufPools.numOfPoolsUsed pools may be defined */
104            if(p_Params->bufPoolDepletion.numberOfPoolsModeEnable)
105            {
106                if((p_Params->bufPoolDepletion.numOfPools > p_Params->extBufPools.numOfPoolsUsed))
107                    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));
108
109                if(!p_Params->bufPoolDepletion.numOfPools)
110                  RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when numberOfPoolsModeEnable=TRUE"));
111            }
112            /* Check that part of IC that needs copying is small enough to enter start margin */
113            if(p_Params->intContext.size + p_Params->intContext.extBufOffset > p_Params->bufMargins.startMargins)
114                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size is larger than start margins"));
115
116            if(p_Params->liodnOffset & ~FM_LIODN_OFFSET_MASK)
117                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
118#ifdef FM_PARTITION_ARRAY
119            {
120                t_FmRevisionInfo revInfo;
121                FM_GetRevision(p_FmPort->h_Fm, &revInfo);
122                if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
123                {
124                    if(p_Params->liodnOffset >= MAX_LIODN_OFFSET)
125                    {
126                        p_Params->liodnOffset = (uint16_t)(p_Params->liodnOffset & (MAX_LIODN_OFFSET-1));
127                        DBG(WARNING, ("liodnOffset number is out of rev1 range - MSB bits cleard."));
128                    }
129                }
130            }
131#endif /* FM_PARTITION_ARRAY */
132        }
133
134        /****************************************/
135        /*   Non Rx ports                       */
136        /****************************************/
137        else
138        {
139            if(p_Params->deqSubPortal >= MAX_QMI_DEQ_SUBPORTAL)
140                 RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" deqSubPortal has to be in the range of 0 - %d", MAX_QMI_DEQ_SUBPORTAL));
141
142            /* to protect HW internal-context from overwrite */
143            if((p_Params->intContext.size) && (p_Params->intContext.intContextOffset < MIN_TX_INT_OFFSET))
144                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("non-Rx intContext.intContextOffset can't be smaller than %d", MIN_TX_INT_OFFSET));
145        }
146
147        /****************************************/
148        /*   Rx Or Offline Parsing              */
149        /****************************************/
150        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))
151        {
152
153            if(!p_Params->dfltFqid)
154                 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
155#if defined(FM_CAPWAP_SUPPORT) && defined(FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004)
156            if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace % 16)
157                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufferPrefixContent.manipExtraSpace has to be devidable by 16"));
158#endif /* defined(FM_CAPWAP_SUPPORT) && ... */
159        }
160
161        /****************************************/
162        /*   All ports                          */
163        /****************************************/
164        /* common BMI registers values */
165        /* Check that Queue Id is not larger than 2^24, and is not 0 */
166        if((p_Params->errFqid & ~0x00FFFFFF) || !p_Params->errFqid)
167            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("errFqid must be between 1 and 2^24-1"));
168        if(p_Params->dfltFqid & ~0x00FFFFFF)
169            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
170    }
171
172    /****************************************/
173    /*   Rx only                            */
174    /****************************************/
175    if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
176    {
177        /* Check that divisible by 256 and not larger than 256 */
178        if(p_Params->rxFifoPriElevationLevel % BMI_FIFO_UNITS)
179            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be divisible by %d", BMI_FIFO_UNITS));
180        if(!p_Params->rxFifoPriElevationLevel || (p_Params->rxFifoPriElevationLevel > BMI_MAX_FIFO_SIZE))
181            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
182        if(p_Params->rxFifoThreshold % BMI_FIFO_UNITS)
183            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be divisible by %d", BMI_FIFO_UNITS));
184        if(!p_Params->rxFifoThreshold ||(p_Params->rxFifoThreshold > BMI_MAX_FIFO_SIZE))
185            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
186
187        /* Check that not larger than 16 */
188        if(p_Params->cutBytesFromEnd > FRAME_END_DATA_SIZE)
189            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
190
191        /* Check the margin definition */
192        if(p_Params->bufMargins.startMargins > MAX_EXT_BUFFER_OFFSET)
193            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
194        if(p_Params->bufMargins.endMargins > MAX_EXT_BUFFER_OFFSET)
195            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.endMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
196
197        /* extra FIFO size (allowed only to Rx ports) */
198        if(p_FmPort->fifoBufs.extra % BMI_FIFO_UNITS)
199             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.extra has to be divisible by %d", BMI_FIFO_UNITS));
200
201        if(p_Params->bufPoolDepletion.numberOfPoolsModeEnable &&
202           !p_Params->bufPoolDepletion.numOfPools)
203              RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when numberOfPoolsModeEnable=TRUE"));
204#ifdef FM_CSI_CFED_LIMIT
205        {
206            t_FmRevisionInfo revInfo;
207            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
208
209            if (revInfo.majorRev == 4)
210            {
211                /* Check that not larger than 16 */
212                if(p_Params->cutBytesFromEnd + p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE)
213                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore + cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
214            }
215        }
216#endif /* FM_CSI_CFED_LIMIT */
217
218    }
219
220    /****************************************/
221    /*   Non Rx ports                       */
222    /****************************************/
223    else
224        /* extra FIFO size (allowed only to Rx ports) */
225        if(p_FmPort->fifoBufs.extra)
226             RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No fifoBufs.extra for non Rx ports"));
227
228    /****************************************/
229    /*   Rx & Tx                            */
230    /****************************************/
231    if((p_FmPort->portType == e_FM_PORT_TYPE_TX) || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ||
232        (p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
233    {
234        /* Check that not larger than 16 */
235        if(p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE)
236            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore can't be larger than %d", FRAME_END_DATA_SIZE));
237    }
238
239    /****************************************/
240    /*   Tx only                            */
241    /****************************************/
242    if((p_FmPort->portType == e_FM_PORT_TYPE_TX) || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
243    {
244        /* Check that divisible by 256 and not larger than 256 */
245        if(p_Params->txFifoMinFillLevel % BMI_FIFO_UNITS)
246            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be divisible by %d", BMI_FIFO_UNITS));
247        if(p_Params->txFifoMinFillLevel > (BMI_MAX_FIFO_SIZE - 256))
248            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be in the range of 0 - %d", BMI_MAX_FIFO_SIZE));
249        if(p_Params->txFifoLowComfLevel % BMI_FIFO_UNITS)
250            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be divisible by %d", BMI_FIFO_UNITS));
251        if(!p_Params->txFifoLowComfLevel || (p_Params->txFifoLowComfLevel > BMI_MAX_FIFO_SIZE))
252            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
253
254        /* Check that not larger than 8 */
255        if((!p_FmPort->txFifoDeqPipelineDepth) ||( p_FmPort->txFifoDeqPipelineDepth > MAX_FIFO_PIPELINE_DEPTH))
256            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoDeqPipelineDepth can't be larger than %d", MAX_FIFO_PIPELINE_DEPTH));
257        if(p_FmPort->portType == e_FM_PORT_TYPE_TX)
258            if(p_FmPort->txFifoDeqPipelineDepth > 2)
259                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoDeqPipelineDepth for !G can't be larger than 2"));
260    }
261    else
262    /****************************************/
263    /*   Non Tx Ports                       */
264    /****************************************/
265    {
266        /* If discard override was selected , no frames may be discarded. */
267        if(p_Params->frmDiscardOverride && p_Params->errorsToDiscard)
268            RETURN_ERROR(MAJOR, E_CONFLICT, ("errorsToDiscard is not empty, but frmDiscardOverride selected (all discarded frames to be enqueued to error queue)."));
269    }
270
271    /****************************************/
272    /*   Rx and Offline parsing             */
273    /****************************************/
274    if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)
275        || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
276    {
277        if(p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
278            unusedMask = BMI_STATUS_OP_MASK_UNUSED;
279        else
280            unusedMask = BMI_STATUS_RX_MASK_UNUSED;
281
282        /* Check that no common bits with BMI_STATUS_MASK_UNUSED */
283        if(p_Params->errorsToDiscard & unusedMask)
284            RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("errorsToDiscard contains undefined bits"));
285    }
286
287    /****************************************/
288    /*   All ports                          */
289    /****************************************/
290
291   /* Check that divisible by 16 and not larger than 240 */
292    if(p_Params->intContext.intContextOffset >MAX_INT_OFFSET)
293        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset can't be larger than %d", MAX_INT_OFFSET));
294    if(p_Params->intContext.intContextOffset % OFFSET_UNITS)
295        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset has to be divisible by %d", OFFSET_UNITS));
296
297    /* check that ic size+ic internal offset, does not exceed ic block size */
298    if(p_Params->intContext.size + p_Params->intContext.intContextOffset > MAX_IC_SIZE)
299        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size + intContext.intContextOffset has to be smaller than %d", MAX_IC_SIZE));
300    /* Check that divisible by 16 and not larger than 256 */
301    if(p_Params->intContext.size % OFFSET_UNITS)
302        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size  has to be divisible by %d", OFFSET_UNITS));
303
304    /* Check that divisible by 16 and not larger than 4K */
305    if(p_Params->intContext.extBufOffset > MAX_EXT_OFFSET)
306        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset can't be larger than %d", MAX_EXT_OFFSET));
307    if(p_Params->intContext.extBufOffset % OFFSET_UNITS)
308        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset  has to be divisible by %d", OFFSET_UNITS));
309
310    /* common BMI registers values */
311    if((!p_FmPort->tasks.num) || (p_FmPort->tasks.num > MAX_NUM_OF_TASKS))
312         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.num can't be larger than %d", MAX_NUM_OF_TASKS));
313    if(p_FmPort->tasks.extra > MAX_NUM_OF_EXTRA_TASKS)
314         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
315    if((!p_FmPort->openDmas.num) || (p_FmPort->openDmas.num > MAX_NUM_OF_DMAS))
316         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.num can't be larger than %d", MAX_NUM_OF_DMAS));
317    if(p_FmPort->openDmas.extra > MAX_NUM_OF_EXTRA_DMAS)
318         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
319    if(!p_FmPort->fifoBufs.num || (p_FmPort->fifoBufs.num > BMI_MAX_FIFO_SIZE))
320         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
321    if(p_FmPort->fifoBufs.num % BMI_FIFO_UNITS)
322         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be divisible by %d", BMI_FIFO_UNITS));
323
324    return E_OK;
325}
326
327static void FmPortDriverParamFree(t_FmPort *p_FmPort)
328{
329    if(p_FmPort->p_FmPortDriverParam)
330    {
331        XX_Free(p_FmPort->p_FmPortDriverParam);
332        p_FmPort->p_FmPortDriverParam = NULL;
333    }
334}
335
336static t_Error SetExtBufferPools(t_FmPort *p_FmPort)
337{
338    t_FmPortExtPools            *p_ExtBufPools = &p_FmPort->p_FmPortDriverParam->extBufPools;
339    t_FmPortBufPoolDepletion    *p_BufPoolDepletion = &p_FmPort->p_FmPortDriverParam->bufPoolDepletion;
340    volatile uint32_t           *p_ExtBufRegs;
341    volatile uint32_t           *p_BufPoolDepletionReg;
342    bool                        rxPort;
343    bool                        found;
344    uint8_t                     orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS];
345    uint16_t                    sizesArray[BM_MAX_NUM_OF_POOLS];
346    uint8_t                     count = 0;
347    uint8_t                     numOfPools;
348    uint16_t                    bufSize = 0, largestBufSize = 0;
349    int                         i=0, j=0, k=0;
350    uint32_t                    tmpReg, vector, minFifoSizeRequired=0;
351
352    memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
353    memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
354    memcpy(&p_FmPort->extBufPools, p_ExtBufPools, sizeof(t_FmPortExtPools));
355
356    switch(p_FmPort->portType)
357    {
358        case(e_FM_PORT_TYPE_RX_10G):
359        case(e_FM_PORT_TYPE_RX):
360            p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi;
361            p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_mpd;
362            rxPort = TRUE;
363            break;
364        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
365            p_ExtBufRegs = p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi;
366            p_BufPoolDepletionReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ompd;
367            rxPort = FALSE;
368            break;
369        default:
370            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for port type"));
371    }
372
373    /* First we copy the external buffers pools information to an ordered local array */
374    for(i=0;i<p_ExtBufPools->numOfPoolsUsed;i++)
375    {
376        /* get pool size */
377        bufSize = p_ExtBufPools->extBufPool[i].size;
378
379        /* keep sizes in an array according to poolId for direct access */
380        sizesArray[p_ExtBufPools->extBufPool[i].id] =  bufSize;
381
382        /* save poolId in an ordered array according to size */
383        for (j=0;j<=i;j++)
384        {
385            /* this is the next free place in the array */
386            if (j==i)
387                orderedArray[i] = p_ExtBufPools->extBufPool[i].id;
388            else
389            {
390                /* find the right place for this poolId */
391                if(bufSize < sizesArray[orderedArray[j]])
392                {
393                    /* move the poolIds one place ahead to make room for this poolId */
394                    for(k=i;k>j;k--)
395                       orderedArray[k] = orderedArray[k-1];
396
397                    /* now k==j, this is the place for the new size */
398                    orderedArray[k] = p_ExtBufPools->extBufPool[i].id;
399                    break;
400                }
401            }
402        }
403    }
404
405    /* build the register value */
406
407    for(i=0;i<p_ExtBufPools->numOfPoolsUsed;i++)
408    {
409        tmpReg = BMI_EXT_BUF_POOL_VALID | BMI_EXT_BUF_POOL_EN_COUNTER;
410        tmpReg |= ((uint32_t)orderedArray[i] << BMI_EXT_BUF_POOL_ID_SHIFT);
411        tmpReg |= sizesArray[orderedArray[i]];
412        /* functionality available only for some deriviatives (limited by config) */
413        if(p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
414            for(j=0;j<p_FmPort->p_FmPortDriverParam->p_BackupBmPools->numOfBackupPools;j++)
415                if(orderedArray[i] == p_FmPort->p_FmPortDriverParam->p_BackupBmPools->poolIds[j])
416                {
417                    tmpReg |= BMI_EXT_BUF_POOL_BACKUP;
418                    break;
419                }
420        WRITE_UINT32(*(p_ExtBufRegs+i), tmpReg);
421    }
422
423    if(p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
424        XX_Free(p_FmPort->p_FmPortDriverParam->p_BackupBmPools);
425
426   numOfPools = (uint8_t)(rxPort ? FM_PORT_MAX_NUM_OF_EXT_POOLS:FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS);
427
428    /* clear unused pools */
429    for(i=p_ExtBufPools->numOfPoolsUsed;i<numOfPools;i++)
430        WRITE_UINT32(*(p_ExtBufRegs+i), 0);
431
432    p_FmPort->rxPoolsParams.largestBufSize = largestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-1]];
433    if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
434    {
435#ifdef FM_FIFO_ALLOCATION_OLD_ALG
436        t_FmRevisionInfo        revInfo;
437        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
438
439        if(revInfo.majorRev != 4)
440        {
441            minFifoSizeRequired = (uint32_t)(((largestBufSize % BMI_FIFO_UNITS) ?
442                                    ((largestBufSize/BMI_FIFO_UNITS + 1) * BMI_FIFO_UNITS) :
443                                    largestBufSize) +
444                                    (7*BMI_FIFO_UNITS));
445        }
446        else
447#endif /* FM_FIFO_ALLOCATION_OLD_ALG */
448        {
449            p_FmPort->rxPoolsParams.numOfPools = p_ExtBufPools->numOfPoolsUsed;
450            if(p_ExtBufPools->numOfPoolsUsed == 1)
451                minFifoSizeRequired = 8*BMI_FIFO_UNITS;
452            else
453            {
454                uint16_t secondLargestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-2]];
455                p_FmPort->rxPoolsParams.secondLargestBufSize = secondLargestBufSize;
456                minFifoSizeRequired = (uint32_t)(((secondLargestBufSize % BMI_FIFO_UNITS) ?
457                                    ((secondLargestBufSize/BMI_FIFO_UNITS + 1) * BMI_FIFO_UNITS) :
458                                    secondLargestBufSize) +
459                                    (7*BMI_FIFO_UNITS));
460            }
461        }
462        if(p_FmPort->fifoBufs.num < minFifoSizeRequired)
463        {
464            p_FmPort->fifoBufs.num = minFifoSizeRequired;
465            DBG(INFO, ("FIFO size for Rx port enlarged to %d",minFifoSizeRequired));
466        }
467    }
468
469    /* check if pool size is not too big */
470    /* This is a definition problem in which if the fifo for the RX port
471       is lower than the largest pool size the hardware will allocate scatter gather
472       buffers even though the frame size can fit in a single buffer. */
473    if (largestBufSize > p_FmPort->fifoBufs.num)
474        DBG(WARNING, ("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)",
475                p_FmPort->fifoBufs.num, largestBufSize));
476
477    /* pool depletion */
478    tmpReg = 0;
479    if(p_BufPoolDepletion->numberOfPoolsModeEnable)
480    {
481        /* calculate vector for number of pools depletion */
482        found = FALSE;
483        vector = 0;
484        count = 0;
485        for(i=0;i<BM_MAX_NUM_OF_POOLS;i++)
486        {
487            if(p_BufPoolDepletion->poolsToConsider[i])
488            {
489                for(j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
490                {
491                    if (i == orderedArray[j])
492                    {
493                        vector |= 0x80000000 >> j;
494                        found = TRUE;
495                        count++;
496                        break;
497                    }
498                }
499                if (!found)
500                    RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
501                else
502                    found = FALSE;
503            }
504        }
505        if (count < p_BufPoolDepletion->numOfPools)
506            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools is larger than the number of pools defined."));
507
508        /* configure num of pools and vector for number of pools mode */
509        tmpReg |= (((uint32_t)p_BufPoolDepletion->numOfPools - 1) << BMI_POOL_DEP_NUM_OF_POOLS_SHIFT);
510        tmpReg |= vector;
511    }
512
513    if(p_BufPoolDepletion->singlePoolModeEnable)
514    {
515        /* calculate vector for number of pools depletion */
516        found = FALSE;
517        vector = 0;
518        count = 0;
519        for(i=0;i<BM_MAX_NUM_OF_POOLS;i++)
520        {
521            if(p_BufPoolDepletion->poolsToConsiderForSingleMode[i])
522            {
523                for(j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
524                {
525                    if (i == orderedArray[j])
526                     {
527                        vector |= 0x00000080 >> j;
528                        found = TRUE;
529                        count++;
530                        break;
531                    }
532                }
533                if (!found)
534                    RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
535                else
536                    found = FALSE;
537            }
538        }
539        if (!count)
540            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("No pools defined for single buffer mode pool depletion."));
541
542        /* configure num of pools and vector for number of pools mode */
543        tmpReg |= vector;
544    }
545
546    WRITE_UINT32(*p_BufPoolDepletionReg, tmpReg);
547
548    return E_OK;
549}
550
551static t_Error ClearPerfCnts(t_FmPort *p_FmPort)
552{
553    FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL, 0);
554    FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL, 0);
555    FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL, 0);
556    FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL, 0);
557    return E_OK;
558}
559
560static t_Error BmiRxPortInit(t_FmPort *p_FmPort)
561{
562    t_FmPortRxBmiRegs       *p_Regs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs;
563    uint32_t                tmpReg;
564    t_FmPortDriverParam     *p_Params = p_FmPort->p_FmPortDriverParam;
565    uint32_t                errorsToEnq = 0;
566    t_FmPortPerformanceCnt  performanceContersParams;
567    t_Error                 err;
568
569    /* check that port is not busy */
570    if (GET_UINT32(p_Regs->fmbm_rcfg) & BMI_PORT_CFG_EN)
571         RETURN_ERROR(MAJOR, E_INVALID_STATE,
572                      ("Port(%d,%d) is already enabled",p_FmPort->portType, p_FmPort->portId));
573
574    /* Set Config register */
575    tmpReg = 0;
576    if (p_FmPort->imEn)
577        tmpReg |= BMI_PORT_CFG_IM;
578    /* No discard - all error frames go to error queue */
579    else if (p_Params->frmDiscardOverride)
580        tmpReg |= BMI_PORT_CFG_FDOVR;
581
582    WRITE_UINT32(p_Regs->fmbm_rcfg, tmpReg);
583
584    /* Configure dma attributes */
585    tmpReg = 0;
586    tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
587    tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
588    tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
589    tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
590    if(p_Params->dmaWriteOptimize)
591        tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
592
593    WRITE_UINT32(p_Regs->fmbm_rda, tmpReg);
594
595    /* Configure Rx Fifo params */
596    tmpReg = 0;
597    tmpReg |= ((p_Params->rxFifoPriElevationLevel/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_PRI_ELEVATION_SHIFT);
598    tmpReg |= ((p_Params->rxFifoThreshold/BMI_FIFO_UNITS - 1) << BMI_RX_FIFO_THRESHOLD_SHIFT);
599
600    WRITE_UINT32(p_Regs->fmbm_rfp, tmpReg);
601
602    {
603#ifdef FM_NO_THRESHOLD_REG
604         t_FmRevisionInfo        revInfo;
605
606         FM_GetRevision(p_FmPort->h_Fm, &revInfo);
607         if (revInfo.majorRev > 1)
608#endif /* FM_NO_THRESHOLD_REG */
609            /* always allow access to the extra resources */
610            WRITE_UINT32(p_Regs->fmbm_reth, BMI_RX_FIFO_THRESHOLD_BC);
611    }
612
613     /* frame end parameters */
614    tmpReg = 0;
615    tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_RX_FRAME_END_CS_IGNORE_SHIFT);
616    tmpReg |= ((uint32_t)p_Params->cutBytesFromEnd<< BMI_RX_FRAME_END_CUT_SHIFT);
617
618    WRITE_UINT32(p_Regs->fmbm_rfed, tmpReg);
619
620    /* IC parameters */
621    tmpReg = 0;
622    tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
623    tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
624    tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS)  << BMI_IC_SIZE_SHIFT);
625
626    WRITE_UINT32(p_Regs->fmbm_ricp, tmpReg);
627
628    if (!p_FmPort->imEn)
629    {
630        /* check if the largest external buffer pool is large enough */
631        if(p_Params->bufMargins.startMargins + MIN_EXT_BUF_SIZE + p_Params->bufMargins.endMargins > p_FmPort->rxPoolsParams.largestBufSize)
632            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins (%d) + minimum buf size (64) + bufMargins.endMargins (%d) is larger than maximum external buffer size (%d)",
633                            p_Params->bufMargins.startMargins, p_Params->bufMargins.endMargins, p_FmPort->rxPoolsParams.largestBufSize));
634
635        /* buffer margins */
636        tmpReg = 0;
637        tmpReg |= (((uint32_t)p_Params->bufMargins.startMargins) << BMI_EXT_BUF_MARG_START_SHIFT);
638        tmpReg |= (((uint32_t)p_Params->bufMargins.endMargins) << BMI_EXT_BUF_MARG_END_SHIFT);
639
640        WRITE_UINT32(p_Regs->fmbm_rebm, tmpReg);
641    }
642
643
644    if(p_FmPort->internalBufferOffset)
645    {
646        tmpReg = (uint32_t)((p_FmPort->internalBufferOffset % OFFSET_UNITS) ?
647                            (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1):
648                            (p_FmPort->internalBufferOffset/OFFSET_UNITS));
649        p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS);
650        WRITE_UINT32(p_Regs->fmbm_rim, tmpReg << BMI_IM_FOF_SHIFT);
651    }
652
653    /* NIA */
654    if (p_FmPort->imEn)
655        WRITE_UINT32(p_Regs->fmbm_rfne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_RX);
656    else
657    {
658        tmpReg = 0;
659        if (p_Params->forwardReuseIntContext)
660            tmpReg |= BMI_PORT_RFNE_FRWD_RPD;
661        /* L3/L4 checksum verify is enabled by default. */
662        /*tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C;*/
663        WRITE_UINT32(p_Regs->fmbm_rfne, tmpReg | NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
664    }
665    WRITE_UINT32(p_Regs->fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
666
667    /* command attribute */
668    tmpReg = BMI_CMD_RX_MR_DEF;
669    if (!p_FmPort->imEn)
670    {
671        tmpReg |= BMI_CMD_ATTR_ORDER;
672        if(p_Params->syncReq)
673            tmpReg |= BMI_CMD_ATTR_SYNC;
674        tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
675    }
676
677    WRITE_UINT32(p_Regs->fmbm_rfca, tmpReg);
678
679    /* default queues */
680    if (!p_FmPort->imEn)
681    {
682        WRITE_UINT32(p_Regs->fmbm_rfqid, p_Params->dfltFqid);
683        WRITE_UINT32(p_Regs->fmbm_refqid, p_Params->errFqid);
684    }
685
686    /* set counters */
687    WRITE_UINT32(p_Regs->fmbm_rstc, BMI_COUNTERS_EN);
688
689    performanceContersParams.taskCompVal    = (uint8_t)p_FmPort->tasks.num;
690    performanceContersParams.queueCompVal   = 1;
691    performanceContersParams.dmaCompVal     =(uint8_t) p_FmPort->openDmas.num;
692    performanceContersParams.fifoCompVal    = p_FmPort->fifoBufs.num;
693    if((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams)) != E_OK)
694        RETURN_ERROR(MAJOR, err, NO_MSG);
695
696    WRITE_UINT32(p_Regs->fmbm_rpc, BMI_COUNTERS_EN);
697
698    /* error/status mask  - check that if discard OV is set, no
699       discard is required for specific errors.*/
700    WRITE_UINT32(p_Regs->fmbm_rfsdm, p_Params->errorsToDiscard);
701
702    errorsToEnq = (RX_ERRS_TO_ENQ & ~p_Params->errorsToDiscard);
703    WRITE_UINT32(p_Regs->fmbm_rfsem, errorsToEnq);
704
705#ifdef FM_BMI_TO_RISC_ENQ_ERRATA_FMANc
706    if((GET_UINT32(p_Regs->fmbm_rfene) && NIA_ENG_MASK)== NIA_ENG_FM_CTL)
707        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("NIA not supported at this stage"));
708#endif /* FM_BMI_TO_RISC_ENQ_ERRATA_FMANc */
709
710    return E_OK;
711}
712
713static t_Error BmiTxPortInit(t_FmPort *p_FmPort)
714{
715    t_FmPortTxBmiRegs   *p_Regs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs;
716    uint32_t            tmpReg;
717    t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
718    /*uint32_t            rateCountUnit;*/
719    t_FmPortPerformanceCnt  performanceContersParams;
720
721    /* check that port is not busy */
722    if (GET_UINT32(p_Regs->fmbm_tcfg) & BMI_PORT_CFG_EN)
723         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
724
725    tmpReg = 0;
726    if (p_FmPort->imEn)
727        tmpReg |= BMI_PORT_CFG_IM;
728
729    WRITE_UINT32(p_Regs->fmbm_tcfg, tmpReg);
730
731    /* Configure dma attributes */
732    tmpReg = 0;
733    tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
734    tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
735    tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
736    tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
737
738    WRITE_UINT32(p_Regs->fmbm_tda, tmpReg);
739
740    /* Configure Tx Fifo params */
741    tmpReg = 0;
742    tmpReg |= ((p_Params->txFifoMinFillLevel/BMI_FIFO_UNITS) << BMI_TX_FIFO_MIN_FILL_SHIFT);
743    tmpReg |= (((uint32_t)p_FmPort->txFifoDeqPipelineDepth - 1) << BMI_TX_FIFO_PIPELINE_DEPTH_SHIFT);
744    tmpReg |= ((p_Params->txFifoLowComfLevel/BMI_FIFO_UNITS - 1) << BMI_TX_LOW_COMF_SHIFT);
745
746    WRITE_UINT32(p_Regs->fmbm_tfp, tmpReg);
747
748    /* frame end parameters */
749    tmpReg = 0;
750    tmpReg |= ((uint32_t)p_Params->cheksumLastBytesIgnore << BMI_TX_FRAME_END_CS_IGNORE_SHIFT);
751
752    WRITE_UINT32(p_Regs->fmbm_tfed, tmpReg);
753
754    if (!p_FmPort->imEn)
755    {
756        /* IC parameters */
757        tmpReg = 0;
758        tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
759        tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
760        tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS)  << BMI_IC_SIZE_SHIFT);
761
762        WRITE_UINT32(p_Regs->fmbm_ticp, tmpReg);
763    }
764
765    /* NIA */
766    if (p_FmPort->imEn)
767    {
768        WRITE_UINT32(p_Regs->fmbm_tfne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX);
769        WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX);
770    }
771    else
772    {
773        WRITE_UINT32(p_Regs->fmbm_tfne, NIA_ENG_QMI_DEQ);
774        WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
775        /* The line bellow is a trick so the FM will not release the buffer
776           to BM nor will try to enq the frame to QM */
777        if(!p_Params->dfltFqid && p_Params->dontReleaseBuf)
778        {
779            /* override fmbm_tcfqid 0 with a false non-0 value. This will force FM to
780             * act acording to tfene. Otherwise, if fmbm_tcfqid is 0 the FM will release
781             * buffers to BM regardless of fmbm_tfene
782             */
783            WRITE_UINT32(p_Regs->fmbm_tcfqid, 0xFFFFFF);
784            WRITE_UINT32(p_Regs->fmbm_tfene, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
785        }
786    }
787
788    /* command attribute */
789    tmpReg = BMI_CMD_TX_MR_DEF;
790    if (p_FmPort->imEn)
791        tmpReg |= BMI_CMD_MR_DEAS;
792    else
793    {
794        tmpReg |= BMI_CMD_ATTR_ORDER;
795        /* if we set syncReq, we may get stuck when HC command is running */
796        /*if(p_Params->syncReq)
797            tmpReg |= BMI_CMD_ATTR_SYNC;*/
798        tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
799    }
800
801    WRITE_UINT32(p_Regs->fmbm_tfca, tmpReg);
802
803    /* default queues */
804    if (!p_FmPort->imEn)
805    {
806        if(p_Params->dfltFqid || !p_Params->dontReleaseBuf)
807            WRITE_UINT32(p_Regs->fmbm_tcfqid, p_Params->dfltFqid);
808        WRITE_UINT32(p_Regs->fmbm_tfeqid, p_Params->errFqid);
809    }
810
811    /* statistics & performance counters */
812    WRITE_UINT32(p_Regs->fmbm_tstc, BMI_COUNTERS_EN);
813
814    performanceContersParams.taskCompVal    = (uint8_t)p_FmPort->tasks.num;
815    performanceContersParams.queueCompVal   = 1;
816    performanceContersParams.dmaCompVal     = (uint8_t)p_FmPort->openDmas.num;
817    performanceContersParams.fifoCompVal    = p_FmPort->fifoBufs.num;
818    FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams);
819
820    WRITE_UINT32(p_Regs->fmbm_tpc, BMI_COUNTERS_EN);
821
822    return E_OK;
823}
824
825static t_Error BmiOhPortInit(t_FmPort *p_FmPort)
826{
827    t_FmPortOhBmiRegs       *p_Regs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs;
828    uint32_t                tmpReg, errorsToEnq = 0;
829    t_FmPortDriverParam     *p_Params = p_FmPort->p_FmPortDriverParam;
830    t_FmPortPerformanceCnt  performanceContersParams;
831    t_Error                 err;
832
833    /* check that port is not busy */
834    if (GET_UINT32(p_Regs->fmbm_ocfg) & BMI_PORT_CFG_EN)
835         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
836
837    /* Configure dma attributes */
838    tmpReg = 0;
839    tmpReg |= (uint32_t)p_Params->dmaSwapData << BMI_DMA_ATTR_SWP_SHIFT;
840    tmpReg |= (uint32_t)p_Params->dmaIntContextCacheAttr << BMI_DMA_ATTR_IC_CACHE_SHIFT;
841    tmpReg |= (uint32_t)p_Params->dmaHeaderCacheAttr << BMI_DMA_ATTR_HDR_CACHE_SHIFT;
842    tmpReg |= (uint32_t)p_Params->dmaScatterGatherCacheAttr << BMI_DMA_ATTR_SG_CACHE_SHIFT;
843    if(p_Params->dmaWriteOptimize)
844        tmpReg |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
845
846    WRITE_UINT32(p_Regs->fmbm_oda, tmpReg);
847
848    /* IC parameters */
849    tmpReg = 0;
850    tmpReg |= (((uint32_t)p_Params->intContext.extBufOffset/OFFSET_UNITS) << BMI_IC_TO_EXT_SHIFT);
851    tmpReg |= (((uint32_t)p_Params->intContext.intContextOffset/OFFSET_UNITS) << BMI_IC_FROM_INT_SHIFT);
852    tmpReg |= (((uint32_t)p_Params->intContext.size/OFFSET_UNITS)  << BMI_IC_SIZE_SHIFT);
853
854    WRITE_UINT32(p_Regs->fmbm_oicp, tmpReg);
855
856    /* NIA */
857    WRITE_UINT32(p_Regs->fmbm_ofdne, NIA_ENG_QMI_DEQ);
858
859    if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND)
860        WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ);
861    else
862        WRITE_UINT32(p_Regs->fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
863
864    /* command attribute */
865    if (p_FmPort->portType==e_FM_PORT_TYPE_OH_HOST_COMMAND)
866        tmpReg =  BMI_CMD_MR_DEAS | BMI_CMD_MR_MA;
867    else
868        tmpReg = BMI_CMD_ATTR_ORDER | BMI_CMD_MR_DEAS | BMI_CMD_MR_MA;
869
870    if(p_Params->syncReq)
871        tmpReg |= BMI_CMD_ATTR_SYNC;
872    tmpReg |= ((uint32_t)p_Params->color << BMI_CMD_ATTR_COLOR_SHIFT);
873    WRITE_UINT32(p_Regs->fmbm_ofca, tmpReg);
874
875    /* No discard - all error frames go to error queue */
876    if (p_Params->frmDiscardOverride)
877        tmpReg = BMI_PORT_CFG_FDOVR;
878    else
879        tmpReg = 0;
880    WRITE_UINT32(p_Regs->fmbm_ocfg, tmpReg);
881
882    if(p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
883    {
884        WRITE_UINT32(p_Regs->fmbm_ofsdm, p_Params->errorsToDiscard);
885
886        errorsToEnq = (OP_ERRS_TO_ENQ & ~p_Params->errorsToDiscard);
887        WRITE_UINT32(p_Regs->fmbm_ofsem, errorsToEnq);
888
889        /* NIA */
890        WRITE_UINT32(p_Regs->fmbm_ofne, NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
891        {
892#ifdef FM_NO_OP_OBSERVED_POOLS
893            t_FmRevisionInfo        revInfo;
894
895            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
896            if ((revInfo.majorRev == 4) && (p_Params->enBufPoolDepletion))
897#endif /* FM_NO_OP_OBSERVED_POOLS */
898            {
899                /* define external buffer pools */
900                err = SetExtBufferPools(p_FmPort);
901                if(err)
902                    RETURN_ERROR(MAJOR, err, NO_MSG);
903            }
904        }
905    }
906    else
907        /* NIA */
908        WRITE_UINT32(p_Regs->fmbm_ofne, NIA_ENG_FM_CTL | NIA_FM_CTL_AC_HC);
909
910    /* default queues */
911    WRITE_UINT32(p_Regs->fmbm_ofqid, p_Params->dfltFqid);
912    WRITE_UINT32(p_Regs->fmbm_oefqid, p_Params->errFqid);
913
914    if(p_FmPort->internalBufferOffset)
915    {
916        tmpReg = (uint32_t)((p_FmPort->internalBufferOffset % OFFSET_UNITS) ?
917                            (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1):
918                            (p_FmPort->internalBufferOffset/OFFSET_UNITS));
919        p_FmPort->internalBufferOffset = (uint8_t)(tmpReg * OFFSET_UNITS);
920        WRITE_UINT32(p_Regs->fmbm_oim, tmpReg << BMI_IM_FOF_SHIFT);
921    }
922    /* statistics & performance counters */
923    WRITE_UINT32(p_Regs->fmbm_ostc, BMI_COUNTERS_EN);
924
925    performanceContersParams.taskCompVal    = (uint8_t)p_FmPort->tasks.num;
926    performanceContersParams.queueCompVal   = 0;
927    performanceContersParams.dmaCompVal     = (uint8_t)p_FmPort->openDmas.num;
928    performanceContersParams.fifoCompVal    = p_FmPort->fifoBufs.num;
929    FM_PORT_SetPerformanceCountersParams(p_FmPort, &performanceContersParams);
930
931    WRITE_UINT32(p_Regs->fmbm_opc, BMI_COUNTERS_EN);
932
933    return E_OK;
934}
935
936static t_Error QmiInit(t_FmPort *p_FmPort)
937{
938    t_FmPortDriverParam             *p_Params = NULL;
939    uint32_t                        tmpReg;
940
941    p_Params = p_FmPort->p_FmPortDriverParam;
942
943    /* check that port is not busy */
944    if(((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
945        (p_FmPort->portType != e_FM_PORT_TYPE_RX)) &&
946       (GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN))
947         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port is already enabled"));
948
949    /* enable & clear counters */
950    WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, QMI_PORT_CFG_EN_COUNTERS);
951
952    /* The following is  done for non-Rx ports only */
953    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
954        (p_FmPort->portType != e_FM_PORT_TYPE_RX))
955    {
956        if((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ||
957                        (p_FmPort->portType == e_FM_PORT_TYPE_TX))
958        {
959            /* define dequeue NIA */
960            WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX);
961            /* define enqueue NIA */
962            WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
963        }
964        else  /* for HC & OP */
965        {
966            WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH);
967            /* define enqueue NIA */
968            WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
969        }
970
971        /* configure dequeue */
972        tmpReg = 0;
973        if(p_Params->deqHighPriority)
974            tmpReg |= QMI_DEQ_CFG_PRI;
975
976        switch(p_Params->deqType)
977        {
978            case(e_FM_PORT_DEQ_TYPE1):
979                tmpReg |= QMI_DEQ_CFG_TYPE1;
980                break;
981            case(e_FM_PORT_DEQ_TYPE2):
982                tmpReg |= QMI_DEQ_CFG_TYPE2;
983                break;
984            case(e_FM_PORT_DEQ_TYPE3):
985                tmpReg |= QMI_DEQ_CFG_TYPE3;
986                break;
987            default:
988                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue type"));
989        }
990
991#ifdef FM_QMI_DEQ_OPTIONS_SUPPORT
992        switch(p_Params->deqPrefetchOption)
993        {
994            case(e_FM_PORT_DEQ_NO_PREFETCH):
995                /* Do nothing - QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_1_FRAME = 0 */
996                break;
997            case(e_FM_PORT_DEQ_PARTIAL_PREFETCH):
998                tmpReg |= QMI_DEQ_CFG_PREFETCH_WAITING_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES;
999                break;
1000            case(e_FM_PORT_DEQ_FULL_PREFETCH):
1001                tmpReg |= QMI_DEQ_CFG_PREFETCH_NO_TNUM | QMI_DEQ_CFG_PREFETCH_3_FRAMES;
1002                break;
1003            default:
1004                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid dequeue prefetch option"));
1005        }
1006#endif /* FM_QMI_DEQ_OPTIONS_SUPPORT */
1007
1008        tmpReg |= p_Params->deqByteCnt;
1009        tmpReg |= (uint32_t)p_Params->deqSubPortal << QMI_DEQ_CFG_SUBPORTAL_SHIFT;
1010
1011        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndc, tmpReg);
1012    }
1013    else /* rx port */
1014        /* define enqueue NIA */
1015        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
1016
1017    return E_OK;
1018}
1019
1020static t_Error BmiRxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
1021{
1022    t_FmPortRxBmiRegs   *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs;
1023
1024     /* check that counters are enabled */
1025    switch(counter)
1026    {
1027        case(e_FM_PORT_COUNTERS_CYCLE):
1028        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1029        case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
1030        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1031        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1032        case(e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
1033            /* performance counters - may be read when disabled */
1034            break;
1035        case(e_FM_PORT_COUNTERS_FRAME):
1036        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1037        case(e_FM_PORT_COUNTERS_RX_BAD_FRAME):
1038        case(e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
1039        case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
1040        case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
1041        case(e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
1042        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1043            if(!(GET_UINT32(p_BmiRegs->fmbm_rstc) & BMI_COUNTERS_EN))
1044               RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
1045            break;
1046         default:
1047            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
1048    }
1049
1050    /* Set counter */
1051    switch(counter)
1052    {
1053        case(e_FM_PORT_COUNTERS_CYCLE):
1054            *p_Ptr = &p_BmiRegs->fmbm_rccn;
1055            break;
1056        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1057            *p_Ptr = &p_BmiRegs->fmbm_rtuc;
1058            break;
1059        case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
1060            *p_Ptr = &p_BmiRegs->fmbm_rrquc;
1061            break;
1062        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1063            *p_Ptr = &p_BmiRegs->fmbm_rduc;
1064            break;
1065        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1066            *p_Ptr = &p_BmiRegs->fmbm_rfuc;
1067            break;
1068        case(e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
1069            *p_Ptr = &p_BmiRegs->fmbm_rpac;
1070            break;
1071        case(e_FM_PORT_COUNTERS_FRAME):
1072            *p_Ptr = &p_BmiRegs->fmbm_rfrc;
1073            break;
1074        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1075            *p_Ptr = &p_BmiRegs->fmbm_rfcd;
1076            break;
1077        case(e_FM_PORT_COUNTERS_RX_BAD_FRAME):
1078            *p_Ptr = &p_BmiRegs->fmbm_rfbc;
1079            break;
1080        case(e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
1081            *p_Ptr = &p_BmiRegs->fmbm_rlfc;
1082            break;
1083        case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
1084            *p_Ptr = &p_BmiRegs->fmbm_rffc;
1085            break;
1086        case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
1087#ifdef FM_PORT_COUNTERS_ERRATA_FMANg
1088            {
1089                t_FmRevisionInfo revInfo;
1090                FM_GetRevision(p_FmPort->h_Fm, &revInfo);
1091                if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
1092                    RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Requested counter is not available in rev1"));
1093            }
1094#endif /* FM_PORT_COUNTERS_ERRATA_FMANg */
1095            *p_Ptr = &p_BmiRegs->fmbm_rfldec;
1096            break;
1097        case(e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
1098            *p_Ptr = &p_BmiRegs->fmbm_rodc;
1099            break;
1100        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1101            *p_Ptr = &p_BmiRegs->fmbm_rbdc;
1102            break;
1103        default:
1104            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
1105    }
1106
1107    return E_OK;
1108}
1109
1110static t_Error BmiTxPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
1111{
1112    t_FmPortTxBmiRegs   *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs;
1113
1114     /* check that counters are enabled */
1115    switch(counter)
1116    {
1117        case(e_FM_PORT_COUNTERS_CYCLE):
1118        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1119        case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
1120        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1121        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1122            /* performance counters - may be read when disabled */
1123            break;
1124        case(e_FM_PORT_COUNTERS_FRAME):
1125        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1126        case(e_FM_PORT_COUNTERS_LENGTH_ERR):
1127        case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
1128        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1129            if(!(GET_UINT32(p_BmiRegs->fmbm_tstc) & BMI_COUNTERS_EN))
1130               RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
1131            break;
1132        default:
1133            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports"));
1134    }
1135
1136    /* Set counter */
1137    switch(counter)
1138    {
1139        case(e_FM_PORT_COUNTERS_CYCLE):
1140           *p_Ptr = &p_BmiRegs->fmbm_tccn;
1141            break;
1142        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1143           *p_Ptr = &p_BmiRegs->fmbm_ttuc;
1144            break;
1145        case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
1146            *p_Ptr = &p_BmiRegs->fmbm_ttcquc;
1147            break;
1148        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1149           *p_Ptr = &p_BmiRegs->fmbm_tduc;
1150            break;
1151        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1152           *p_Ptr = &p_BmiRegs->fmbm_tfuc;
1153            break;
1154        case(e_FM_PORT_COUNTERS_FRAME):
1155           *p_Ptr = &p_BmiRegs->fmbm_tfrc;
1156            break;
1157        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1158           *p_Ptr = &p_BmiRegs->fmbm_tfdc;
1159            break;
1160        case(e_FM_PORT_COUNTERS_LENGTH_ERR):
1161           *p_Ptr = &p_BmiRegs->fmbm_tfledc;
1162            break;
1163        case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
1164            *p_Ptr = &p_BmiRegs->fmbm_tfufdc;
1165            break;
1166        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1167            *p_Ptr = &p_BmiRegs->fmbm_tbdc;
1168            break;
1169        default:
1170            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Tx ports"));
1171    }
1172
1173    return E_OK;
1174}
1175
1176static t_Error BmiOhPortCheckAndGetCounterPtr(t_FmPort *p_FmPort, e_FmPortCounters counter, volatile uint32_t **p_Ptr)
1177{
1178    t_FmPortOhBmiRegs   *p_BmiRegs = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs;
1179
1180    /* check that counters are enabled */
1181    switch(counter)
1182    {
1183        case(e_FM_PORT_COUNTERS_CYCLE):
1184        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1185        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1186        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1187            /* performance counters - may be read when disabled */
1188            break;
1189        case(e_FM_PORT_COUNTERS_FRAME):
1190        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1191        case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
1192        case(e_FM_PORT_COUNTERS_WRED_DISCARD):
1193        case(e_FM_PORT_COUNTERS_LENGTH_ERR):
1194        case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
1195        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1196            if(!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN))
1197               RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
1198            break;
1199        case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME): /* only valid for offline parsing */
1200            if(p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
1201                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Host Command ports"));
1202            if(!(GET_UINT32(p_BmiRegs->fmbm_ostc) & BMI_COUNTERS_EN))
1203               RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
1204            break;
1205        default:
1206            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for O/H ports"));
1207    }
1208
1209    /* Set counter */
1210    switch(counter)
1211    {
1212        case(e_FM_PORT_COUNTERS_CYCLE):
1213           *p_Ptr = &p_BmiRegs->fmbm_occn;
1214            break;
1215        case(e_FM_PORT_COUNTERS_TASK_UTIL):
1216           *p_Ptr = &p_BmiRegs->fmbm_otuc;
1217            break;
1218        case(e_FM_PORT_COUNTERS_DMA_UTIL):
1219           *p_Ptr = &p_BmiRegs->fmbm_oduc;
1220            break;
1221        case(e_FM_PORT_COUNTERS_FIFO_UTIL):
1222           *p_Ptr = &p_BmiRegs->fmbm_ofuc;
1223            break;
1224        case(e_FM_PORT_COUNTERS_FRAME):
1225           *p_Ptr = &p_BmiRegs->fmbm_ofrc;
1226            break;
1227        case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
1228           *p_Ptr = &p_BmiRegs->fmbm_ofdc;
1229            break;
1230        case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
1231           *p_Ptr = &p_BmiRegs->fmbm_offc;
1232            break;
1233        case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
1234#ifdef FM_PORT_COUNTERS_ERRATA_FMANg
1235        {
1236            t_FmRevisionInfo revInfo;
1237            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
1238            if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
1239                RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Requested counter is not available in rev1"));
1240        }
1241#endif /* FM_PORT_COUNTERS_ERRATA_FMANg */
1242          *p_Ptr = &p_BmiRegs->fmbm_ofldec;
1243            break;
1244        case(e_FM_PORT_COUNTERS_WRED_DISCARD):
1245           *p_Ptr = &p_BmiRegs->fmbm_ofwdc;
1246            break;
1247        case(e_FM_PORT_COUNTERS_LENGTH_ERR):
1248           *p_Ptr = &p_BmiRegs->fmbm_ofledc;
1249            break;
1250        case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
1251            *p_Ptr = &p_BmiRegs->fmbm_ofufdc;
1252            break;
1253        case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
1254            *p_Ptr = &p_BmiRegs->fmbm_obdc;
1255            break;
1256        default:
1257            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for O/H ports"));
1258    }
1259
1260    return E_OK;
1261}
1262
1263static t_Error  AdditionalPrsParams(t_FmPort *p_FmPort, t_FmPcdPrsAdditionalHdrParams *p_HdrParams, uint32_t *p_SoftSeqAttachReg)
1264{
1265    uint8_t                     hdrNum, Ipv4HdrNum;
1266    u_FmPcdHdrPrsOpts           *p_prsOpts;
1267    uint32_t                    tmpReg = 0, tmpPrsOffset;
1268
1269    if(IS_PRIVATE_HEADER(p_HdrParams->hdr) || IS_SPECIAL_HEADER(p_HdrParams->hdr))
1270        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("No additional parameters for private or special headers."));
1271
1272    if(p_HdrParams->errDisable)
1273        tmpReg |= PRS_HDR_ERROR_DIS;
1274
1275    /* Set parser options */
1276    if(p_HdrParams->usePrsOpts)
1277    {
1278        p_prsOpts = &p_HdrParams->prsOpts;
1279        switch(p_HdrParams->hdr)
1280        {
1281            case(HEADER_TYPE_MPLS):
1282                if(p_prsOpts->mplsPrsOptions.labelInterpretationEnable)
1283                    tmpReg |= PRS_HDR_MPLS_LBL_INTER_EN;
1284                GET_PRS_HDR_NUM(hdrNum, p_prsOpts->mplsPrsOptions.nextParse);
1285                if(hdrNum == ILLEGAL_HDR_NUM)
1286                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
1287                GET_PRS_HDR_NUM(Ipv4HdrNum, HEADER_TYPE_IPv4);
1288                if(hdrNum < Ipv4HdrNum)
1289                    RETURN_ERROR(MAJOR, E_INVALID_VALUE,
1290                        ("Header must be equal or higher than IPv4"));
1291                tmpReg |= ((uint32_t)hdrNum * PRS_HDR_ENTRY_SIZE) << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
1292                break;
1293            case(HEADER_TYPE_PPPoE):
1294                if(p_prsOpts->pppoePrsOptions.enableMTUCheck)
1295                {
1296#ifdef FM_PPPOE_NO_MTU_CHECK
1297                    t_FmRevisionInfo revInfo;
1298                    FM_GetRevision(p_FmPort->h_Fm, &revInfo);
1299                    if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
1300                        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Invalid parser option"));
1301                    else
1302#endif /* FM_PPPOE_NO_MTU_CHECK */
1303                        tmpReg |= PRS_HDR_PPPOE_MTU_CHECK_EN;
1304                }
1305                break;
1306            case(HEADER_TYPE_IPv6):
1307                if(p_prsOpts->ipv6PrsOptions.routingHdrDisable)
1308                    tmpReg |= PRS_HDR_IPV6_ROUTE_HDR_DIS;
1309                break;
1310            case(HEADER_TYPE_TCP):
1311                if(p_prsOpts->tcpPrsOptions.padIgnoreChecksum)
1312                   tmpReg |= PRS_HDR_TCP_PAD_REMOVAL;
1313                break;
1314            case(HEADER_TYPE_UDP):
1315                if(p_prsOpts->udpPrsOptions.padIgnoreChecksum)
1316                   tmpReg |= PRS_HDR_TCP_PAD_REMOVAL;
1317                break;
1318            default:
1319                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header"));
1320        }
1321    }
1322
1323    /* set software parsing (address is devided in 2 since parser uses 2 byte access. */
1324    if(p_HdrParams->swPrsEnable)
1325    {
1326        tmpPrsOffset = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, p_HdrParams->hdr, p_HdrParams->indexPerHdr);
1327        if(tmpPrsOffset == ILLEGAL_BASE)
1328            RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
1329        tmpReg |= (PRS_HDR_SW_PRS_EN | tmpPrsOffset);
1330    }
1331    *p_SoftSeqAttachReg = tmpReg;
1332
1333    return E_OK;
1334}
1335
1336static uint32_t GetPortSchemeBindParams(t_Handle h_FmPort, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
1337{
1338    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
1339    uint32_t                    walking1Mask = 0x80000000, tmp;
1340    uint8_t                     idx = 0;
1341
1342    p_SchemeBind->netEnvId = p_FmPort->netEnvId;
1343    p_SchemeBind->hardwarePortId = p_FmPort->hardwarePortId;
1344    p_SchemeBind->useClsPlan = p_FmPort->useClsPlan;
1345    p_SchemeBind->numOfSchemes = 0;
1346    tmp = p_FmPort->schemesPerPortVector;
1347    if(tmp)
1348    {
1349        while (tmp)
1350        {
1351            if(tmp & walking1Mask)
1352            {
1353                p_SchemeBind->schemesIds[p_SchemeBind->numOfSchemes] = FmPcdKgGetSchemeSwId(p_FmPort->h_FmPcd, idx);
1354                p_SchemeBind->numOfSchemes++;
1355                tmp &= ~walking1Mask;
1356            }
1357            walking1Mask >>= 1;
1358            idx++;
1359        }
1360    }
1361
1362    return tmp;
1363}
1364
1365static t_Error BuildBufferStructure(t_FmPort *p_FmPort)
1366{
1367    uint32_t                        tmp;
1368
1369    ASSERT_COND(p_FmPort);
1370
1371    /* Align start of internal context data to 16 byte */
1372    p_FmPort->p_FmPortDriverParam->intContext.extBufOffset =
1373        (uint16_t)((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize & (OFFSET_UNITS-1)) ?
1374            ((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize + OFFSET_UNITS) & ~(uint16_t)(OFFSET_UNITS-1)) :
1375             p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize);
1376
1377    /* Translate margin and intContext params to FM parameters */
1378#ifdef FM_INCORRECT_CS_ERRATA_FMAN18
1379    {
1380        t_FmRevisionInfo revInfo;
1381        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
1382        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
1383        {
1384            uint8_t mod = p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign % 256;
1385            if(mod)
1386            {
1387                p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign += (256-mod);
1388                DBG(WARNING,("dataAlign modified to next 256 to conform with FMAN18 errata\n"));
1389            }
1390        }
1391    }
1392#endif /* FM_INCORRECT_CS_ERRATA_FMAN18 */
1393
1394    /* Initialize with illegal value. Later we'll set legal values. */
1395    p_FmPort->bufferOffsets.prsResultOffset = (uint32_t)ILLEGAL_BASE;
1396    p_FmPort->bufferOffsets.timeStampOffset = (uint32_t)ILLEGAL_BASE;
1397    p_FmPort->bufferOffsets.hashResultOffset= (uint32_t)ILLEGAL_BASE;
1398    p_FmPort->bufferOffsets.pcdInfoOffset   = (uint32_t)ILLEGAL_BASE;
1399#ifdef DEBUG
1400    p_FmPort->bufferOffsets.debugOffset     = (uint32_t)ILLEGAL_BASE;
1401#endif /* DEBUG */
1402
1403    /* Internally the driver supports 4 options
1404       1. prsResult/timestamp/hashResult selection (in fact 8 options, but for simplicity we'll
1405          relate to it as 1).
1406       2. All IC context (from AD) except debug.
1407       3. Debug information only.
1408       4. All IC context (from AD) including debug.
1409       Note, that if user asks for prsResult/timestamp/hashResult and Debug, we give them (4) */
1410
1411    /* This 'if' covers options  2 & 4. We copy from beginning of context with or without debug. */
1412    /* If passAllOtherPCDInfo explicitly requested, or passDebugInfo+prs/ts --> we also take passAllOtherPCDInfo */
1413    if ((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo)
1414#ifdef DEBUG
1415        || (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passDebugInfo &&
1416         (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult ||
1417          p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp ||
1418          p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passHashResult))
1419#endif /* DEBUG */
1420       )
1421    {
1422#ifdef DEBUG
1423        if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passDebugInfo)
1424        {
1425            p_FmPort->p_FmPortDriverParam->intContext.size = 240;
1426            p_FmPort->bufferOffsets.debugOffset =
1427                (uint32_t)(p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + 128);
1428        }
1429        else
1430#endif /* DEBUG */
1431            p_FmPort->p_FmPortDriverParam->intContext.size = 128; /* must be aligned to 16 */
1432        /* Start copying data after 16 bytes (FD) from the beginning of the internal context */
1433        p_FmPort->p_FmPortDriverParam->intContext.intContextOffset = 16;
1434
1435        if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo)
1436            p_FmPort->bufferOffsets.pcdInfoOffset = p_FmPort->p_FmPortDriverParam->intContext.extBufOffset;
1437        if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult)
1438            p_FmPort->bufferOffsets.prsResultOffset =
1439                (uint32_t)(p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + 16);
1440        if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp)
1441            p_FmPort->bufferOffsets.timeStampOffset =
1442                (uint32_t)(p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + 48);
1443        if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passHashResult)
1444            p_FmPort->bufferOffsets.hashResultOffset =
1445                (uint32_t)(p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + 56);
1446    }
1447    else
1448    {
1449#ifdef DEBUG
1450        if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passDebugInfo)
1451        {
1452            /* This case covers option 3 */
1453            p_FmPort->p_FmPortDriverParam->intContext.size = 112;
1454            p_FmPort->p_FmPortDriverParam->intContext.intContextOffset = 144;
1455            p_FmPort->bufferOffsets.debugOffset = p_FmPort->p_FmPortDriverParam->intContext.extBufOffset;
1456        }
1457        else
1458#endif /* DEBUG */
1459        {
1460            /* This case covers the options under 1 */
1461            /* Copy size must be in 16-byte granularity. */
1462            p_FmPort->p_FmPortDriverParam->intContext.size =
1463                (uint16_t)((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult ? 32 : 0) +
1464                          ((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp ||
1465                          p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passHashResult) ? 16 : 0));
1466
1467            /* Align start of internal context data to 16 byte */
1468            p_FmPort->p_FmPortDriverParam->intContext.intContextOffset =
1469                (uint8_t)(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult ? 32 :
1470                          ((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp  ||
1471                           p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passHashResult) ? 64 : 0));
1472
1473            if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult)
1474                p_FmPort->bufferOffsets.prsResultOffset = p_FmPort->p_FmPortDriverParam->intContext.extBufOffset;
1475            if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp)
1476                p_FmPort->bufferOffsets.timeStampOffset =  p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult ?
1477                                            (p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + sizeof(t_FmPrsResult)) :
1478                                            p_FmPort->p_FmPortDriverParam->intContext.extBufOffset;
1479            if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passHashResult)
1480                /* If PR is not requested, whether TS is requested or not, IC will be copied from TS */
1481                p_FmPort->bufferOffsets.hashResultOffset = p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult ?
1482                                              (p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + sizeof(t_FmPrsResult) + 8) :
1483                                              p_FmPort->p_FmPortDriverParam->intContext.extBufOffset + 8;
1484        }
1485    }
1486
1487    p_FmPort->p_FmPortDriverParam->bufMargins.startMargins =
1488        (uint16_t)(p_FmPort->p_FmPortDriverParam->intContext.extBufOffset +
1489                   p_FmPort->p_FmPortDriverParam->intContext.size);
1490#ifdef FM_CAPWAP_SUPPORT
1491    /* save extra space for manip in both external and internal buffers */
1492    if(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace)
1493    {
1494        if((p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace + FRAG_EXTRA_SPACE) >= 256)
1495            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace + 32 can not be equal or larger to 256"));
1496        p_FmPort->bufferOffsets.manipOffset = p_FmPort->p_FmPortDriverParam->bufMargins.startMargins;
1497        p_FmPort->p_FmPortDriverParam->bufMargins.startMargins += (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace + FRAG_EXTRA_SPACE);
1498        p_FmPort->p_FmPortDriverParam->internalBufferOffset =
1499            (uint8_t)(p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace + FRAG_EXTRA_SPACE);
1500    }
1501#endif /* FM_CAPWAP_SUPPORT */
1502
1503    /* align data start */
1504    tmp = (uint32_t)(p_FmPort->p_FmPortDriverParam->bufMargins.startMargins %
1505                     p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign);
1506    if (tmp)
1507        p_FmPort->p_FmPortDriverParam->bufMargins.startMargins += (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign-tmp);
1508    p_FmPort->bufferOffsets.dataOffset = p_FmPort->p_FmPortDriverParam->bufMargins.startMargins;
1509    p_FmPort->internalBufferOffset = p_FmPort->p_FmPortDriverParam->internalBufferOffset;
1510
1511    return E_OK;
1512}
1513
1514static t_Error SetPcd(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParams)
1515{
1516    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
1517    t_Error                             err = E_OK;
1518    uint32_t                            tmpReg;
1519    volatile uint32_t                   *p_BmiNia=NULL;
1520    volatile uint32_t                   *p_BmiPrsNia=NULL;
1521    volatile uint32_t                   *p_BmiPrsStartOffset=NULL;
1522    volatile uint32_t                   *p_BmiInitPrsResult=NULL;
1523    volatile uint32_t                   *p_BmiCcBase=NULL;
1524    uint8_t                             hdrNum, L3HdrNum, greHdrNum;
1525    int                                 i;
1526    bool                                isEmptyClsPlanGrp;
1527    uint32_t                            tmpHxs[FM_PCD_PRS_NUM_OF_HDRS];
1528    uint16_t                            absoluteProfileId;
1529    uint8_t                             physicalSchemeId;
1530    uint32_t                            ccTreePhysOffset;
1531    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
1532    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
1533
1534    if (p_FmPort->imEn)
1535        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
1536
1537    if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
1538        (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
1539        (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
1540        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
1541
1542    p_FmPort->netEnvId = (uint8_t)(PTR_TO_UINT(p_PcdParams->h_NetEnv)-1);
1543
1544    p_FmPort->pcdEngines = 0;
1545
1546    /* initialize p_FmPort->pcdEngines field in port's structure */
1547    switch(p_PcdParams->pcdSupport)
1548    {
1549        case(e_FM_PORT_PCD_SUPPORT_NONE):
1550            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No PCD configuration required if e_FM_PORT_PCD_SUPPORT_NONE selected"));
1551        case(e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
1552            p_FmPort->pcdEngines |= FM_PCD_PRS;
1553            break;
1554        case(e_FM_PORT_PCD_SUPPORT_PLCR_ONLY):
1555            if (CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1556                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser support is required"));
1557            p_FmPort->pcdEngines |= FM_PCD_PLCR;
1558            break;
1559        case(e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
1560            p_FmPort->pcdEngines |= FM_PCD_PRS;
1561            p_FmPort->pcdEngines |= FM_PCD_PLCR;
1562            break;
1563        case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
1564            p_FmPort->pcdEngines |= FM_PCD_PRS;
1565            p_FmPort->pcdEngines |= FM_PCD_KG;
1566            break;
1567        case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
1568            p_FmPort->pcdEngines |= FM_PCD_PRS;
1569            p_FmPort->pcdEngines |= FM_PCD_CC;
1570            p_FmPort->pcdEngines |= FM_PCD_KG;
1571            break;
1572        case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
1573            p_FmPort->pcdEngines |= FM_PCD_PRS;
1574            p_FmPort->pcdEngines |= FM_PCD_KG;
1575            p_FmPort->pcdEngines |= FM_PCD_CC;
1576            p_FmPort->pcdEngines |= FM_PCD_PLCR;
1577            break;
1578        case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
1579            p_FmPort->pcdEngines |= FM_PCD_PRS;
1580            p_FmPort->pcdEngines |= FM_PCD_KG;
1581            p_FmPort->pcdEngines |= FM_PCD_PLCR;
1582            break;
1583
1584#ifdef FM_CAPWAP_SUPPORT
1585        case(e_FM_PORT_PCD_SUPPORT_CC_ONLY):
1586            if (CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1587                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser support is required"));
1588            p_FmPort->pcdEngines |= FM_PCD_CC;
1589            break;
1590        case(e_FM_PORT_PCD_SUPPORT_CC_AND_KG):
1591            if (CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1592                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser support is required"));
1593            p_FmPort->pcdEngines |= FM_PCD_CC;
1594            p_FmPort->pcdEngines |= FM_PCD_KG;
1595            break;
1596        case(e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR):
1597            if (CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1598                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser support is required"));
1599            p_FmPort->pcdEngines |= FM_PCD_CC;
1600            p_FmPort->pcdEngines |= FM_PCD_KG;
1601            p_FmPort->pcdEngines |= FM_PCD_PLCR;
1602            break;
1603#endif /* FM_CAPWAP_SUPPORT */
1604        default:
1605            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid pcdSupport"));
1606    }
1607
1608    if((p_FmPort->pcdEngines & FM_PCD_PRS) && (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams > FM_PCD_PRS_NUM_OF_HDRS))
1609        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Port parser numOfHdrsWithAdditionalParams may not exceed %d", FM_PCD_PRS_NUM_OF_HDRS));
1610
1611    /* check that parameters exist for each and only each defined engine */
1612    if((!!(p_FmPort->pcdEngines & FM_PCD_PRS) != !!p_PcdParams->p_PrsParams) ||
1613        (!!(p_FmPort->pcdEngines & FM_PCD_KG) != !!p_PcdParams->p_KgParams) ||
1614        (!!(p_FmPort->pcdEngines & FM_PCD_CC) != !!p_PcdParams->p_CcParams))
1615        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistant with pcdSupport"));
1616
1617    /* get PCD registers pointers */
1618    switch(p_FmPort->portType)
1619    {
1620        case(e_FM_PORT_TYPE_RX_10G):
1621        case(e_FM_PORT_TYPE_RX):
1622            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
1623            p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
1624            p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
1625            p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[0];
1626            p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb;
1627            break;
1628        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
1629            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
1630            p_BmiPrsNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
1631            p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
1632            p_BmiInitPrsResult = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[0];
1633            p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb;
1634            break;
1635        default:
1636            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
1637    }
1638
1639    if(p_FmPort->pcdEngines & FM_PCD_KG)
1640    {
1641
1642        if(p_PcdParams->p_KgParams->numOfSchemes == 0)
1643            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For ports using Keygen, at lease one scheme must be bound. "));
1644        /* for each scheme */
1645        for(i = 0; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
1646        {
1647            physicalSchemeId = (uint8_t)(PTR_TO_UINT(p_PcdParams->p_KgParams->h_Schemes[i])-1);
1648            /* build vector */
1649            p_FmPort->schemesPerPortVector |= 1 << (31 - (uint32_t)physicalSchemeId);
1650        }
1651
1652        err = FmPcdKgSetOrBindToClsPlanGrp(p_FmPort->h_FmPcd,
1653                                            p_FmPort->hardwarePortId,
1654                                            p_FmPort->netEnvId,
1655                                            p_FmPort->optArray,
1656                                            &p_FmPort->clsPlanGrpId,
1657                                            &isEmptyClsPlanGrp);
1658         if(err)
1659             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FmPcdKgSetOrBindToClsPlanGrp failed. "));
1660
1661         p_FmPort->useClsPlan = !isEmptyClsPlanGrp;
1662    }
1663
1664    /* set PCD port parameter */
1665    if(p_FmPort->pcdEngines & FM_PCD_CC)
1666    {
1667        err = FmPcdCcBindTree(p_FmPort->h_FmPcd, p_PcdParams->p_CcParams->h_CcTree, &ccTreePhysOffset, h_FmPort);
1668        if(err)
1669            RETURN_ERROR(MINOR, err, NO_MSG);
1670
1671        WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
1672        p_FmPort->ccTreeId = p_PcdParams->p_CcParams->h_CcTree;
1673    }
1674
1675    /***************************/
1676    /* configure NIA after BMI */
1677    /***************************/
1678    if (!CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1679        /* rfne may contain FDCS bits, so first we read them. */
1680        p_FmPort->savedBmiNia = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
1681
1682    /* If policer is used directly after BMI or PRS */
1683    if((p_FmPort->pcdEngines & FM_PCD_PLCR) &&
1684        ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PLCR_ONLY) ||
1685                (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR)))
1686    {
1687        absoluteProfileId = (uint16_t)(PTR_TO_UINT(p_PcdParams->p_PlcrParams->h_Profile)-1);
1688
1689        if(!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
1690            RETURN_ERROR(MINOR, E_INVALID_STATE, ("Private port profile not valid."));
1691
1692        tmpReg = (uint32_t)(absoluteProfileId | NIA_PLCR_ABSOLUTE);
1693
1694        if(p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
1695        {
1696            /* update BMI HPNIA */
1697            WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_PLCR | tmpReg));
1698        }
1699        else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
1700            /* update BMI NIA */
1701            p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PLCR);
1702    }
1703
1704#ifdef FM_CAPWAP_SUPPORT
1705    /* if CC is used directly after BMI */
1706    if((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_ONLY) ||
1707        (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG) ||
1708        (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR))
1709    {
1710        if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
1711            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("e_FM_PORT_PCD_SUPPORT_CC_xx available for offline parsing ports only"));
1712        p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
1713         /* check that prs start offset == RIM[FOF] */
1714    }
1715#endif /* FM_CAPWAP_SUPPORT */
1716
1717    if (p_FmPort->pcdEngines & FM_PCD_PRS)
1718    {
1719        ASSERT_COND(p_PcdParams->p_PrsParams);
1720        /* if PRS is used it is always first */
1721        GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->firstPrsHdr);
1722        if (hdrNum == ILLEGAL_HDR_NUM)
1723            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
1724        if (!CHECK_FM_CTL_AC_POST_FETCH_PCD(p_FmPort->savedBmiNia))
1725            p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PRS | (uint32_t)(hdrNum));
1726        /* set after parser NIA */
1727        tmpReg = 0;
1728        switch(p_PcdParams->pcdSupport)
1729        {
1730            case(e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
1731                WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
1732                break;
1733            case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
1734            case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
1735                tmpReg = NIA_KG_CC_EN;
1736            case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
1737            case(e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
1738                if(p_PcdParams->p_KgParams->directScheme)
1739                {
1740                    physicalSchemeId = (uint8_t)(PTR_TO_UINT(p_PcdParams->p_KgParams->h_DirectScheme)-1);
1741                    /* check that this scheme was bound to this port */
1742                    for(i=0 ; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
1743                        if(p_PcdParams->p_KgParams->h_DirectScheme == p_PcdParams->p_KgParams->h_Schemes[i])
1744                            break;
1745                    if(i == p_PcdParams->p_KgParams->numOfSchemes)
1746                        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Direct scheme is not one of the port selected schemes."));
1747                    tmpReg |= (uint32_t)(NIA_KG_DIRECT | physicalSchemeId);
1748                }
1749                WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_KG | tmpReg);
1750                break;
1751            case(e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
1752                break;
1753            default:
1754                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid PCD support"));
1755        }
1756
1757        /* set start parsing offset */
1758        /* WRITE_UINT32(*p_BmiPrsStartOffset, p_PcdParams->p_PrsParams->parsingOffset); */
1759
1760        /************************************/
1761        /* Parser port parameters           */
1762        /************************************/
1763        /* stop before configuring */
1764        WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
1765        /* wait for parser to be in idle state */
1766        while(GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
1767
1768        /* set soft seq attachment register */
1769        memset(tmpHxs, 0, FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t));
1770
1771        /* set protocol options */
1772        for(i=0;p_FmPort->optArray[i];i++)
1773            switch(p_FmPort->optArray[i])
1774            {
1775                case(ETH_BROADCAST):
1776                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
1777                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_BC_SHIFT;
1778                    break;
1779                case(ETH_MULTICAST):
1780                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
1781                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_MC_SHIFT;
1782                    break;
1783                case(VLAN_STACKED):
1784                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_VLAN)
1785                    tmpHxs[hdrNum] |= (i+1)<< PRS_HDR_VLAN_STACKED_SHIFT;
1786                    break;
1787                case(MPLS_STACKED):
1788                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
1789                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_MPLS_STACKED_SHIFT;
1790                    break;
1791                case(IPV4_BROADCAST_1):
1792                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
1793                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_BC_SHIFT;
1794                    break;
1795                case(IPV4_MULTICAST_1):
1796                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
1797                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_MC_SHIFT;
1798                    break;
1799                case(IPV4_UNICAST_2):
1800                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
1801                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_UC_SHIFT;
1802                    break;
1803                case(IPV4_MULTICAST_BROADCAST_2):
1804                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
1805                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_MC_BC_SHIFT;
1806                    break;
1807                case(IPV6_MULTICAST_1):
1808                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
1809                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_1_MC_SHIFT;
1810                    break;
1811                case(IPV6_UNICAST_2):
1812                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
1813                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_UC_SHIFT;
1814                    break;
1815                case(IPV6_MULTICAST_2):
1816                    GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
1817                    tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_MC_SHIFT;
1818                    break;
1819            }
1820
1821        if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, p_FmPort->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP))
1822        {
1823            p_PcdParams->p_PrsParams->additionalParams
1824                [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].hdr = HEADER_TYPE_UDP;
1825            p_PcdParams->p_PrsParams->additionalParams
1826                [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].swPrsEnable = TRUE;
1827            p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams++;
1828        }
1829
1830        /* set MPLS default next header - HW reset workaround  */
1831        GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
1832        tmpHxs[hdrNum] |= PRS_HDR_MPLS_LBL_INTER_EN;
1833        GET_PRS_HDR_NUM(L3HdrNum, HEADER_TYPE_USER_DEFINED_L3);
1834        tmpHxs[hdrNum] |= (uint32_t)L3HdrNum  << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
1835
1836        /* for GRE, disable errors */
1837        GET_PRS_HDR_NUM(greHdrNum, HEADER_TYPE_GRE);
1838        tmpHxs[greHdrNum] |= PRS_HDR_ERROR_DIS;
1839
1840        /* config additional params for specific headers */
1841        for(i=0 ; i<p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams ; i++)
1842        {
1843            GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->additionalParams[i].hdr);
1844            if(hdrNum== ILLEGAL_HDR_NUM)
1845                RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
1846            if(hdrNum==NO_HDR_NUM)
1847                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Private headers may not use additional parameters"));
1848
1849            err = AdditionalPrsParams(p_FmPort, &p_PcdParams->p_PrsParams->additionalParams[i], &tmpReg);
1850            if(err)
1851                RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
1852
1853            tmpHxs[hdrNum] |= tmpReg;
1854        }
1855#ifdef FM_PRS_L4_SHELL_ERRATA_FMANb
1856        {
1857            t_FmRevisionInfo revInfo;
1858            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
1859            if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
1860            {
1861               /* link to sw parser code for L4 shells - only if no other code is applied. */
1862                GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_SCTP)
1863                if(!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
1864                    tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | SCTP_SW_PATCH_START);
1865                GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_DCCP)
1866                if(!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
1867                    tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | DCCP_SW_PATCH_START);
1868                GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPSEC_AH)
1869                if(!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
1870                    tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IPSEC_SW_PATCH_START);
1871            }
1872        }
1873#endif /* FM_PRS_L4_SHELL_ERRATA_FMANb */
1874
1875        for(i=0 ; i<FM_PCD_PRS_NUM_OF_HDRS ; i++)
1876        {
1877            /* For all header set LCV as taken from netEnv*/
1878            WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].lcv,  FmPcdGetLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId, (uint8_t)i));
1879            /* set HXS register according to default+Additional params+protocol options */
1880            WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].softSeqAttach,  tmpHxs[i]);
1881        }
1882
1883        /* set tpid. */
1884        tmpReg = PRS_TPID_DFLT;
1885        if(p_PcdParams->p_PrsParams->setVlanTpid1)
1886        {
1887            tmpReg &= PRS_TPID2_MASK;
1888            tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid1 << PRS_PCTPID_SHIFT;
1889        }
1890        if(p_PcdParams->p_PrsParams->setVlanTpid2)
1891        {
1892            tmpReg &= PRS_TPID1_MASK;
1893            tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid2;
1894        }
1895        WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pctpid, tmpReg);
1896
1897        /* enable parser */
1898        WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, 0);
1899
1900        if(p_PcdParams->p_PrsParams->prsResultPrivateInfo)
1901            p_FmPort->privateInfo = p_PcdParams->p_PrsParams->prsResultPrivateInfo;
1902
1903    } /* end parser */
1904    else
1905        p_FmPort->privateInfo = 0;
1906
1907    WRITE_UINT32(*p_BmiPrsStartOffset, GET_UINT32(*p_BmiPrsStartOffset) + p_FmPort->internalBufferOffset);
1908
1909    /* set initial parser result - used for all engines */
1910    for (i=0;i<FM_PORT_PRS_RESULT_NUM_OF_WORDS;i++)
1911    {
1912        if (!i)
1913            WRITE_UINT32(*(p_BmiInitPrsResult), (uint32_t)(((uint32_t)p_FmPort->privateInfo << BMI_PR_PORTID_SHIFT)
1914                                                            | BMI_PRS_RESULT_HIGH));
1915        else
1916            if (i< FM_PORT_PRS_RESULT_NUM_OF_WORDS/2)
1917                WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_HIGH);
1918            else
1919                WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_LOW);
1920    }
1921
1922    return E_OK;
1923}
1924
1925static t_Error DeletePcd(t_Handle h_FmPort)
1926{
1927    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
1928    t_Error                             err = E_OK;
1929    volatile uint32_t                   *p_BmiNia=NULL;
1930
1931    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
1932    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
1933
1934    if (p_FmPort->imEn)
1935        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
1936
1937    if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
1938        (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
1939        (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
1940        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
1941
1942    if(!p_FmPort->pcdEngines)
1943        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("called for non PCD port"));
1944
1945    /* get PCD registers pointers */
1946    switch(p_FmPort->portType)
1947    {
1948        case(e_FM_PORT_TYPE_RX_10G):
1949        case(e_FM_PORT_TYPE_RX):
1950            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
1951            break;
1952        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
1953            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
1954            break;
1955        default:
1956            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
1957    }
1958
1959    if((GET_UINT32(*p_BmiNia) & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
1960        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("port has to be detached previousely"));
1961
1962    /* "cut" PCD out of the port's flow - go to BMI */
1963    /* WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); */
1964
1965    if(p_FmPort->pcdEngines | FM_PCD_PRS)
1966    {
1967        /* stop parser */
1968        WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
1969        /* wait for parser to be in idle state */
1970        while(GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
1971    }
1972
1973    if(p_FmPort->pcdEngines & FM_PCD_KG)
1974    {
1975        err = FmPcdKgDeleteOrUnbindPortToClsPlanGrp(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, p_FmPort->clsPlanGrpId);
1976        if(err)
1977            RETURN_ERROR(MINOR, err, NO_MSG);
1978        p_FmPort->useClsPlan = FALSE;
1979    }
1980
1981    if(p_FmPort->pcdEngines & FM_PCD_CC)
1982    {
1983        /* unbind - we need to get the treeId too */
1984        err = FmPcdCcUnbindTree(p_FmPort->h_FmPcd,  p_FmPort->ccTreeId);
1985        if(err)
1986            RETURN_ERROR(MINOR, err, NO_MSG);
1987    }
1988
1989    p_FmPort->pcdEngines = 0;
1990
1991    return E_OK;
1992}
1993
1994
1995/********************************************/
1996/*  Inter-module API                        */
1997/********************************************/
1998void FmPortSetMacsecLcv(t_Handle h_FmPort)
1999{
2000    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
2001    volatile uint32_t           *p_BmiCfgReg = NULL;
2002    uint32_t                    macsecEn = BMI_PORT_CFG_EN_MACSEC;
2003    uint32_t                    lcv, walking1Mask = 0x80000000;
2004    uint8_t                     cnt = 0;
2005
2006    SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
2007    SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
2008
2009    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2010    {
2011        REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Rx ports only"));
2012        return;
2013    }
2014
2015    p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
2016    /* get LCV for MACSEC */
2017    if ((p_FmPort->h_FmPcd) && ((lcv = FmPcdGetMacsecLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId))!= 0))
2018    {
2019        while(!(lcv & walking1Mask))
2020        {
2021            cnt++;
2022            walking1Mask >>= 1;
2023        }
2024
2025        macsecEn |= (uint32_t)cnt << BMI_PORT_CFG_MS_SEL_SHIFT;
2026     }
2027
2028     WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | macsecEn);
2029}
2030
2031void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci)
2032{
2033    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
2034    volatile uint32_t           *p_BmiCfgReg = NULL;
2035    uint32_t                    tmpReg;
2036
2037    SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
2038    SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
2039
2040    if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
2041    {
2042        REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Tx ports only"));
2043        return;
2044    }
2045
2046    p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfca;
2047    tmpReg = GET_UINT32(*p_BmiCfgReg) & ~BMI_CMD_ATTR_MACCMD_MASK;
2048    tmpReg |= BMI_CMD_ATTR_MACCMD_SECURED;
2049    tmpReg |= (((uint32_t)dfltSci << BMI_CMD_ATTR_MACCMD_SC_SHIFT) & BMI_CMD_ATTR_MACCMD_SC_MASK);
2050
2051    WRITE_UINT32(*p_BmiCfgReg, tmpReg);
2052}
2053
2054uint8_t FmPortGetNetEnvId(t_Handle h_FmPort)
2055{
2056    return ((t_FmPort*)h_FmPort)->netEnvId;
2057}
2058
2059uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort)
2060{
2061    return ((t_FmPort*)h_FmPort)->hardwarePortId;
2062}
2063
2064uint32_t FmPortGetPcdEngines(t_Handle h_FmPort)
2065{
2066    return ((t_FmPort*)h_FmPort)->pcdEngines;
2067}
2068
2069t_Error FmPortAttachPCD(t_Handle h_FmPort)
2070{
2071    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
2072    volatile uint32_t                   *p_BmiNia=NULL;
2073
2074/*TODO - to take care about the chnges that were made in the port because of the previously assigned tree.
2075pndn, pnen ... maybe were changed because of the Tree requirement*/
2076
2077    /* get PCD registers pointers */
2078    switch(p_FmPort->portType)
2079    {
2080        case(e_FM_PORT_TYPE_RX_10G):
2081        case(e_FM_PORT_TYPE_RX):
2082            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
2083            break;
2084        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2085            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
2086            break;
2087        default:
2088            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
2089    }
2090
2091    if(p_FmPort->requiredAction  & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
2092        if(FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 1)!= E_OK)
2093            RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
2094
2095    /* check that current NIA is BMI to BMI */
2096    if((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
2097            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
2098
2099    WRITE_UINT32(*p_BmiNia, p_FmPort->savedBmiNia);
2100
2101    if(p_FmPort->requiredAction  & UPDATE_NIA_PNEN)
2102        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, p_FmPort->savedQmiPnen);
2103
2104    if(p_FmPort->requiredAction  & UPDATE_NIA_PNDN)
2105        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, p_FmPort->savedNonRxQmiRegsPndn);
2106
2107
2108    return E_OK;
2109}
2110
2111t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_CcParams)
2112{
2113    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
2114    int                 tmpInt;
2115    volatile uint32_t   *p_BmiPrsStartOffset = NULL;
2116
2117    /* this function called from Cc for pass and receive parameters port params between CC and PORT*/
2118
2119    if((p_CcParams->getCcParams.type & OFFSET_OF_PR) && (p_FmPort->bufferOffsets.prsResultOffset != ILLEGAL_BASE))
2120    {
2121        p_CcParams->getCcParams.prOffset = (uint8_t)p_FmPort->bufferOffsets.prsResultOffset;
2122        p_CcParams->getCcParams.type &= ~OFFSET_OF_PR;
2123    }
2124    if(p_CcParams->getCcParams.type & HW_PORT_ID)
2125    {
2126        p_CcParams->getCcParams.hardwarePortId = (uint8_t)p_FmPort->hardwarePortId;
2127        p_CcParams->getCcParams.type &= ~HW_PORT_ID;
2128    }
2129    if((p_CcParams->getCcParams.type & OFFSET_OF_DATA) && (p_FmPort->bufferOffsets.dataOffset != ILLEGAL_BASE))
2130    {
2131        p_CcParams->getCcParams.dataOffset = (uint16_t)p_FmPort->bufferOffsets.dataOffset;
2132        p_CcParams->getCcParams.type &= ~OFFSET_OF_DATA;
2133    }
2134    if(p_CcParams->getCcParams.type & NUM_OF_TASKS)
2135    {
2136        p_CcParams->getCcParams.numOfTasks = p_FmPort->numOfTasks;
2137        p_CcParams->getCcParams.type &= ~NUM_OF_TASKS;
2138    }
2139    if(p_CcParams->getCcParams.type & BUFFER_POOL_ID_FOR_MANIP)
2140    {
2141        if(p_CcParams->getCcParams.poolIndex < p_FmPort->extBufPools.numOfPoolsUsed)
2142        {
2143            p_CcParams->getCcParams.poolIdForManip = p_FmPort->extBufPools.extBufPool[p_CcParams->getCcParams.poolIndex].id;
2144            p_CcParams->getCcParams.type &= ~BUFFER_POOL_ID_FOR_MANIP;
2145        }
2146    }
2147
2148    if((p_CcParams->setCcParams.type & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) && !(p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY))
2149    {
2150        p_FmPort->requiredAction |= UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
2151    }
2152
2153    if((p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) && !(p_FmPort->requiredAction & UPDATE_NIA_PNEN))
2154    {
2155        p_FmPort->savedQmiPnen = p_CcParams->setCcParams.nia;
2156        p_FmPort->requiredAction |= UPDATE_NIA_PNEN;
2157    }
2158    else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNEN)
2159    {
2160       if(p_FmPort->savedQmiPnen != p_CcParams->setCcParams.nia)
2161            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("pnen was defined previously different"));
2162    }
2163
2164    if((p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) && !(p_FmPort->requiredAction & UPDATE_NIA_PNDN))
2165    {
2166        p_FmPort->savedNonRxQmiRegsPndn = p_CcParams->setCcParams.nia;
2167        p_FmPort->requiredAction |= UPDATE_NIA_PNDN;
2168    }
2169    else if(p_CcParams->setCcParams.type & UPDATE_NIA_PNDN)
2170    {
2171        if(p_FmPort->savedNonRxQmiRegsPndn != p_CcParams->setCcParams.nia)
2172            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("pndn was defined previously different"));
2173    }
2174
2175
2176    if((p_CcParams->setCcParams.type & UPDATE_PSO) && !(p_FmPort->requiredAction & UPDATE_PSO))
2177    {
2178        /* get PCD registers pointers */
2179         switch(p_FmPort->portType)
2180         {
2181             case(e_FM_PORT_TYPE_RX_10G):
2182             case(e_FM_PORT_TYPE_RX):
2183                 p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
2184                 break;
2185             case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2186                 p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
2187                 break;
2188             default:
2189                 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
2190         }
2191        /* set start parsing offset */
2192        tmpInt = (int)GET_UINT32(*p_BmiPrsStartOffset)+ p_CcParams->setCcParams.psoSize;
2193        if(tmpInt>0)
2194            WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)tmpInt);
2195
2196        p_FmPort->requiredAction |= UPDATE_PSO;
2197        p_FmPort->savedPrsStartOffset = p_CcParams->setCcParams.psoSize;
2198
2199    }
2200    else if (p_CcParams->setCcParams.type & UPDATE_PSO)
2201    {
2202        if(p_FmPort->savedPrsStartOffset != p_CcParams->setCcParams.psoSize)
2203            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser start offset was defoned previousley different"));
2204    }
2205    return E_OK;
2206}
2207/**********************************         End of inter-module routines ********************************/
2208
2209/****************************************/
2210/*       API Init unit functions        */
2211/****************************************/
2212t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams)
2213{
2214    t_FmPort    *p_FmPort;
2215    uintptr_t   baseAddr = p_FmPortParams->baseAddr;
2216
2217    /* Allocate FM structure */
2218    p_FmPort = (t_FmPort *) XX_Malloc(sizeof(t_FmPort));
2219    if (!p_FmPort)
2220    {
2221        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver structure"));
2222        return NULL;
2223    }
2224    memset(p_FmPort, 0, sizeof(t_FmPort));
2225
2226    /* Allocate the FM driver's parameters structure */
2227    p_FmPort->p_FmPortDriverParam = (t_FmPortDriverParam *)XX_Malloc(sizeof(t_FmPortDriverParam));
2228    if (!p_FmPort->p_FmPortDriverParam)
2229    {
2230        XX_Free(p_FmPort);
2231        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver parameters"));
2232        return NULL;
2233    }
2234    memset(p_FmPort->p_FmPortDriverParam, 0, sizeof(t_FmPortDriverParam));
2235
2236    /* Initialize FM port parameters which will be kept by the driver */
2237    p_FmPort->portType      = p_FmPortParams->portType;
2238    p_FmPort->portId        = p_FmPortParams->portId;
2239    p_FmPort->pcdEngines    = FM_PCD_NONE;
2240    p_FmPort->f_Exception   = p_FmPortParams->f_Exception;
2241    p_FmPort->h_App         = p_FmPortParams->h_App;
2242    p_FmPort->h_Fm          = p_FmPortParams->h_Fm;
2243
2244    /* calculate global portId number */
2245    SW_PORT_ID_TO_HW_PORT_ID(p_FmPort->hardwarePortId, p_FmPort->portType, p_FmPortParams->portId);
2246
2247    /* Initialize FM port parameters for initialization phase only */
2248    p_FmPort->p_FmPortDriverParam->baseAddr                         = baseAddr;
2249    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize = DEFAULT_PORT_bufferPrefixContent_privDataSize;
2250    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult= DEFAULT_PORT_bufferPrefixContent_passPrsResult;
2251    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp= DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
2252    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo
2253                                                                    = DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
2254#ifdef DEBUG
2255    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passDebugInfo= DEFAULT_PORT_bufferPrefixContent_debugInfo;
2256#endif /* DEBUG */
2257    p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign    = DEFAULT_PORT_bufferPrefixContent_dataAlign;
2258    p_FmPort->p_FmPortDriverParam->dmaSwapData                      = DEFAULT_PORT_dmaSwapData;
2259    p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr           = DEFAULT_PORT_dmaIntContextCacheAttr;
2260    p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr               = DEFAULT_PORT_dmaHeaderCacheAttr;
2261    p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr        = DEFAULT_PORT_dmaScatterGatherCacheAttr;
2262    p_FmPort->p_FmPortDriverParam->dmaWriteOptimize                 = DEFAULT_PORT_dmaWriteOptimize;
2263    p_FmPort->p_FmPortDriverParam->liodnBase                        = p_FmPortParams->liodnBase;
2264
2265    /* resource distribution. */
2266    p_FmPort->fifoBufs.num                     = DEFAULT_PORT_sizeOfFifo(p_FmPort->portType);
2267    p_FmPort->fifoBufs.extra                   = DEFAULT_PORT_extraSizeOfFifo(p_FmPort->portType);
2268    p_FmPort->openDmas.num                     = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType);
2269    p_FmPort->openDmas.extra                   = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType);
2270    p_FmPort->tasks.num                        = DEFAULT_PORT_numOfTasks(p_FmPort->portType);
2271    p_FmPort->tasks.extra                      = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType);
2272    p_FmPort->numOfTasks = (uint8_t)p_FmPort->tasks.num;
2273#ifdef FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16
2274    {
2275        t_FmRevisionInfo revInfo;
2276        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2277        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
2278        {
2279            p_FmPort->fifoBufs.extra           = 0;
2280            p_FmPort->openDmas.extra           = 0;
2281            p_FmPort->tasks.extra              = 0;
2282        }
2283    }
2284#endif /* FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16 */
2285
2286    p_FmPort->p_FmPortDriverParam->color                            = DEFAULT_PORT_color;
2287#ifdef FM_OP_PORT_QMAN_REJECT_ERRATA_FMAN21
2288    {
2289        t_FmRevisionInfo revInfo;
2290        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2291        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0) &&
2292            (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
2293                p_FmPort->p_FmPortDriverParam->color              = e_FM_PORT_COLOR_OVERRIDE;
2294    }
2295#endif /* FM_OP_PORT_QMAN_REJECT_ERRATA_FMAN21 */
2296
2297    if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
2298        p_FmPort->p_FmPortDriverParam->syncReq          = DEFAULT_PORT_syncReqForHc;
2299    else
2300        p_FmPort->p_FmPortDriverParam->syncReq          = DEFAULT_PORT_syncReq;
2301
2302#ifdef FM_PORT_SYNC_ERRATA_FMAN6
2303    {
2304        t_FmRevisionInfo revInfo;
2305        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2306        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0) &&
2307            (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
2308                p_FmPort->p_FmPortDriverParam->syncReq              = FALSE;
2309    }
2310#endif /* FM_PORT_SYNC_ERRATA_FMAN6 */
2311
2312    /* Port type specific initialization: */
2313    if ((p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
2314        (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
2315        p_FmPort->p_FmPortDriverParam->frmDiscardOverride           = DEFAULT_PORT_frmDiscardOverride;
2316
2317    switch(p_FmPort->portType)
2318    {
2319    case(e_FM_PORT_TYPE_RX):
2320    case(e_FM_PORT_TYPE_RX_10G):
2321        /* Initialize FM port parameters for initialization phase only */
2322        p_FmPort->p_FmPortDriverParam->cutBytesFromEnd              = DEFAULT_PORT_cutBytesFromEnd;
2323        p_FmPort->p_FmPortDriverParam->enBufPoolDepletion           = FALSE;
2324        p_FmPort->p_FmPortDriverParam->frmDiscardOverride           = DEFAULT_PORT_frmDiscardOverride;
2325        p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel      = DEFAULT_PORT_rxFifoPriElevationLevel;
2326        p_FmPort->p_FmPortDriverParam->rxFifoThreshold              = DEFAULT_PORT_rxFifoThreshold;
2327        p_FmPort->p_FmPortDriverParam->bufMargins.endMargins        = DEFAULT_PORT_BufMargins_endMargins;
2328        p_FmPort->p_FmPortDriverParam->errorsToDiscard              = DEFAULT_PORT_errorsToDiscard;
2329        p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore       = DEFAULT_PORT_cheksumLastBytesIgnore;
2330        p_FmPort->p_FmPortDriverParam->forwardReuseIntContext       = DEFAULT_PORT_forwardIntContextReuse;
2331        break;
2332
2333    case(e_FM_PORT_TYPE_TX):
2334        p_FmPort->txFifoDeqPipelineDepth                            = DEFAULT_PORT_txFifoDeqPipelineDepth_1G;
2335        p_FmPort->p_FmPortDriverParam->dontReleaseBuf               = FALSE;
2336    case(e_FM_PORT_TYPE_TX_10G):
2337        if(p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)
2338            p_FmPort->txFifoDeqPipelineDepth                        = DEFAULT_PORT_txFifoDeqPipelineDepth_10G;
2339        p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore       = DEFAULT_PORT_cheksumLastBytesIgnore;
2340        p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel           = DEFAULT_PORT_txFifoMinFillLevel;
2341        p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel           = DEFAULT_PORT_txFifoLowComfLevel;
2342    case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2343    case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
2344        p_FmPort->p_FmPortDriverParam->deqHighPriority              = DEFAULT_PORT_deqHighPriority;
2345        p_FmPort->p_FmPortDriverParam->deqType                      = DEFAULT_PORT_deqType;
2346#ifdef FM_QMI_DEQ_OPTIONS_SUPPORT
2347        p_FmPort->p_FmPortDriverParam->deqPrefetchOption            = DEFAULT_PORT_deqPrefetchOption;
2348#endif /* FM_QMI_DEQ_OPTIONS_SUPPORT */
2349        p_FmPort->p_FmPortDriverParam->deqByteCnt                   = DEFAULT_PORT_deqByteCnt;
2350
2351        if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
2352            p_FmPort->p_FmPortDriverParam->errorsToDiscard          = DEFAULT_PORT_errorsToDiscard;
2353        break;
2354
2355    default:
2356        XX_Free(p_FmPort->p_FmPortDriverParam);
2357        XX_Free(p_FmPort);
2358        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
2359        return NULL;
2360    }
2361#ifdef FM_QMI_DEQ_OPTIONS_SUPPORT
2362    if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
2363        p_FmPort->p_FmPortDriverParam->deqPrefetchOption            = DEFAULT_PORT_deqPrefetchOption_HC;
2364#endif /* FM_QMI_DEQ_OPTIONS_SUPPORT */
2365
2366    if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
2367        (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
2368        p_FmPort->txFifoDeqPipelineDepth                            = OH_PIPELINE_DEPTH;
2369
2370    p_FmPort->imEn = p_FmPortParams->independentModeEnable;
2371
2372    if (p_FmPort->imEn)
2373    {
2374        if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
2375            (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
2376            p_FmPort->txFifoDeqPipelineDepth = DEFAULT_PORT_txFifoDeqPipelineDepth_IM;
2377        FmPortConfigIM(p_FmPort, p_FmPortParams);
2378    }
2379    else
2380    {
2381        switch(p_FmPort->portType)
2382        {
2383        case(e_FM_PORT_TYPE_RX):
2384        case(e_FM_PORT_TYPE_RX_10G):
2385            /* Initialize FM port parameters for initialization phase only */
2386            memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools,
2387                   &p_FmPortParams->specificParams.rxParams.extBufPools,
2388                   sizeof(t_FmPortExtPools));
2389            p_FmPort->p_FmPortDriverParam->errFqid                      = p_FmPortParams->specificParams.rxParams.errFqid;
2390            p_FmPort->p_FmPortDriverParam->dfltFqid                     = p_FmPortParams->specificParams.rxParams.dfltFqid;
2391            p_FmPort->p_FmPortDriverParam->liodnOffset                  = p_FmPortParams->specificParams.rxParams.liodnOffset;
2392            break;
2393        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2394#ifdef FM_OP_PARTITION_ERRATA_FMANx8
2395        {
2396            t_FmRevisionInfo revInfo;
2397            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2398            if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
2399                p_FmPort->p_FmPortDriverParam->liodnOffset              = p_FmPortParams->specificParams.nonRxParams.opLiodnOffset;
2400        }
2401#endif /* FM_OP_PARTITION_ERRATA_FMANx8 */
2402        case(e_FM_PORT_TYPE_TX):
2403        case(e_FM_PORT_TYPE_TX_10G):
2404        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
2405            p_FmPort->p_FmPortDriverParam->errFqid                      = p_FmPortParams->specificParams.nonRxParams.errFqid;
2406            p_FmPort->p_FmPortDriverParam->deqSubPortal                 =
2407                (uint8_t)(p_FmPortParams->specificParams.nonRxParams.qmChannel & QMI_DEQ_CFG_SUBPORTAL_MASK);
2408            p_FmPort->p_FmPortDriverParam->dfltFqid                     = p_FmPortParams->specificParams.nonRxParams.dfltFqid;
2409            break;
2410        default:
2411            XX_Free(p_FmPort->p_FmPortDriverParam);
2412            XX_Free(p_FmPort);
2413            REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
2414            return NULL;
2415        }
2416    }
2417
2418    memset(p_FmPort->name, 0, (sizeof(char)) * MODULE_NAME_SIZE);
2419    if(Sprint (p_FmPort->name, "FM-%d-port-%s-%d",
2420               FmGetId(p_FmPort->h_Fm),
2421               ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING ||
2422                 (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ?
2423                "OH" : (p_FmPort->portType == e_FM_PORT_TYPE_RX ?
2424                        "1g-RX" : (p_FmPort->portType == e_FM_PORT_TYPE_TX ?
2425                                   "1g-TX" : (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G ?
2426                                              "10g-RX" : "10g-TX")))),
2427               p_FmPort->portId) == 0)
2428    {
2429        XX_Free(p_FmPort->p_FmPortDriverParam);
2430        XX_Free(p_FmPort);
2431        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
2432        return NULL;
2433    }
2434
2435    p_FmPort->h_Spinlock = XX_InitSpinlock();
2436    if (!p_FmPort->h_Spinlock)
2437    {
2438        XX_Free(p_FmPort->p_FmPortDriverParam);
2439        XX_Free(p_FmPort);
2440        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
2441        return NULL;
2442    }
2443
2444    return p_FmPort;
2445}
2446
2447/**************************************************************************//**
2448 @Function      FM_PORT_Init
2449
2450 @Description   Initializes the FM module
2451
2452 @Param[in]     h_FmPort - FM module descriptor
2453
2454 @Return        E_OK on success; Error code otherwise.
2455*//***************************************************************************/
2456t_Error FM_PORT_Init(t_Handle h_FmPort)
2457{
2458    t_FmPort                        *p_FmPort = (t_FmPort*)h_FmPort;
2459    t_FmPortDriverParam             *p_Params;
2460    t_Error                         err = E_OK;
2461    t_FmInterModulePortInitParams   fmParams;
2462    uint32_t                        minFifoSizeRequired = 0;
2463
2464    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
2465    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2466
2467    if ((err = BuildBufferStructure(p_FmPort)) != E_OK)
2468        RETURN_ERROR(MINOR, err, NO_MSG);
2469
2470    CHECK_INIT_PARAMETERS(p_FmPort, CheckInitParameters);
2471
2472    p_Params = p_FmPort->p_FmPortDriverParam;
2473
2474    /* set memory map pointers */
2475    p_FmPort->p_FmPortQmiRegs     = (t_FmPortQmiRegs *)UINT_TO_PTR(p_Params->baseAddr + QMI_PORT_REGS_OFFSET);
2476    p_FmPort->p_FmPortBmiRegs     = (u_FmPortBmiRegs *)UINT_TO_PTR(p_Params->baseAddr + BMI_PORT_REGS_OFFSET);
2477    p_FmPort->p_FmPortPrsRegs     = (t_FmPortPrsRegs *)UINT_TO_PTR(p_Params->baseAddr + PRS_PORT_REGS_OFFSET);
2478
2479    /* For O/H ports, check fifo size and update if necessary */
2480    if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
2481    {
2482        minFifoSizeRequired = (uint32_t)((p_FmPort->txFifoDeqPipelineDepth+4)*BMI_FIFO_UNITS);
2483        if (p_FmPort->fifoBufs.num < minFifoSizeRequired)
2484        {
2485            p_FmPort->fifoBufs.num = minFifoSizeRequired;
2486            DBG(WARNING, ("FIFO size enlarged to %d due to txFifoDeqPipelineDepth size", minFifoSizeRequired));
2487        }
2488    }
2489
2490    /* For Rx Ports, call the external Buffer routine which also checks fifo
2491       size and updates it if necessary */
2492    if(((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
2493        && !p_FmPort->imEn)
2494    {
2495        /* define external buffer pools and pool depletion*/
2496        err = SetExtBufferPools(p_FmPort);
2497        if(err)
2498            RETURN_ERROR(MAJOR, err, NO_MSG);
2499    }
2500
2501    /************************************************************/
2502    /* Call FM module routine for communicating parameters      */
2503    /************************************************************/
2504    memset(&fmParams, 0, sizeof(fmParams));
2505    fmParams.hardwarePortId     = p_FmPort->hardwarePortId;
2506    fmParams.portType           = (e_FmPortType)p_FmPort->portType;
2507    fmParams.numOfTasks         = (uint8_t)p_FmPort->tasks.num;
2508    fmParams.numOfExtraTasks    = (uint8_t)p_FmPort->tasks.extra;
2509    fmParams.numOfOpenDmas      = (uint8_t)p_FmPort->openDmas.num;
2510    fmParams.numOfExtraOpenDmas = (uint8_t)p_FmPort->openDmas.extra;
2511    fmParams.sizeOfFifo         = p_FmPort->fifoBufs.num;
2512    fmParams.extraSizeOfFifo    = p_FmPort->fifoBufs.extra;
2513    fmParams.independentMode    = p_FmPort->imEn;
2514    fmParams.liodnOffset        = p_Params->liodnOffset;
2515    fmParams.liodnBase          = p_Params->liodnBase;
2516
2517    switch(p_FmPort->portType)
2518    {
2519        case(e_FM_PORT_TYPE_RX_10G):
2520        case(e_FM_PORT_TYPE_RX):
2521            break;
2522        case(e_FM_PORT_TYPE_TX_10G):
2523        case(e_FM_PORT_TYPE_TX):
2524        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2525        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
2526            fmParams.deqPipelineDepth = p_FmPort->txFifoDeqPipelineDepth;
2527            break;
2528        default:
2529            RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
2530    }
2531
2532    err = FmGetSetPortParams(p_FmPort->h_Fm, &fmParams);
2533    if(err)
2534        RETURN_ERROR(MAJOR, err, NO_MSG);
2535
2536    p_FmPort->tasks.num        = fmParams.numOfTasks;
2537    p_FmPort->tasks.extra      = fmParams.numOfExtraTasks;
2538    p_FmPort->openDmas.num     = fmParams.numOfOpenDmas;
2539    p_FmPort->openDmas.extra   = fmParams.numOfExtraOpenDmas;
2540    p_FmPort->fifoBufs.num     = fmParams.sizeOfFifo;
2541    p_FmPort->fifoBufs.extra   = fmParams.extraSizeOfFifo;
2542
2543    /* get params for use in init */
2544    p_Params->fmMuramPhysBaseAddr =
2545        (uint64_t)((uint64_t)(fmParams.fmMuramPhysBaseAddr.low) |
2546                   ((uint64_t)(fmParams.fmMuramPhysBaseAddr.high) << 32));
2547
2548    /**********************/
2549    /* Init BMI Registers */
2550    /**********************/
2551    switch(p_FmPort->portType)
2552    {
2553        case(e_FM_PORT_TYPE_RX_10G):
2554        case(e_FM_PORT_TYPE_RX):
2555            err = BmiRxPortInit(p_FmPort);
2556            if(err)
2557                RETURN_ERROR(MAJOR, err, NO_MSG);
2558            break;
2559        case(e_FM_PORT_TYPE_TX_10G):
2560        case(e_FM_PORT_TYPE_TX):
2561            err = BmiTxPortInit(p_FmPort);
2562            if(err)
2563                RETURN_ERROR(MAJOR, err, NO_MSG);
2564            break;
2565        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
2566        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
2567            err = BmiOhPortInit(p_FmPort);
2568            if(err)
2569                RETURN_ERROR(MAJOR, err, NO_MSG);
2570            break;
2571        default:
2572            RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
2573    }
2574
2575    /**********************/
2576    /* Init QMI Registers */
2577    /**********************/
2578    if (!p_FmPort->imEn && ((err = QmiInit(p_FmPort)) != E_OK))
2579        RETURN_ERROR(MAJOR, err, NO_MSG);
2580
2581    if (p_FmPort->imEn && ((err = FmPortImInit(p_FmPort)) != E_OK))
2582        RETURN_ERROR(MAJOR, err, NO_MSG);
2583
2584    FmPortDriverParamFree(p_FmPort);
2585
2586    return E_OK;
2587}
2588
2589/**************************************************************************//**
2590 @Function      FM_PORT_Free
2591
2592 @Description   Frees all resources that were assigned to FM module.
2593
2594                Calling this routine invalidates the descriptor.
2595
2596 @Param[in]     h_FmPort - FM module descriptor
2597
2598 @Return        E_OK on success; Error code otherwise.
2599*//***************************************************************************/
2600t_Error FM_PORT_Free(t_Handle h_FmPort)
2601{
2602    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
2603    t_FmInterModulePortFreeParams       fmParams;
2604
2605    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2606
2607    if(p_FmPort->pcdEngines)
2608        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Trying to free a port with PCD. FM_PORT_DeletePCD must be called first."));
2609
2610    if (p_FmPort->enabled)
2611    {
2612        if (FM_PORT_Disable(p_FmPort) != E_OK)
2613            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM_PORT_Disable FAILED"));
2614    }
2615
2616    FmPortDriverParamFree(p_FmPort);
2617
2618    if (p_FmPort->imEn)
2619        FmPortImFree(p_FmPort);
2620
2621    fmParams.hardwarePortId = p_FmPort->hardwarePortId;
2622    fmParams.portType = (e_FmPortType)p_FmPort->portType;
2623#ifdef FM_QMI_DEQ_OPTIONS_SUPPORT
2624    fmParams.deqPipelineDepth = p_FmPort->txFifoDeqPipelineDepth;
2625#endif /* FM_QMI_DEQ_OPTIONS_SUPPORT */
2626
2627    FmFreePortParams(p_FmPort->h_Fm, &fmParams);
2628
2629    if (p_FmPort->h_Spinlock)
2630        XX_FreeSpinlock(p_FmPort->h_Spinlock);
2631
2632    XX_Free(p_FmPort);
2633
2634    return E_OK;
2635}
2636
2637
2638/*************************************************/
2639/*       API Advanced Init unit functions        */
2640/*************************************************/
2641
2642t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri)
2643{
2644    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2645
2646    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2647    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2648    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
2649        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for Rx ports"));
2650
2651    p_FmPort->p_FmPortDriverParam->deqHighPriority = highPri;
2652
2653    return E_OK;
2654}
2655
2656t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType)
2657{
2658    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2659
2660    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2661    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2662    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
2663        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
2664
2665    p_FmPort->p_FmPortDriverParam->deqType = deqType;
2666
2667    return E_OK;
2668}
2669
2670#ifdef FM_QMI_DEQ_OPTIONS_SUPPORT
2671t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption)
2672{
2673    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2674
2675    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2676    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2677    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
2678        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
2679    p_FmPort->p_FmPortDriverParam->deqPrefetchOption = deqPrefetchOption;
2680    return E_OK;
2681}
2682#endif /* FM_QMI_DEQ_OPTIONS_SUPPORT */
2683
2684t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmPortBackupBmPools *p_BackupBmPools)
2685{
2686    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
2687#ifdef FM_NO_BACKUP_POOLS
2688    t_FmRevisionInfo    revInfo;
2689#endif /* FM_NO_BACKUP_POOLS */
2690
2691    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2692    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2693    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2694        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
2695
2696#ifdef FM_NO_BACKUP_POOLS
2697    FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2698    if (revInfo.majorRev != 4)
2699        RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigBackupPools"));
2700#endif /* FM_NO_BACKUP_POOLS */
2701
2702    p_FmPort->p_FmPortDriverParam->p_BackupBmPools = (t_FmPortBackupBmPools *)XX_Malloc(sizeof(t_FmPortBackupBmPools));
2703    if(!p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
2704        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed"));
2705    memcpy(p_FmPort->p_FmPortDriverParam->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmPortBackupBmPools));
2706
2707    return E_OK;
2708}
2709
2710t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt)
2711{
2712    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2713
2714    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2715    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2716    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
2717        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
2718
2719    p_FmPort->p_FmPortDriverParam->deqByteCnt = deqByteCnt;
2720
2721    return E_OK;
2722}
2723
2724t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, t_FmPortBufferPrefixContent *p_FmPortBufferPrefixContent)
2725{
2726    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2727
2728    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2729    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2730
2731    memcpy(&p_FmPort->p_FmPortDriverParam->bufferPrefixContent, p_FmPortBufferPrefixContent, sizeof(t_FmPortBufferPrefixContent));
2732    /* if dataAlign was not initialized by user, we return to driver's deafult */
2733    if (!p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign)
2734        p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign;
2735
2736    return E_OK;
2737}
2738
2739t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore)
2740{
2741    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2742
2743    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2744    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2745    if((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
2746        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx & Tx ports only"));
2747
2748    p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = cheksumLastBytesIgnore;
2749
2750    return E_OK;
2751}
2752
2753t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd)
2754{
2755    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2756
2757    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2758    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2759    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2760        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
2761
2762    p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = cutBytesFromEnd;
2763
2764    return E_OK;
2765}
2766
2767t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmPortBufPoolDepletion *p_BufPoolDepletion)
2768{
2769    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2770
2771    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2772    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2773    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2774        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
2775
2776    p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
2777    memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmPortBufPoolDepletion));
2778
2779    return E_OK;
2780}
2781
2782t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion)
2783{
2784    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2785
2786    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2787    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2788    if(p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
2789        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
2790
2791    p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
2792    memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, &p_FmPortObservedBufPoolDepletion->poolDepletionParams, sizeof(t_FmPortBufPoolDepletion));
2793    memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, &p_FmPortObservedBufPoolDepletion->poolsParams, sizeof(t_FmPortExtPools));
2794
2795    return E_OK;
2796}
2797
2798t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmPortExtPools *p_FmPortExtPools)
2799{
2800    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2801
2802    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2803    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2804    if(p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
2805        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
2806
2807    memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, p_FmPortExtPools, sizeof(t_FmPortExtPools));
2808
2809    return E_OK;
2810}
2811
2812t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold)
2813{
2814    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2815
2816    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2817    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2818    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2819        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
2820
2821    p_FmPort->p_FmPortDriverParam->rxFifoThreshold = fifoThreshold;
2822
2823    return E_OK;
2824}
2825
2826t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel)
2827{
2828    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2829
2830    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2831    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2832    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
2833        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
2834
2835    p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = priElevationLevel;
2836
2837    return E_OK;
2838}
2839
2840t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel)
2841{
2842    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2843
2844    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2845    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2846    if((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
2847        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
2848
2849    p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = minFillLevel;
2850
2851    return E_OK;
2852}
2853
2854t_Error FM_PORT_ConfigTxFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth)
2855{
2856    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2857
2858    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2859    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2860    if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) &&
2861        (p_FmPort->portType != e_FM_PORT_TYPE_TX))
2862        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
2863    if (p_FmPort->imEn)
2864        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for IM ports!"));
2865
2866    p_FmPort->txFifoDeqPipelineDepth = deqPipelineDepth;
2867
2868    return E_OK;
2869}
2870
2871t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel)
2872{
2873    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2874
2875    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2876    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2877    if((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
2878        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
2879
2880    p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = fifoLowComfLevel;
2881
2882    return E_OK;
2883}
2884
2885t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort)
2886{
2887    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2888
2889    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2890    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2891    if((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
2892        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
2893
2894    p_FmPort->p_FmPortDriverParam->dontReleaseBuf = TRUE;
2895
2896    return E_OK;
2897}
2898
2899t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color)
2900{
2901    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2902
2903    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2904    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2905#ifdef FM_OP_PORT_QMAN_REJECT_ERRATA_FMAN21
2906    {
2907        t_FmRevisionInfo revInfo;
2908        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2909        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
2910            RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigDfltColor!"));
2911    }
2912#endif /* FM_OP_PORT_QMAN_REJECT_ERRATA_FMAN21 */
2913    p_FmPort->p_FmPortDriverParam->color = color;
2914
2915    return E_OK;
2916}
2917
2918t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq)
2919{
2920    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2921
2922    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2923    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2924#ifdef FM_PORT_SYNC_ERRATA_FMAN6
2925    {
2926        t_FmRevisionInfo revInfo;
2927        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
2928        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
2929            RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("port-sync!"));
2930    }
2931#endif /* FM_PORT_SYNC_ERRATA_FMAN6 */
2932
2933    p_FmPort->p_FmPortDriverParam->syncReq = syncReq;
2934
2935    return E_OK;
2936}
2937
2938
2939t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override)
2940{
2941    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2942
2943    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2944    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2945    if((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX))
2946        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Tx ports"));
2947
2948    p_FmPort->p_FmPortDriverParam->frmDiscardOverride = override;
2949
2950    return E_OK;
2951}
2952
2953t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs)
2954{
2955    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2956
2957    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2958    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2959    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
2960                                                            (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
2961        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
2962
2963    p_FmPort->p_FmPortDriverParam->errorsToDiscard = errs;
2964
2965    return E_OK;
2966}
2967
2968t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmPortDmaSwap swapData)
2969{
2970    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2971
2972    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2973    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2974
2975    p_FmPort->p_FmPortDriverParam->dmaSwapData = swapData;
2976
2977    return E_OK;
2978}
2979
2980t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmPortDmaCache intContextCacheAttr)
2981{
2982    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2983
2984    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2985    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2986
2987    p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = intContextCacheAttr;
2988
2989    return E_OK;
2990}
2991
2992t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmPortDmaCache headerCacheAttr)
2993{
2994    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
2995
2996    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
2997    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
2998
2999    p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = headerCacheAttr;
3000
3001    return E_OK;
3002}
3003
3004t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmPortDmaCache scatterGatherCacheAttr)
3005{
3006    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
3007
3008    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3009    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3010
3011    p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = scatterGatherCacheAttr;
3012
3013    return E_OK;
3014}
3015
3016t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize)
3017{
3018    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
3019
3020    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3021    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3022
3023    if((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_TX))
3024        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports"));
3025
3026    p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = optimize;
3027
3028    return E_OK;
3029}
3030
3031t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool forwardReuse)
3032{
3033    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
3034
3035    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3036    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3037
3038    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
3039        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
3040
3041    p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = forwardReuse;
3042
3043    return E_OK;
3044}
3045
3046
3047/****************************************************/
3048/*       PCD Advaced config API                     */
3049/****************************************************/
3050
3051/****************************************************/
3052/*       API Run-time Control unit functions        */
3053/****************************************************/
3054
3055t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas)
3056{
3057    t_FmPort    *p_FmPort = (t_FmPort*)h_FmPort;
3058    t_Error     err;
3059
3060    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3061    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3062
3063#ifdef FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16
3064    {
3065        t_FmRevisionInfo revInfo;
3066        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
3067        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0) &&
3068            (p_NumOfOpenDmas->extra))
3069            RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("excessive resources"));
3070    }
3071#endif /* FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16 */
3072
3073    if((!p_NumOfOpenDmas->num) || (p_NumOfOpenDmas->num > MAX_NUM_OF_DMAS))
3074         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-num can't be larger than %d", MAX_NUM_OF_DMAS));
3075    if(p_NumOfOpenDmas->extra > MAX_NUM_OF_EXTRA_DMAS)
3076         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
3077    err = FmSetNumOfOpenDmas(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t)p_NumOfOpenDmas->num, (uint8_t)p_NumOfOpenDmas->extra, FALSE);
3078    if(err)
3079        RETURN_ERROR(MINOR, err, NO_MSG);
3080
3081    memcpy(&p_FmPort->openDmas, p_NumOfOpenDmas, sizeof(t_FmPortRsrc));
3082
3083    return E_OK;
3084}
3085
3086t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks)
3087{
3088    t_FmPort    *p_FmPort = (t_FmPort*)h_FmPort;
3089    t_Error     err;
3090
3091    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3092    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3093
3094    if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
3095        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for host command port where number is always 1"));
3096
3097#ifdef FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16
3098    {
3099        t_FmRevisionInfo revInfo;
3100        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
3101        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0) &&
3102            (p_NumOfTasks->extra))
3103            RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("excessive resources"));
3104    }
3105#endif /* FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16 */
3106
3107    if((!p_NumOfTasks->num) || (p_NumOfTasks->num > MAX_NUM_OF_TASKS))
3108         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-num can't be larger than %d", MAX_NUM_OF_TASKS));
3109    if(p_NumOfTasks->extra > MAX_NUM_OF_EXTRA_TASKS)
3110         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
3111
3112    err = FmSetNumOfTasks(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t)p_NumOfTasks->num, (uint8_t)p_NumOfTasks->extra, FALSE);
3113    if(err)
3114        RETURN_ERROR(MINOR, err, NO_MSG);
3115
3116    /* update driver's struct */
3117    memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc));
3118    return E_OK;
3119}
3120
3121t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo)
3122{
3123    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
3124    t_Error                             err;
3125    t_FmInterModulePortRxPoolsParams    rxPoolsParams;
3126    uint32_t                            minFifoSizeRequired;
3127
3128    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3129    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3130
3131#ifdef FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16
3132    {
3133        t_FmRevisionInfo revInfo;
3134        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
3135        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0) &&
3136            (p_SizeOfFifo->extra))
3137            RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("excessive resources"));
3138    }
3139#endif /* FM_PORT_EXCESSIVE_BUDGET_ERRATA_FMANx16 */
3140    if(!p_SizeOfFifo->num || (p_SizeOfFifo->num > BMI_MAX_FIFO_SIZE))
3141         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be in the range of 256 - %d", BMI_MAX_FIFO_SIZE));
3142    if(p_SizeOfFifo->num % BMI_FIFO_UNITS)
3143         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be divisible by %d", BMI_FIFO_UNITS));
3144    if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
3145    {
3146        /* extra FIFO size (allowed only to Rx ports) */
3147         if(p_SizeOfFifo->extra % BMI_FIFO_UNITS)
3148              RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-extra has to be divisible by %d", BMI_FIFO_UNITS));
3149    }
3150    else
3151        if(p_SizeOfFifo->extra)
3152            RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No SizeOfFifo-extra for non Rx ports"));
3153
3154    /* For O/H ports, check fifo size and update if necessary */
3155    if((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
3156    {
3157        minFifoSizeRequired = (uint32_t)((p_FmPort->txFifoDeqPipelineDepth+4)*BMI_FIFO_UNITS);
3158        if (p_FmPort->fifoBufs.num < minFifoSizeRequired)
3159        {
3160            p_FmPort->fifoBufs.num = minFifoSizeRequired;
3161            DBG(INFO, ("FIFO size enlarged to %d", minFifoSizeRequired));
3162        }
3163    }
3164    memcpy(&rxPoolsParams, &p_FmPort->rxPoolsParams, sizeof(rxPoolsParams));
3165    err = FmSetSizeOfFifo(p_FmPort->h_Fm,
3166                            p_FmPort->hardwarePortId,
3167                            p_FmPort->portType,
3168                            p_FmPort->imEn,
3169                            &p_SizeOfFifo->num,
3170                            p_SizeOfFifo->extra,
3171                            p_FmPort->txFifoDeqPipelineDepth,
3172                            &rxPoolsParams,
3173                            FALSE);
3174    if(err)
3175        RETURN_ERROR(MINOR, err, NO_MSG);
3176
3177    /* update driver's structure AFTER the FM routine, as it may change by the FM. */
3178    memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc));
3179
3180    return E_OK;
3181}
3182
3183uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort)
3184{
3185    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3186
3187    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
3188    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
3189
3190    return p_FmPort->bufferOffsets.dataOffset;
3191}
3192
3193uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data)
3194{
3195    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3196
3197    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
3198    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
3199
3200    if(p_FmPort->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE)
3201        return NULL;
3202
3203    return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.pcdInfoOffset);
3204}
3205
3206#ifdef DEBUG
3207uint8_t * FM_PORT_GetBufferDebugInfo(t_Handle h_FmPort, char *p_Data)
3208{
3209    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3210
3211    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
3212    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
3213
3214    if(p_FmPort->bufferOffsets.debugOffset == ILLEGAL_BASE)
3215        return NULL;
3216
3217    return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.debugOffset);
3218}
3219#endif /* DEBUG */
3220
3221t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data)
3222{
3223    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3224
3225    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
3226    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
3227
3228    if(p_FmPort->bufferOffsets.prsResultOffset == ILLEGAL_BASE)
3229        return NULL;
3230
3231    return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.prsResultOffset);
3232}
3233
3234uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data)
3235{
3236    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3237
3238    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
3239    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
3240
3241    if(p_FmPort->bufferOffsets.timeStampOffset == ILLEGAL_BASE)
3242        return NULL;
3243
3244    return (uint64_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.timeStampOffset);
3245}
3246
3247uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data)
3248{
3249    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3250
3251    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
3252    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
3253
3254    if(p_FmPort->bufferOffsets.hashResultOffset == ILLEGAL_BASE)
3255        return NULL;
3256
3257    return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.hashResultOffset);
3258}
3259
3260t_Error FM_PORT_Disable(t_Handle h_FmPort)
3261{
3262    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3263    volatile uint32_t           *p_BmiCfgReg = NULL;
3264    volatile uint32_t           *p_BmiStatusReg = NULL;
3265    bool                        rxPort = FALSE;
3266    int                         tries;
3267
3268    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3269    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3270
3271    switch(p_FmPort->portType)
3272    {
3273        case(e_FM_PORT_TYPE_RX_10G):
3274        case(e_FM_PORT_TYPE_RX):
3275            p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
3276            p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rst;
3277            rxPort = TRUE;
3278            break;
3279        case(e_FM_PORT_TYPE_TX_10G):
3280        case(e_FM_PORT_TYPE_TX):
3281             p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg;
3282             p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tst;
3283            break;
3284        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3285        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3286            p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg;
3287            p_BmiStatusReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ost;
3288            break;
3289        default:
3290            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3291    }
3292    /* check if port is already disabled */
3293    if(!(GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN))
3294    {
3295        if (!rxPort && !p_FmPort->imEn)
3296        {
3297            if(!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN))
3298                /* port is disabled */
3299                return E_OK;
3300            else
3301                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Inconsistency: Port's QMI is enabled but BMI disabled"));
3302        }
3303        /* port is disabled */
3304        return E_OK;
3305    }
3306
3307    /* Disable QMI */
3308    if (!rxPort && !p_FmPort->imEn)
3309    {
3310        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
3311                     GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & ~QMI_PORT_CFG_EN);
3312        /* wait for QMI to finish Handling dequeue tnums */
3313        tries=1000;
3314        while ((GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pns) & QMI_PORT_STATUS_DEQ_FD_BSY) &&
3315                --tries)
3316            XX_UDelay(1);
3317        if (!tries)
3318            RETURN_ERROR(MINOR, E_BUSY, ("%s: can't disable!", p_FmPort->name));
3319    }
3320
3321    /* Disable BMI */
3322    WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) & ~BMI_PORT_CFG_EN);
3323
3324    if (p_FmPort->imEn)
3325        FmPortImDisable(p_FmPort);
3326
3327    tries=5000;
3328    while ((GET_UINT32(*p_BmiStatusReg) & BMI_PORT_STATUS_BSY) &&
3329            --tries)
3330        XX_UDelay(1);
3331
3332    if (!tries)
3333        RETURN_ERROR(MINOR, E_BUSY, ("%s: can't disable!", p_FmPort->name));
3334
3335    p_FmPort->enabled = 0;
3336
3337    return E_OK;
3338}
3339
3340t_Error FM_PORT_Enable(t_Handle h_FmPort)
3341{
3342    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
3343    volatile uint32_t           *p_BmiCfgReg = NULL;
3344    bool                        rxPort = FALSE;
3345
3346    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3347    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3348
3349    switch(p_FmPort->portType)
3350    {
3351        case(e_FM_PORT_TYPE_RX_10G):
3352        case(e_FM_PORT_TYPE_RX):
3353            p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg;
3354            rxPort = TRUE;
3355            break;
3356        case(e_FM_PORT_TYPE_TX_10G):
3357        case(e_FM_PORT_TYPE_TX):
3358             p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg;
3359            break;
3360        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3361        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3362            p_BmiCfgReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocfg;
3363            break;
3364        default:
3365            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3366    }
3367
3368    /* check if port is already enabled */
3369    if(GET_UINT32(*p_BmiCfgReg) & BMI_PORT_CFG_EN)
3370    {
3371        if (!rxPort && !p_FmPort->imEn)
3372        {
3373            if(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc)& QMI_PORT_CFG_EN)
3374                /* port is enabled */
3375                return E_OK;
3376            else
3377                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Inconsistency: Port's BMI is enabled but QMI disabled"));
3378        }
3379        /* port is enabled */
3380        return E_OK;
3381    }
3382
3383    if (p_FmPort->imEn)
3384        FmPortImEnable(p_FmPort);
3385
3386    /* Enable QMI */
3387    if (!rxPort && !p_FmPort->imEn)
3388        WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc,
3389                     GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) | QMI_PORT_CFG_EN);
3390
3391    /* Enable BMI */
3392    WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | BMI_PORT_CFG_EN);
3393
3394    p_FmPort->enabled = 1;
3395
3396    return E_OK;
3397}
3398
3399t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit)
3400{
3401    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
3402    uint32_t            tmpRateLimit, tmpRateLimitScale;
3403    volatile uint32_t   *p_RateLimitReg, *p_RateLimitScaleReg;
3404    uint8_t             factor, countUnitBit;
3405    uint16_t            baseGran;
3406
3407    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3408    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3409
3410    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
3411                                                (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
3412        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only"));
3413
3414    switch(p_FmPort->portType)
3415    {
3416        case(e_FM_PORT_TYPE_TX_10G):
3417        case(e_FM_PORT_TYPE_TX):
3418            p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt;
3419            p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts;
3420            baseGran = 16000;
3421            break;
3422        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3423            p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt;
3424            p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts;
3425            baseGran = 10000;
3426           break;
3427        default:
3428            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3429    }
3430
3431    countUnitBit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm);  /* TimeStamp per nano seconds units */
3432    /* normally, we use 1 usec as the reference count */
3433    factor = 1;
3434    /* if ratelimit is too small for a 1usec factor, multiply the factor */
3435    while (p_RateLimit->rateLimit < baseGran/factor)
3436    {
3437        if (countUnitBit==31)
3438            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too small"));
3439
3440        countUnitBit++;
3441        factor <<= 1;
3442    }
3443    /* if ratelimit is too large for a 1usec factor, it is also larger than max rate*/
3444    if (p_RateLimit->rateLimit > ((uint32_t)baseGran * (1<<10) * (uint32_t)factor))
3445        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too large"));
3446
3447    tmpRateLimit = (uint32_t)(p_RateLimit->rateLimit*factor/baseGran - 1);
3448
3449    if(!p_RateLimit->maxBurstSize || (p_RateLimit->maxBurstSize > MAX_BURST_SIZE))
3450        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxBurstSize must be between 1K and %dk", MAX_BURST_SIZE));
3451
3452    tmpRateLimitScale = ((31 - (uint32_t)countUnitBit) << BMI_COUNT_RATE_UNIT_SHIFT) | BMI_RATE_LIMIT_EN;
3453
3454    if(p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
3455        tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT;
3456    else
3457    {
3458#ifndef FM_NO_ADVANCED_RATE_LIMITER
3459        t_FmRevisionInfo    revInfo;
3460
3461        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
3462        if (revInfo.majorRev == 4)
3463        {
3464            switch(p_RateLimit->rateLimitDivider)
3465            {
3466                case(e_FM_PORT_DUAL_RATE_LIMITER_NONE):
3467                    break;
3468                case(e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2):
3469                    tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_2;
3470                    break;
3471                case(e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4):
3472                    tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_4;
3473                    break;
3474                case(e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8):
3475                    tmpRateLimitScale |= BMI_RATE_LIMIT_SCALE_BY_8;
3476                    break;
3477                default:
3478                    break;
3479            }
3480            tmpRateLimit |= BMI_RATE_LIMIT_BURST_SIZE_GRAN;
3481        }
3482        else
3483#endif /* ! FM_NO_ADVANCED_RATE_LIMITER */
3484        {
3485            if(p_RateLimit->rateLimitDivider != e_FM_PORT_DUAL_RATE_LIMITER_NONE)
3486                    RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigDualRateLimitScaleDown"));
3487
3488            if(p_RateLimit->maxBurstSize % 1000)
3489            {
3490                p_RateLimit->maxBurstSize = (uint16_t)((p_RateLimit->maxBurstSize/1000)+1);
3491                DBG(WARNING, ("rateLimit.maxBurstSize rounded up to %d", (p_RateLimit->maxBurstSize/1000+1)*1000));
3492            }
3493            else
3494                p_RateLimit->maxBurstSize = (uint16_t)(p_RateLimit->maxBurstSize/1000);
3495        }
3496        tmpRateLimit |= (uint32_t)(p_RateLimit->maxBurstSize - 1) << BMI_MAX_BURST_SHIFT;
3497
3498    }
3499    WRITE_UINT32(*p_RateLimitScaleReg, tmpRateLimitScale);
3500    WRITE_UINT32(*p_RateLimitReg, tmpRateLimit);
3501
3502    return E_OK;
3503}
3504
3505t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort)
3506{
3507    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
3508    volatile uint32_t   *p_RateLimitReg, *p_RateLimitScaleReg;
3509
3510    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3511    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
3512
3513    if((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
3514                                                (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
3515        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only"));
3516
3517    switch(p_FmPort->portType)
3518    {
3519        case(e_FM_PORT_TYPE_TX_10G):
3520        case(e_FM_PORT_TYPE_TX):
3521            p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmt;
3522            p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_trlmts;
3523            break;
3524        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3525            p_RateLimitReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmt;
3526            p_RateLimitScaleReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_orlmts;
3527           break;
3528        default:
3529            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3530    }
3531
3532    WRITE_UINT32(*p_RateLimitScaleReg, 0);
3533    WRITE_UINT32(*p_RateLimitReg, 0);
3534
3535    return E_OK;
3536}
3537
3538
3539t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable)
3540{
3541    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3542    uint32_t                tmpReg;
3543
3544    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3545    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3546
3547    tmpReg = GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc);
3548    if(enable)
3549        tmpReg |= QMI_PORT_CFG_EN_COUNTERS ;
3550    else
3551        tmpReg &= ~QMI_PORT_CFG_EN_COUNTERS;
3552
3553    WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc, tmpReg);
3554
3555    return E_OK;
3556}
3557
3558t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable)
3559{
3560    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3561    volatile uint32_t       *p_BmiPcReg = NULL;
3562
3563    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3564    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3565
3566    switch(p_FmPort->portType)
3567    {
3568        case(e_FM_PORT_TYPE_RX_10G):
3569        case(e_FM_PORT_TYPE_RX):
3570            p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpc;
3571            break;
3572        case(e_FM_PORT_TYPE_TX_10G):
3573        case(e_FM_PORT_TYPE_TX):
3574            p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpc;
3575            break;
3576        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3577        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3578            p_BmiPcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opc;
3579            break;
3580        default:
3581            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3582    }
3583
3584    if(enable)
3585        WRITE_UINT32(*p_BmiPcReg, BMI_COUNTERS_EN);
3586    else
3587        WRITE_UINT32(*p_BmiPcReg, 0);
3588
3589    return E_OK;
3590}
3591
3592t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt)
3593{
3594    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3595    uint32_t                tmpReg;
3596    volatile uint32_t       *p_BmiPcpReg = NULL;
3597
3598    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3599
3600    switch(p_FmPort->portType)
3601    {
3602        case(e_FM_PORT_TYPE_RX_10G):
3603        case(e_FM_PORT_TYPE_RX):
3604            p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpcp;
3605            break;
3606        case(e_FM_PORT_TYPE_TX_10G):
3607        case(e_FM_PORT_TYPE_TX):
3608            p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpcp;
3609            break;
3610        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3611        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3612            p_BmiPcpReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opcp;
3613            break;
3614        default:
3615            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3616    }
3617
3618    /* check parameters */
3619    if (!p_FmPortPerformanceCnt->taskCompVal ||
3620        (p_FmPortPerformanceCnt->taskCompVal > p_FmPort->tasks.num))
3621        RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3622                     ("performanceCnt.taskCompVal has to be in the range of 1 - %d (current value)!",
3623                      p_FmPort->tasks.num));
3624    if (!p_FmPortPerformanceCnt->dmaCompVal ||
3625        (p_FmPortPerformanceCnt->dmaCompVal > p_FmPort->openDmas.num))
3626        RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3627                     ("performanceCnt.dmaCompVal has to be in the range of 1 - %d (current value)!",
3628                      p_FmPort->openDmas.num));
3629    if (!p_FmPortPerformanceCnt->fifoCompVal ||
3630        (p_FmPortPerformanceCnt->fifoCompVal > p_FmPort->fifoBufs.num))
3631        RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3632                     ("performanceCnt.fifoCompVal has to be in the range of 256 - %d (current value)!",
3633                      p_FmPort->fifoBufs.num));
3634    if (p_FmPortPerformanceCnt->fifoCompVal % BMI_FIFO_UNITS)
3635        RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3636                     ("performanceCnt.fifoCompVal has to be divisible by %d",
3637                      BMI_FIFO_UNITS));
3638    switch(p_FmPort->portType)
3639    {
3640        case(e_FM_PORT_TYPE_RX_10G):
3641        case(e_FM_PORT_TYPE_RX):
3642            if (!p_FmPortPerformanceCnt->queueCompVal ||
3643                (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_RX_QUEUE_COMP))
3644                RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3645                             ("performanceCnt.queueCompVal for Rx has to be in the range of 1 - %d",
3646                              MAX_PERFORMANCE_RX_QUEUE_COMP));
3647            break;
3648        case(e_FM_PORT_TYPE_TX_10G):
3649        case(e_FM_PORT_TYPE_TX):
3650            if (!p_FmPortPerformanceCnt->queueCompVal ||
3651                (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_TX_QUEUE_COMP))
3652                RETURN_ERROR(MAJOR, E_INVALID_VALUE,
3653                             ("performanceCnt.queueCompVal for Tx has to be in the range of 1 - %d",
3654                              MAX_PERFORMANCE_TX_QUEUE_COMP));
3655            break;
3656        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3657        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3658            if (p_FmPortPerformanceCnt->queueCompVal)
3659                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("performanceCnt.queueCompVal is not relevant for H/O ports."));
3660            break;
3661        default:
3662            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3663    }
3664
3665    tmpReg = 0;
3666    tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->queueCompVal - 1) << BMI_PERFORMANCE_PORT_COMP_SHIFT);
3667    tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->dmaCompVal- 1) << BMI_PERFORMANCE_DMA_COMP_SHIFT);
3668    tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->fifoCompVal/BMI_FIFO_UNITS - 1) << BMI_PERFORMANCE_FIFO_COMP_SHIFT);
3669    if ((p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && (p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND))
3670        tmpReg |= ((uint32_t)(p_FmPortPerformanceCnt->taskCompVal - 1) << BMI_PERFORMANCE_TASK_COMP_SHIFT);
3671
3672    WRITE_UINT32(*p_BmiPcpReg, tmpReg);
3673
3674    return E_OK;
3675}
3676
3677t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort)
3678{
3679    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3680    t_FmPortPerformanceCnt  currParams, savedParams;
3681    t_Error                 err;
3682    bool                    underTest, failed = FALSE;
3683
3684    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3685
3686    XX_Print("Analyzing Performance parameters for port (type %d, id%d)\n",
3687             p_FmPort->portType, p_FmPort->portId);
3688
3689    currParams.taskCompVal    = (uint8_t)p_FmPort->tasks.num;
3690    if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
3691        (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
3692        currParams.queueCompVal   = 0;
3693    else
3694        currParams.queueCompVal   = 1;
3695    currParams.dmaCompVal     =(uint8_t) p_FmPort->openDmas.num;
3696    currParams.fifoCompVal    = p_FmPort->fifoBufs.num;
3697
3698    FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
3699    ClearPerfCnts(p_FmPort);
3700    if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
3701        RETURN_ERROR(MAJOR, err, NO_MSG);
3702    FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
3703    XX_UDelay(1000000);
3704    FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
3705    if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
3706    {
3707        XX_Print ("Max num of defined port tasks (%d) utilized - Please enlarge\n",p_FmPort->tasks.num);
3708        failed = TRUE;
3709    }
3710    if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
3711    {
3712        XX_Print ("Max num of defined port openDmas (%d) utilized - Please enlarge\n",p_FmPort->openDmas.num);
3713        failed = TRUE;
3714    }
3715    if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
3716    {
3717        XX_Print ("Max size of defined port fifo (%d) utilized - Please enlarge\n",p_FmPort->fifoBufs.num*BMI_FIFO_UNITS);
3718        failed = TRUE;
3719    }
3720    if (failed)
3721        RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3722
3723    memset(&savedParams, 0, sizeof(savedParams));
3724    while (TRUE)
3725    {
3726        underTest = FALSE;
3727        if ((currParams.taskCompVal != 1) && !savedParams.taskCompVal)
3728        {
3729            currParams.taskCompVal--;
3730            underTest = TRUE;
3731        }
3732        if ((currParams.dmaCompVal != 1) && !savedParams.dmaCompVal)
3733        {
3734            currParams.dmaCompVal--;
3735            underTest = TRUE;
3736        }
3737        if ((currParams.fifoCompVal != BMI_FIFO_UNITS) && !savedParams.fifoCompVal)
3738        {
3739            currParams.fifoCompVal -= BMI_FIFO_UNITS;
3740            underTest = TRUE;
3741        }
3742        if (!underTest)
3743            break;
3744
3745        ClearPerfCnts(p_FmPort);
3746        if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
3747            RETURN_ERROR(MAJOR, err, NO_MSG);
3748        FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
3749        XX_UDelay(1000000);
3750        FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
3751
3752        if (!savedParams.taskCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
3753            savedParams.taskCompVal = (uint8_t)(currParams.taskCompVal+2);
3754        if (!savedParams.dmaCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
3755            savedParams.dmaCompVal = (uint8_t)(currParams.dmaCompVal+2);
3756        if (!savedParams.fifoCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
3757            savedParams.fifoCompVal = currParams.fifoCompVal+2;
3758    }
3759
3760    XX_Print("best vals: tasks %d, dmas %d, fifos %d\n",
3761             savedParams.taskCompVal, savedParams.dmaCompVal, savedParams.fifoCompVal);
3762    return E_OK;
3763}
3764
3765t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable)
3766{
3767    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3768    uint32_t                tmpReg;
3769    volatile uint32_t       *p_BmiStcReg = NULL;
3770
3771    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3772    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3773
3774    switch(p_FmPort->portType)
3775    {
3776        case(e_FM_PORT_TYPE_RX_10G):
3777        case(e_FM_PORT_TYPE_RX):
3778            p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rstc;
3779            break;
3780        case(e_FM_PORT_TYPE_TX_10G):
3781        case(e_FM_PORT_TYPE_TX):
3782            p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tstc;
3783            break;
3784        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3785        case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3786            p_BmiStcReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ostc;
3787            break;
3788        default:
3789            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
3790    }
3791
3792    tmpReg = GET_UINT32(*p_BmiStcReg);
3793
3794    if(enable)
3795        tmpReg |= BMI_COUNTERS_EN;
3796    else
3797        tmpReg &= ~BMI_COUNTERS_EN;
3798
3799    WRITE_UINT32(*p_BmiStcReg, tmpReg);
3800
3801    return E_OK;
3802}
3803
3804t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort,  fmPortFrameErrSelect_t errs)
3805{
3806    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3807    volatile uint32_t       *p_ErrQReg, *p_ErrDiscard;
3808
3809    switch(p_FmPort->portType)
3810    {
3811        case(e_FM_PORT_TYPE_RX_10G):
3812        case(e_FM_PORT_TYPE_RX):
3813            p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsem;
3814            p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm;
3815            break;
3816        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3817            p_ErrQReg = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsem;
3818            p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm;
3819            break;
3820        default:
3821           RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
3822    }
3823
3824    if (GET_UINT32(*p_ErrDiscard) & errs)
3825        RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Selectd Errors that were configured to cause frame discard."));
3826
3827    WRITE_UINT32(*p_ErrQReg, errs);
3828
3829    return E_OK;
3830}
3831
3832t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable)
3833{
3834    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
3835    uint32_t                tmpReg;
3836    int                     i;
3837
3838    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3839    SANITY_CHECK_RETURN_ERROR(poolId<BM_MAX_NUM_OF_POOLS, E_INVALID_HANDLE);
3840    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3841
3842    if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
3843        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
3844
3845    for(i=0 ; i< FM_PORT_MAX_NUM_OF_EXT_POOLS ; i++)
3846    {
3847        tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
3848        if ((uint8_t)((tmpReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT) == poolId)
3849        {
3850            if(enable)
3851                tmpReg |= BMI_EXT_BUF_POOL_EN_COUNTER;
3852            else
3853                tmpReg &= ~BMI_EXT_BUF_POOL_EN_COUNTER;
3854            WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], tmpReg);
3855            break;
3856        }
3857    }
3858    if (i == FM_PORT_MAX_NUM_OF_EXT_POOLS)
3859        RETURN_ERROR(MINOR, E_INVALID_VALUE,("poolId %d is not included in this ports pools", poolId));
3860
3861    return E_OK;
3862}
3863
3864uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters counter)
3865{
3866    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
3867    bool                bmiCounter = FALSE;
3868    volatile uint32_t   *p_Reg;
3869
3870    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
3871    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3872
3873    switch(counter)
3874    {
3875        case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
3876        case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
3877        case(e_FM_PORT_COUNTERS_DEQ_CONFIRM ):
3878            /* check that counter is available for the port type */
3879            if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
3880            {
3881                REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
3882                return 0;
3883            }
3884            bmiCounter = FALSE;
3885        case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
3886            bmiCounter = FALSE;
3887            break;
3888        default: /* BMI counters (or error - will be checked in BMI routine )*/
3889            bmiCounter = TRUE;
3890            break;
3891    }
3892
3893    if(bmiCounter)
3894    {
3895        switch(p_FmPort->portType)
3896        {
3897            case(e_FM_PORT_TYPE_RX_10G):
3898            case(e_FM_PORT_TYPE_RX):
3899                if(BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3900                {
3901                    REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3902                    return 0;
3903                }
3904                break;
3905            case(e_FM_PORT_TYPE_TX_10G):
3906            case(e_FM_PORT_TYPE_TX):
3907                if(BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3908                {
3909                    REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3910                    return 0;
3911                }
3912                break;
3913            case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3914            case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3915                if(BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3916                {
3917                    REPORT_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3918                    return 0;
3919                }
3920                break;
3921            default:
3922                REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type"));
3923                return 0;
3924        }
3925        return GET_UINT32(*p_Reg);
3926    }
3927    else /* QMI counter */
3928    {
3929
3930        /* check that counters are enabled */
3931        if(!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
3932        {
3933            REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
3934            return 0;
3935        }
3936
3937        /* Set counter */
3938        switch(counter)
3939        {
3940           case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
3941                return GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc);
3942            case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
3943                return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc);
3944            case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
3945                return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc);
3946            case(e_FM_PORT_COUNTERS_DEQ_CONFIRM):
3947                return GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc);
3948            default:
3949                REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
3950                return 0;
3951        }
3952    }
3953
3954    return 0;
3955}
3956
3957t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters counter, uint32_t value)
3958{
3959    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
3960    bool                bmiCounter = FALSE;
3961    volatile uint32_t   *p_Reg;
3962
3963    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
3964    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
3965
3966    switch(counter)
3967    {
3968        case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
3969        case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
3970        case(e_FM_PORT_COUNTERS_DEQ_CONFIRM ):
3971            /* check that counter is available for the port type */
3972            if((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
3973                        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
3974        case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
3975            bmiCounter = FALSE;
3976            break;
3977        default: /* BMI counters (or error - will be checked in BMI routine )*/
3978            bmiCounter = TRUE;
3979            break;
3980    }
3981
3982    if(bmiCounter)
3983    {
3984        switch(p_FmPort->portType)
3985        {
3986            case(e_FM_PORT_TYPE_RX_10G):
3987            case(e_FM_PORT_TYPE_RX):
3988               if(BmiRxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3989                    RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3990                break;
3991            case(e_FM_PORT_TYPE_TX_10G):
3992            case(e_FM_PORT_TYPE_TX):
3993               if(BmiTxPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3994                    RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
3995                break;
3996            case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
3997            case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
3998               if(BmiOhPortCheckAndGetCounterPtr(p_FmPort, counter, &p_Reg))
3999                    RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
4000                 break;
4001            default:
4002               RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type"));
4003        }
4004        WRITE_UINT32(*p_Reg, value);
4005    }
4006    else /* QMI counter */
4007    {
4008
4009        /* check that counters are enabled */
4010        if(!(GET_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
4011                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
4012
4013        /* Set counter */
4014        switch(counter)
4015        {
4016           case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
4017                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnetfc, value);
4018                break;
4019            case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
4020                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndtfc, value);
4021                break;
4022            case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
4023                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndfdc, value);
4024                break;
4025            case(e_FM_PORT_COUNTERS_DEQ_CONFIRM):
4026                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndcc, value);
4027                break;
4028            default:
4029                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
4030        }
4031    }
4032
4033    return E_OK;
4034}
4035
4036uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId)
4037{
4038    t_FmPort        *p_FmPort = (t_FmPort*)h_FmPort;
4039    uint32_t        extPoolReg;
4040    uint8_t         tmpPool;
4041    uint8_t         i;
4042
4043    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
4044    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4045
4046    if((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
4047    {
4048        REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
4049        return 0;
4050    }
4051
4052    for(i=0;i<FM_PORT_MAX_NUM_OF_EXT_POOLS;i++)
4053    {
4054        extPoolReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
4055        if (extPoolReg & BMI_EXT_BUF_POOL_VALID)
4056        {
4057            tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT);
4058            if(tmpPool == poolId)
4059            {
4060                if(extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER)
4061                    return  GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i]);
4062                else
4063                {
4064                    REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled"));
4065                    return 0;
4066                }
4067            }
4068        }
4069    }
4070    REPORT_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId));
4071    return 0;
4072}
4073
4074t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value)
4075{
4076    t_FmPort        *p_FmPort = (t_FmPort *)h_FmPort;
4077    uint32_t        extPoolReg;
4078    uint8_t         tmpPool;
4079    uint8_t         i;
4080
4081    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4082    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4083
4084    if((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
4085        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
4086
4087
4088    for(i=0;i<FM_PORT_MAX_NUM_OF_EXT_POOLS;i++)
4089    {
4090        extPoolReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i]);
4091        if (extPoolReg & BMI_EXT_BUF_POOL_VALID)
4092        {
4093            tmpPool = (uint8_t)((extPoolReg & BMI_EXT_BUF_POOL_ID_MASK) >> BMI_EXT_BUF_POOL_ID_SHIFT);
4094            if(tmpPool == poolId)
4095            {
4096                if(extPoolReg & BMI_EXT_BUF_POOL_EN_COUNTER)
4097                {
4098                    WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], value);
4099                    return E_OK;
4100                }
4101                else
4102                    RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not enabled"));
4103            }
4104        }
4105    }
4106    RETURN_ERROR(MINOR, E_INVALID_STATE, ("Pool %d is not used", poolId));
4107}
4108
4109bool FM_PORT_IsStalled(t_Handle h_FmPort)
4110{
4111    t_FmPort    *p_FmPort = (t_FmPort*)h_FmPort;
4112    t_Error     err;
4113    bool        isStalled;
4114
4115    SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, FALSE);
4116    SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, FALSE);
4117
4118    err = FmIsPortStalled(p_FmPort->h_Fm, p_FmPort->hardwarePortId, &isStalled);
4119    if(err != E_OK)
4120    {
4121        REPORT_ERROR(MINOR, err, NO_MSG);
4122        return TRUE;
4123    }
4124    return isStalled;
4125}
4126
4127t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort)
4128{
4129    t_FmPort        *p_FmPort = (t_FmPort*)h_FmPort;
4130
4131    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4132    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4133
4134    return FmResumeStalledPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
4135}
4136
4137t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum)
4138{
4139    t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
4140    uint32_t tmpReg;
4141
4142    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4143    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4144
4145    if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
4146        (p_FmPort->portType != e_FM_PORT_TYPE_RX))
4147        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
4148
4149    tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne);
4150    if (l4Checksum)
4151        tmpReg &= ~BMI_PORT_RFNE_FRWD_DCL4C;
4152    else
4153        tmpReg |= BMI_PORT_RFNE_FRWD_DCL4C;
4154    WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, tmpReg);
4155
4156    return E_OK;
4157}
4158
4159
4160/*       API Run-time PCD Control unit functions        */
4161
4162t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles)
4163{
4164    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
4165    t_Error                     err = E_OK;
4166
4167    p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
4168    ASSERT_COND(p_FmPort->h_FmPcd);
4169
4170    if(numOfProfiles)
4171    {
4172        err = FmPcdPlcrAllocProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, numOfProfiles);
4173        if(err)
4174            RETURN_ERROR(MAJOR, err,NO_MSG);
4175    }
4176    FmPcdPortRegister(p_FmPort->h_FmPcd, h_FmPort, p_FmPort->hardwarePortId);
4177
4178    return E_OK;
4179}
4180
4181t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort)
4182{
4183    t_FmPort                    *p_FmPort = (t_FmPort*)h_FmPort;
4184    t_Error                     err = E_OK;
4185
4186    err = FmPcdPlcrFreeProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId);
4187    if(err)
4188        RETURN_ERROR(MAJOR, err,NO_MSG);
4189    return E_OK;
4190}
4191
4192t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme)
4193{
4194    t_FmPort                *p_FmPort = (t_FmPort*)h_FmPort;
4195    volatile uint32_t       *p_BmiHpnia = NULL;
4196    uint32_t                tmpReg;
4197    uint8_t                 relativeSchemeId;
4198    uint8_t                 physicalSchemeId;
4199
4200    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4201    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4202    SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
4203
4204    tmpReg = (uint32_t)((p_FmPort->pcdEngines & FM_PCD_CC)? NIA_KG_CC_EN:0);
4205    switch(p_FmPort->portType)
4206    {
4207        case(e_FM_PORT_TYPE_RX_10G):
4208        case(e_FM_PORT_TYPE_RX):
4209            p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
4210            break;
4211        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4212            p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
4213            break;
4214        default:
4215            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
4216    }
4217
4218    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4219        return ERROR_CODE(E_BUSY);
4220    /* if we want to change to direct scheme, we need to check that this scheme is valid */
4221    if(p_FmPcdKgScheme->direct)
4222    {
4223        physicalSchemeId = (uint8_t)(PTR_TO_UINT(p_FmPcdKgScheme->h_DirectScheme)-1);
4224        /* check that this scheme is bound to this port */
4225        if(!(p_FmPort->schemesPerPortVector &  (uint32_t)(1 << (31 - (uint32_t)physicalSchemeId))))
4226        {
4227            RELEASE_LOCK(p_FmPort->lock);
4228            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with a scheme that is not bound to this port"));
4229        }
4230
4231        relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPort->h_FmPcd, physicalSchemeId);
4232        if(relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
4233        {
4234            RELEASE_LOCK(p_FmPort->lock);
4235            RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("called with invalid Scheme "));
4236        }
4237
4238        if(!FmPcdKgIsSchemeValidSw(p_FmPort->h_FmPcd, relativeSchemeId))
4239        {
4240            RELEASE_LOCK(p_FmPort->lock);
4241            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with uninitialized Scheme "));
4242        }
4243
4244        WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg | NIA_KG_DIRECT | (uint32_t)physicalSchemeId);
4245    }
4246    else /* change to indirect scheme */
4247        WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg);
4248    RELEASE_LOCK(p_FmPort->lock);
4249
4250    return E_OK;
4251}
4252
4253t_Error     FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile)
4254{
4255    t_FmPort                        *p_FmPort = (t_FmPort*)h_FmPort;
4256    volatile uint32_t               *p_BmiNia;
4257    volatile uint32_t               *p_BmiHpnia;
4258    uint32_t                        tmpReg;
4259    uint16_t                        absoluteProfileId = (uint16_t)(PTR_TO_UINT(h_Profile)-1);
4260
4261    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4262    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4263    SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PLCR , E_INVALID_STATE);
4264
4265    /* check relevancy of this routine  - only when policer is used
4266    directly after BMI or Parser */
4267    if((p_FmPort->pcdEngines & FM_PCD_KG) || (p_FmPort->pcdEngines & FM_PCD_CC))
4268        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"));
4269
4270    switch(p_FmPort->portType)
4271    {
4272        case(e_FM_PORT_TYPE_RX_10G):
4273        case(e_FM_PORT_TYPE_RX):
4274            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
4275            p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne;
4276            tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
4277            break;
4278        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4279            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
4280            p_BmiHpnia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofpne;
4281            tmpReg = 0;
4282            break;
4283        default:
4284           RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
4285    }
4286
4287    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4288        return ERROR_CODE(E_BUSY);
4289    if(!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
4290    {
4291        RELEASE_LOCK(p_FmPort->lock);
4292        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Invalid profile"));
4293    }
4294
4295    tmpReg = (uint32_t)(NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId);
4296
4297    if(p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
4298    {
4299        /* update BMI HPNIA */
4300        WRITE_UINT32(*p_BmiHpnia, tmpReg);
4301    }
4302    else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
4303    {
4304        /* rfne may contain FDCS bits, so first we read them. */
4305        tmpReg |= (GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK);
4306        /* update BMI NIA */
4307        WRITE_UINT32(*p_BmiNia, tmpReg);
4308    }
4309    RELEASE_LOCK(p_FmPort->lock);
4310
4311    return E_OK;
4312}
4313
4314
4315t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree)
4316{
4317    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
4318    t_Error                             err = E_OK;
4319    volatile uint32_t                   *p_BmiCcBase=NULL;
4320    volatile uint32_t                   *p_BmiNia=NULL;
4321    uint32_t                            ccTreePhysOffset;
4322
4323    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_VALUE);
4324
4325    if (p_FmPort->imEn)
4326        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
4327
4328    /* get PCD registers pointers */
4329    switch(p_FmPort->portType)
4330    {
4331        case(e_FM_PORT_TYPE_RX_10G):
4332        case(e_FM_PORT_TYPE_RX):
4333            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
4334            break;
4335        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4336            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
4337            break;
4338        default:
4339            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
4340    }
4341
4342    /* check that current NIA is BMI to BMI */
4343    if((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
4344            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
4345
4346/*TODO - to take care of changes due to previous tree. Maybe in the previous tree where chnged pndn, pnen ...
4347         it has to be returned to the default state - initially*/
4348
4349    p_FmPort->requiredAction = 0;
4350
4351    if(p_FmPort->pcdEngines & FM_PCD_CC)
4352    {
4353        switch(p_FmPort->portType)
4354        {
4355            case(e_FM_PORT_TYPE_RX_10G):
4356            case(e_FM_PORT_TYPE_RX):
4357                p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rccb;
4358                break;
4359            case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4360                p_BmiCcBase = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_occb;
4361                break;
4362            default:
4363                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
4364        }
4365
4366        if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4367            return ERROR_CODE(E_BUSY);
4368        err = FmPcdCcBindTree(p_FmPort->h_FmPcd, h_CcTree, &ccTreePhysOffset, h_FmPort);
4369        if(err)
4370        {
4371            RELEASE_LOCK(p_FmPort->lock);
4372            RETURN_ERROR(MINOR, err, NO_MSG);
4373        }
4374        WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
4375
4376        p_FmPort->ccTreeId = h_CcTree;
4377        RELEASE_LOCK(p_FmPort->lock);
4378    }
4379    else
4380        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Coarse CLassification not defined for this port."));
4381
4382    return E_OK;
4383}
4384
4385t_Error FM_PORT_AttachPCD(t_Handle h_FmPort)
4386{
4387
4388    t_FmPort        *p_FmPort = (t_FmPort*)h_FmPort;
4389    t_Error         err = E_OK;
4390
4391    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
4392    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4393
4394    if (p_FmPort->imEn)
4395        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
4396
4397    /* TODO - may add here checks for:
4398        SP (or in sw: schemes)
4399        CPP (or in sw clsPlan)
4400        Parser enabled and configured(?)
4401        Tree(?)
4402        Profile - only if direct.
4403        Scheme - only if direct
4404    */
4405
4406    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4407        return ERROR_CODE(E_BUSY);
4408    err = FmPortAttachPCD(h_FmPort);
4409    RELEASE_LOCK(p_FmPort->lock);
4410
4411    return err;
4412}
4413
4414t_Error FM_PORT_DetachPCD(t_Handle h_FmPort)
4415{
4416    t_FmPort                            *p_FmPort = (t_FmPort*)h_FmPort;
4417    volatile uint32_t                   *p_BmiNia=NULL;
4418
4419    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
4420    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4421
4422    if (p_FmPort->imEn)
4423        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
4424
4425    /* get PCD registers pointers */
4426    switch(p_FmPort->portType)
4427    {
4428        case(e_FM_PORT_TYPE_RX_10G):
4429        case(e_FM_PORT_TYPE_RX):
4430            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
4431            break;
4432        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4433            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
4434            break;
4435        default:
4436            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
4437    }
4438
4439    WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
4440
4441/*TODO - not atomic - it seems that port has to be disabled*/
4442    if(p_FmPort->requiredAction & UPDATE_NIA_PNEN)
4443    {
4444        switch(p_FmPort->portType)
4445        {
4446            case(e_FM_PORT_TYPE_TX_10G):
4447            case(e_FM_PORT_TYPE_TX):
4448                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
4449                break;
4450            case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
4451            case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4452            case(e_FM_PORT_TYPE_RX):
4453            case(e_FM_PORT_TYPE_RX_10G):
4454                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
4455                break;
4456           default:
4457                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage"));
4458        }
4459    }
4460
4461    if(p_FmPort->requiredAction & UPDATE_NIA_PNDN)
4462    {
4463        switch(p_FmPort->portType)
4464        {
4465            case(e_FM_PORT_TYPE_TX_10G):
4466            case(e_FM_PORT_TYPE_TX):
4467                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_TX);
4468                break;
4469            case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
4470            case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4471                WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, NIA_ENG_BMI | NIA_BMI_AC_FETCH);
4472                break;
4473            default:
4474                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Can not reach this stage"));
4475        }
4476    }
4477
4478
4479    if(p_FmPort->requiredAction  & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
4480        if(FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 2)!= E_OK)
4481            RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
4482    return E_OK;
4483}
4484
4485t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParams)
4486{
4487    t_FmPort                                *p_FmPort = (t_FmPort*)h_FmPort;
4488    t_FmPcdKgInterModuleBindPortToSchemes   schemeBind;
4489    t_Error                                 err = E_OK;
4490    uint8_t                                 i;
4491
4492    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
4493    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4494
4495    if (p_FmPort->imEn)
4496        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
4497
4498    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4499        return ERROR_CODE(E_BUSY);
4500    p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
4501    ASSERT_COND(p_FmPort->h_FmPcd);
4502
4503    err = SetPcd( h_FmPort, p_PcdParams);
4504    if(err)
4505    {
4506        RELEASE_LOCK(p_FmPort->lock);
4507        RETURN_ERROR(MAJOR, err, NO_MSG);
4508    }
4509
4510    if(p_FmPort->pcdEngines & FM_PCD_KG)
4511    {
4512        schemeBind.netEnvId = p_FmPort->netEnvId;
4513        schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
4514        schemeBind.numOfSchemes = p_PcdParams->p_KgParams->numOfSchemes;
4515        schemeBind.useClsPlan = p_FmPort->useClsPlan;
4516        for(i = 0;i<schemeBind.numOfSchemes;i++)
4517            schemeBind.schemesIds[i] = (uint8_t)(PTR_TO_UINT(p_PcdParams->p_KgParams->h_Schemes[i])-1);
4518
4519        err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
4520        if(err)
4521        {
4522            DeletePcd(p_FmPort);
4523            RELEASE_LOCK(p_FmPort->lock);
4524            RETURN_ERROR(MAJOR, err, NO_MSG);
4525        }
4526    }
4527
4528    if ((p_FmPort->pcdEngines & FM_PCD_PRS) && (p_PcdParams->p_PrsParams->includeInPrsStatistics))
4529        FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, TRUE);
4530
4531    FmPcdIncNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
4532
4533    err = FmPortAttachPCD(h_FmPort);
4534    RELEASE_LOCK(p_FmPort->lock);
4535
4536    return err;
4537}
4538
4539t_Error FM_PORT_DeletePCD(t_Handle h_FmPort)
4540{
4541    t_FmPort                                *p_FmPort = (t_FmPort*)h_FmPort;
4542    t_FmPcdKgInterModuleBindPortToSchemes   schemeBind;
4543    t_Error                                 err = E_OK;
4544
4545    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
4546    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4547
4548    if (p_FmPort->imEn)
4549        RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
4550
4551    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4552        return ERROR_CODE(E_BUSY);
4553
4554    err = FM_PORT_DetachPCD(h_FmPort);
4555    if(err)
4556    {
4557        RELEASE_LOCK(p_FmPort->lock);
4558        RETURN_ERROR(MAJOR, err, NO_MSG);
4559    }
4560
4561    FmPcdDecNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
4562
4563    /* we do it anyway, instead of checking if included */
4564    if (FmIsMaster(p_FmPort->h_Fm) &&
4565        (p_FmPort->pcdEngines & FM_PCD_PRS))
4566        FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, FALSE);
4567
4568    if(p_FmPort->pcdEngines & FM_PCD_KG)
4569    {
4570        /* unbind all schemes */
4571        p_FmPort->schemesPerPortVector = GetPortSchemeBindParams(p_FmPort, &schemeBind);
4572
4573        err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
4574        if(err)
4575        {
4576            RELEASE_LOCK(p_FmPort->lock);
4577            RETURN_ERROR(MAJOR, err, NO_MSG);
4578        }
4579    }
4580
4581    err = DeletePcd(h_FmPort);
4582    RELEASE_LOCK(p_FmPort->lock);
4583
4584    return err;
4585}
4586
4587t_Error  FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
4588{
4589    t_FmPort                                *p_FmPort = (t_FmPort*)h_FmPort;
4590    t_FmPcdKgInterModuleBindPortToSchemes   schemeBind;
4591    t_Error                                 err = E_OK;
4592    uint32_t                                tmpScmVec=0;
4593    int                                     i;
4594
4595    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4596    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4597    SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
4598
4599    schemeBind.netEnvId = p_FmPort->netEnvId;
4600    schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
4601    schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
4602    schemeBind.useClsPlan = p_FmPort->useClsPlan;
4603    for (i=0; i<schemeBind.numOfSchemes; i++)
4604    {
4605        schemeBind.schemesIds[i] = (uint8_t)(PTR_TO_UINT(p_PortScheme->h_Schemes[i])-1);
4606        /* build vector */
4607        tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
4608    }
4609
4610    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4611        return ERROR_CODE(E_BUSY);
4612    err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
4613    if (err == E_OK)
4614        p_FmPort->schemesPerPortVector |= tmpScmVec;
4615    RELEASE_LOCK(p_FmPort->lock);
4616
4617    return err;
4618}
4619
4620t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
4621{
4622    t_FmPort                                *p_FmPort = (t_FmPort*)h_FmPort;
4623    t_FmPcdKgInterModuleBindPortToSchemes   schemeBind;
4624    t_Error                                 err = E_OK;
4625    uint32_t                                tmpScmVec=0;
4626    int                                     i;
4627
4628    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4629    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4630    SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
4631
4632    schemeBind.netEnvId = p_FmPort->netEnvId;
4633    schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
4634    schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
4635    for (i=0; i<schemeBind.numOfSchemes; i++)
4636    {
4637        schemeBind.schemesIds[i] = (uint8_t)(PTR_TO_UINT(p_PortScheme->h_Schemes[i])-1);
4638        /* build vector */
4639        tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
4640    }
4641
4642    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4643        return ERROR_CODE(E_BUSY);
4644    err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
4645    if (err == E_OK)
4646        p_FmPort->schemesPerPortVector &= ~tmpScmVec;
4647    RELEASE_LOCK(p_FmPort->lock);
4648
4649    return err;
4650}
4651
4652t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart)
4653{
4654    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
4655    volatile uint32_t   *p_BmiPrsStartOffset = NULL;
4656    volatile uint32_t   *p_BmiNia = NULL;
4657    uint32_t            tmpReg;
4658    uint8_t             hdrNum;
4659
4660    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4661    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4662    SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PRS , E_INVALID_STATE);
4663
4664    switch(p_FmPort->portType)
4665    {
4666        case(e_FM_PORT_TYPE_RX_10G):
4667        case(e_FM_PORT_TYPE_RX):
4668            p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
4669            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
4670            tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
4671            break;
4672        case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4673            p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
4674            p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
4675            tmpReg = 0;
4676            break;
4677        default:
4678            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
4679    }
4680
4681    /* check that current NIA is BMI to BMI */
4682    if((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
4683            RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
4684
4685    if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
4686        return ERROR_CODE(E_BUSY);
4687    /* set the first header */
4688    GET_PRS_HDR_NUM(hdrNum, p_FmPcdPrsStart->firstPrsHdr);
4689    if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM))
4690    {
4691        RELEASE_LOCK(p_FmPort->lock);
4692        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
4693    }
4694    WRITE_UINT32(*p_BmiNia, (uint32_t)(NIA_ENG_PRS | (uint32_t)hdrNum | tmpReg));
4695
4696    /* set start parsing offset */
4697    WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)(p_FmPcdPrsStart->parsingOffset + p_FmPort->internalBufferOffset));
4698    RELEASE_LOCK(p_FmPort->lock);
4699
4700    return E_OK;
4701}
4702
4703#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
4704t_Error FM_PORT_DumpRegs(t_Handle h_FmPort)
4705{
4706    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
4707    t_Error             err = E_OK;
4708    char                arr[30];
4709    uint8_t             flag;
4710    int                 i=0;
4711
4712    DECLARE_DUMP;
4713
4714    SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
4715    SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
4716    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortQmiRegs, E_INVALID_HANDLE);
4717    SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortBmiRegs, E_INVALID_HANDLE);
4718
4719    switch (p_FmPort->portType)
4720    {
4721        case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
4722            strcpy(arr, "PORT_TYPE_OFFLINE_PARSING");
4723            flag = 0;
4724            break;
4725        case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
4726            strcpy(arr, "PORT_TYPE_HOST_COMMAND");
4727            flag = 0;
4728            break;
4729        case (e_FM_PORT_TYPE_RX):
4730            strcpy(arr, "PORT_TYPE_RX");
4731            flag = 1;
4732            break;
4733        case (e_FM_PORT_TYPE_RX_10G):
4734            strcpy(arr, "PORT_TYPE_RX_10G");
4735            flag = 1;
4736            break;
4737        case (e_FM_PORT_TYPE_TX):
4738            strcpy(arr, "PORT_TYPE_TX");
4739            flag = 2;
4740            break;
4741        case (e_FM_PORT_TYPE_TX_10G):
4742            strcpy(arr, "PORT_TYPE_TX_10G");
4743            flag = 2;
4744            break;
4745        default:
4746            return ERROR_CODE(E_INVALID_VALUE);
4747    }
4748
4749    DUMP_TITLE(UINT_TO_PTR(p_FmPort->hardwarePortId), ("PortId for %s %d", arr, p_FmPort->portId ));
4750    DUMP_TITLE(p_FmPort->p_FmPortBmiRegs, ("Bmi Port Regs"));
4751
4752    err = FmDumpPortRegs(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
4753    if(err)
4754        RETURN_ERROR(MAJOR, err, NO_MSG);
4755
4756    switch(flag)
4757    {
4758        case(0):
4759
4760        DUMP_SUBTITLE(("\n"));
4761        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocfg);
4762        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ost);
4763        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oda);
4764        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdne);
4765        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofne);
4766        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofca);
4767        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofpne);
4768        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opso);
4769        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opp);
4770        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occb);
4771
4772        DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai), ("fmbm_oprai"));
4773        DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
4774        {
4775            DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[i]), sizeof(uint32_t));
4776        }
4777        DUMP_SUBTITLE(("\n"));
4778        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofqid );
4779        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oefqid);
4780        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsdm );
4781        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsem );
4782        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofene );
4783        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmts);
4784        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmt);
4785
4786        {
4787#ifndef FM_NO_OP_OBSERVED_POOLS
4788            t_FmRevisionInfo    revInfo;
4789
4790            FM_GetRevision(p_FmPort->h_Fm, &revInfo);
4791            if (revInfo.majorRev == 4)
4792#endif /* !FM_NO_OP_OBSERVED_POOLS */
4793            {
4794                DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi, ("fmbm_oebmpi"));
4795
4796                DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS)
4797                {
4798                    DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi[i], sizeof(uint32_t));
4799                }
4800                DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocgm);
4801            }
4802        }
4803
4804        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ostc);
4805        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofrc );
4806        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdc );
4807        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofledc);
4808        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofufdc);
4809        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_offc);
4810        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofwdc);
4811        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofldec);
4812        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opc);
4813        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opcp);
4814        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occn);
4815        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_otuc);
4816        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oduc);
4817        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofuc);
4818        break;
4819    case(1):
4820        DUMP_SUBTITLE(("\n"));
4821        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rcfg);
4822        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rst);
4823        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rda);
4824        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfp);
4825        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_reth);
4826        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfed);
4827        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_ricp);
4828        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rebm);
4829        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfne);
4830        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfca);
4831        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfpne);
4832        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpso);
4833        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpp);
4834
4835        DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai), ("fmbm_rprai"));
4836        DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
4837        {
4838            DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[i]), sizeof(uint32_t));
4839        }
4840        DUMP_SUBTITLE(("\n"));
4841        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfqid);
4842        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_refqid);
4843        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsdm);
4844        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsem);
4845        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfene);
4846        DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi, ("fmbm_ebmpi"));
4847        DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
4848        {
4849            DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], sizeof(uint32_t));
4850        }
4851        DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt, ("fmbm_acnt"));
4852        DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
4853        {
4854            DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], sizeof(uint32_t));
4855        }
4856        DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm, ("fmbm_cgm"));
4857        DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_NUM_OF_CONGESTION_GRPS/32)
4858        {
4859            DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm[i], sizeof(uint32_t));
4860        }
4861        DUMP_SUBTITLE(("\n"));
4862        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_mpd);
4863        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rstc);
4864        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfrc);
4865        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfbc);
4866        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rlfc);
4867        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rffc);
4868        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfcd);
4869        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfldec);
4870        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rodc);
4871        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpc);
4872        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpcp);
4873        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rccn);
4874        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rtuc);
4875        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rrquc);
4876        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rduc);
4877        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfuc);
4878        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpac);
4879        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rdbg);
4880        break;
4881    case(2):
4882
4883        DUMP_SUBTITLE(("\n"));
4884        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfg);
4885        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tst);
4886        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tda);
4887        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfp);
4888        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfed);
4889        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ticp);
4890        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfne);
4891        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfca);
4892        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfqid);
4893        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfeqid);
4894        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfene);
4895        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmts);
4896        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmt);
4897        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tstc);
4898        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfrc);
4899        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdc);
4900        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfledc);
4901        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfufdc);
4902        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpc);
4903        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpcp);
4904        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tccn);
4905        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttuc);
4906        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttcquc);
4907        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tduc);
4908        DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfuc);
4909        break;
4910
4911   default:
4912        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid flag"));
4913    }
4914
4915    DUMP_TITLE(p_FmPort->p_FmPortQmiRegs, ("Qmi Port Regs"));
4916
4917    DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnc);
4918    DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pns);
4919    DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnts);
4920    DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnen);
4921    DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnetfc);
4922
4923    if(flag !=1)
4924    {
4925        DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndn);
4926        DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndc);
4927        DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndtfc);
4928        DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndfdc);
4929        DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndcc);
4930    }
4931
4932    return E_OK;
4933}
4934#endif /* (defined(DEBUG_ERRORS) && ... */
4935
4936t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
4937{
4938    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
4939    bool                tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort;
4940    int                 i;
4941    uint8_t             mod;
4942    uint32_t            tmpReg = 0;
4943
4944    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
4945
4946    {
4947#ifdef FM_NO_OP_OBSERVED_CGS
4948        t_FmRevisionInfo    revInfo;
4949
4950        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
4951        if (revInfo.majorRev != 4)
4952        {
4953            if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
4954                    (p_FmPort->portType != e_FM_PORT_TYPE_RX))
4955                RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
4956        }
4957        else
4958#endif /* FM_NO_OP_OBSERVED_CGS */
4959        if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
4960                (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
4961                (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
4962            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
4963    }
4964
4965    opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE);
4966
4967    /* to minimize memory access (groups may belong to the same regsiter, and may
4968    be out of order), we first collect all information into a 256 booleans array,
4969    representing each possible group. */
4970
4971    memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool));
4972    for(i=0;i<p_CongestionGrps->numOfCongestionGrpsToConsider;i++)
4973        tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE;
4974
4975    for(i=0;i<FM_PORT_NUM_OF_CONGESTION_GRPS;i++)
4976    {
4977        mod = (uint8_t)(i%32);
4978        /* each 32 congestion groups are represented by a register */
4979        if (mod == 0) /* first in a 32 bunch of congestion groups, get the currest register state  */
4980            tmpReg = opPort ?   GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm):
4981                                GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm[7-i/32]);
4982
4983        /* set in the register, the bit representing the relevant congestion group. */
4984        if(tmpArray[i])
4985            tmpReg |=  (0x00000001 << (uint32_t)mod);
4986
4987        if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */
4988        {
4989            if(opPort)
4990                WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg);
4991            else
4992                WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm[7-i/32], tmpReg);
4993        }
4994    }
4995
4996    return  E_OK;
4997}
4998
4999t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
5000{
5001    t_FmPort            *p_FmPort = (t_FmPort*)h_FmPort;
5002    bool                tmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS], opPort;
5003    int                 i;
5004    uint8_t             mod;
5005    uint32_t            tmpReg = 0;
5006
5007    SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
5008
5009    {
5010#ifdef FM_NO_OP_OBSERVED_CGS
5011        t_FmRevisionInfo    revInfo;
5012
5013        FM_GetRevision(p_FmPort->h_Fm, &revInfo);
5014        if (revInfo.majorRev != 4)
5015        {
5016            if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
5017                    (p_FmPort->portType != e_FM_PORT_TYPE_RX))
5018                RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
5019        }
5020        else
5021#endif /* FM_NO_OP_OBSERVED_CGS */
5022        if((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
5023                (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
5024                (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
5025            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
5026    }
5027
5028    opPort = (bool)((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? TRUE:FALSE);
5029
5030    /* to minimize memory access (groups may belong to the same regsiter, and may
5031    be out of order), we first collect all information into a 256 booleans array,
5032    representing each possible group. */
5033    memset(&tmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(bool));
5034    for(i=0;i<p_CongestionGrps->numOfCongestionGrpsToConsider;i++)
5035        tmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] = TRUE;
5036
5037    for(i=0;i<FM_PORT_NUM_OF_CONGESTION_GRPS;i++)
5038    {
5039        mod = (uint8_t)(i%32);
5040        /* each 32 congestion groups are represented by a register */
5041        if (mod == 0) /* first in a 32 bunch of congestion groups, get the currest register state  */
5042            tmpReg = opPort ?   GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm):
5043                                GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm[7-i/32]);
5044
5045        /* set in the register, the bit representing the relevant congestion group. */
5046        if(tmpArray[i])
5047            tmpReg &=  ~(0x00000001 << (uint32_t)mod);
5048
5049        if (mod == 31) /* last in a 32 bunch of congestion groups - write the corresponding register */
5050        {
5051            if(opPort)
5052                WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ocgm, tmpReg);
5053            else
5054                WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_cgm[7-i/32], tmpReg);
5055        }
5056    }
5057
5058    return  E_OK;
5059}
5060
5061