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 
52 static 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 
327 static 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 
336 static 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 
551 static 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 
560 static 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 
713 static 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 
825 static 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 
936 static 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 
1020 static 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 
1110 static 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 
1176 static 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 
1263 static 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 
1336 static 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 
1365 static 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 
1514 static 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 
1925 static 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 /********************************************/
1998 void 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 
2031 void 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 
2054 uint8_t FmPortGetNetEnvId(t_Handle h_FmPort)
2055 {
2056     return ((t_FmPort*)h_FmPort)->netEnvId;
2057 }
2058 
2059 uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort)
2060 {
2061     return ((t_FmPort*)h_FmPort)->hardwarePortId;
2062 }
2063 
2064 uint32_t FmPortGetPcdEngines(t_Handle h_FmPort)
2065 {
2066     return ((t_FmPort*)h_FmPort)->pcdEngines;
2067 }
2068 
2069 t_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.
2075 pndn, 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 
2111 t_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 /****************************************/
2212 t_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 *//***************************************************************************/
2456 t_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 *//***************************************************************************/
2600 t_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 
2642 t_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 
2656 t_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
2671 t_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 
2684 t_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 
2710 t_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 
2724 t_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 
2739 t_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 
2753 t_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 
2767 t_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 
2782 t_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 
2798 t_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 
2812 t_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 
2826 t_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 
2840 t_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 
2854 t_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 
2871 t_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 
2885 t_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 
2899 t_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 
2918 t_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 
2939 t_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 
2953 t_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 
2968 t_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 
2980 t_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 
2992 t_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 
3004 t_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 
3016 t_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 
3031 t_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 
3055 t_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 
3086 t_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 
3121 t_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 
3183 uint32_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 
3193 uint8_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
3207 uint8_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 
3221 t_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 
3234 uint64_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 
3247 uint8_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 
3260 t_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 
3340 t_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 
3399 t_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 
3505 t_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 
3539 t_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 
3558 t_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 
3592 t_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 
3677 t_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 
3765 t_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 
3804 t_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 
3832 t_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 
3864 uint32_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 
3957 t_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 
4036 uint32_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 
4074 t_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 
4109 bool 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 
4127 t_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 
4137 t_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 
4162 t_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 
4181 t_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 
4192 t_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 
4253 t_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 
4315 t_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 
4385 t_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 
4414 t_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 
4485 t_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 
4539 t_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 
4587 t_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 
4620 t_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 
4652 t_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))
4704 t_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 
4936 t_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 
4999 t_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