1/*
2 * Copyright 2008-2012 Freescale Semiconductor Inc.
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/******************************************************************************
35 @File          fm_kg.c
36
37 @Description   FM PCD ...
38*//***************************************************************************/
39#include "std_ext.h"
40#include "error_ext.h"
41#include "string_ext.h"
42#include "debug_ext.h"
43#include "net_ext.h"
44#include "fm_port_ext.h"
45
46#include "fm_common.h"
47#include "fm_pcd.h"
48#include "fm_hc.h"
49#include "fm_pcd_ipc.h"
50#include "fm_kg.h"
51#include "fsl_fman_kg.h"
52
53
54/****************************************/
55/*       static functions               */
56/****************************************/
57
58static uint32_t KgHwLock(t_Handle h_FmPcdKg)
59{
60    ASSERT_COND(h_FmPcdKg);
61    return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock);
62}
63
64static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags)
65{
66    ASSERT_COND(h_FmPcdKg);
67    XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags);
68}
69
70static uint32_t KgSchemeLock(t_Handle h_Scheme)
71{
72    ASSERT_COND(h_Scheme);
73    return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
74}
75
76static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags)
77{
78    ASSERT_COND(h_Scheme);
79    FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags);
80}
81
82static bool KgSchemeFlagTryLock(t_Handle h_Scheme)
83{
84    ASSERT_COND(h_Scheme);
85    return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
86}
87
88static void KgSchemeFlagUnlock(t_Handle h_Scheme)
89{
90    ASSERT_COND(h_Scheme);
91    FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
92}
93
94static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar)
95{
96
97    struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
98
99    if (fman_kg_write_ar_wait(regs, fmkg_ar))
100        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation"));
101
102    return E_OK;
103}
104
105static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code)
106{
107    int i;
108
109    switch (code)
110    {
111        case (KG_SCH_GEN_PARSE_RESULT_N_FQID):
112        case (KG_SCH_GEN_DEFAULT):
113        case (KG_SCH_GEN_NEXTHDR):
114            for (i=0 ; i<numOfSwDefaults ; i++)
115                if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_NOT_FROM_DATA)
116                    return swDefaults[i].dfltSelect;
117            break;
118        case (KG_SCH_GEN_SHIM1):
119        case (KG_SCH_GEN_SHIM2):
120        case (KG_SCH_GEN_IP_PID_NO_V):
121        case (KG_SCH_GEN_ETH_NO_V):
122        case (KG_SCH_GEN_SNAP_NO_V):
123        case (KG_SCH_GEN_VLAN1_NO_V):
124        case (KG_SCH_GEN_VLAN2_NO_V):
125        case (KG_SCH_GEN_ETH_TYPE_NO_V):
126        case (KG_SCH_GEN_PPP_NO_V):
127        case (KG_SCH_GEN_MPLS1_NO_V):
128        case (KG_SCH_GEN_MPLS_LAST_NO_V):
129        case (KG_SCH_GEN_L3_NO_V):
130        case (KG_SCH_GEN_IP2_NO_V):
131        case (KG_SCH_GEN_GRE_NO_V):
132        case (KG_SCH_GEN_L4_NO_V):
133            for (i=0 ; i<numOfSwDefaults ; i++)
134                if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V)
135                    return swDefaults[i].dfltSelect;
136            break;
137        case (KG_SCH_GEN_START_OF_FRM):
138        case (KG_SCH_GEN_ETH):
139        case (KG_SCH_GEN_SNAP):
140        case (KG_SCH_GEN_VLAN1):
141        case (KG_SCH_GEN_VLAN2):
142        case (KG_SCH_GEN_ETH_TYPE):
143        case (KG_SCH_GEN_PPP):
144        case (KG_SCH_GEN_MPLS1):
145        case (KG_SCH_GEN_MPLS2):
146        case (KG_SCH_GEN_MPLS3):
147        case (KG_SCH_GEN_MPLS_LAST):
148        case (KG_SCH_GEN_IPV4):
149        case (KG_SCH_GEN_IPV6):
150        case (KG_SCH_GEN_IPV4_TUNNELED):
151        case (KG_SCH_GEN_IPV6_TUNNELED):
152        case (KG_SCH_GEN_MIN_ENCAP):
153        case (KG_SCH_GEN_GRE):
154        case (KG_SCH_GEN_TCP):
155        case (KG_SCH_GEN_UDP):
156        case (KG_SCH_GEN_IPSEC_AH):
157        case (KG_SCH_GEN_SCTP):
158        case (KG_SCH_GEN_DCCP):
159        case (KG_SCH_GEN_IPSEC_ESP):
160            for (i=0 ; i<numOfSwDefaults ; i++)
161                if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA)
162                    return swDefaults[i].dfltSelect;
163            break;
164        default:
165            break;
166    }
167
168    return e_FM_PCD_KG_DFLT_ILLEGAL;
169}
170
171static uint8_t GetGenCode(e_FmPcdExtractFrom src, uint8_t *p_Offset)
172{
173    *p_Offset = 0;
174
175    switch (src)
176    {
177        case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
178            return KG_SCH_GEN_START_OF_FRM;
179        case (e_FM_PCD_EXTRACT_FROM_DFLT_VALUE):
180            return KG_SCH_GEN_DEFAULT;
181        case (e_FM_PCD_EXTRACT_FROM_PARSE_RESULT):
182            return KG_SCH_GEN_PARSE_RESULT_N_FQID;
183        case (e_FM_PCD_EXTRACT_FROM_ENQ_FQID):
184            *p_Offset = 32;
185            return KG_SCH_GEN_PARSE_RESULT_N_FQID;
186        case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
187            return KG_SCH_GEN_NEXTHDR;
188        default:
189            REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
190            return 0;
191    }
192}
193
194static uint8_t GetGenHdrCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex, bool ignoreProtocolValidation)
195{
196    if (!ignoreProtocolValidation)
197        switch (hdr)
198        {
199            case (HEADER_TYPE_NONE):
200                ASSERT_COND(FALSE);
201            case (HEADER_TYPE_ETH):
202                return KG_SCH_GEN_ETH;
203            case (HEADER_TYPE_LLC_SNAP):
204                return KG_SCH_GEN_SNAP;
205            case (HEADER_TYPE_PPPoE):
206                return KG_SCH_GEN_PPP;
207            case (HEADER_TYPE_MPLS):
208                if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
209                    return KG_SCH_GEN_MPLS1;
210                if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
211                    return KG_SCH_GEN_MPLS2;
212                if (hdrIndex == e_FM_PCD_HDR_INDEX_3)
213                    return KG_SCH_GEN_MPLS3;
214                if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
215                    return KG_SCH_GEN_MPLS_LAST;
216                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
217                return 0;
218            case (HEADER_TYPE_IPv4):
219                if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
220                    return KG_SCH_GEN_IPV4;
221                if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
222                    return KG_SCH_GEN_IPV4_TUNNELED;
223                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 header index"));
224                return 0;
225            case (HEADER_TYPE_IPv6):
226                if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
227                    return KG_SCH_GEN_IPV6;
228                if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
229                    return KG_SCH_GEN_IPV6_TUNNELED;
230                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 header index"));
231                return 0;
232            case (HEADER_TYPE_GRE):
233                return KG_SCH_GEN_GRE;
234            case (HEADER_TYPE_TCP):
235                return KG_SCH_GEN_TCP;
236            case (HEADER_TYPE_UDP):
237                return KG_SCH_GEN_UDP;
238            case (HEADER_TYPE_IPSEC_AH):
239                return KG_SCH_GEN_IPSEC_AH;
240            case (HEADER_TYPE_IPSEC_ESP):
241                return KG_SCH_GEN_IPSEC_ESP;
242            case (HEADER_TYPE_SCTP):
243                return KG_SCH_GEN_SCTP;
244            case (HEADER_TYPE_DCCP):
245                return KG_SCH_GEN_DCCP;
246            default:
247                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
248                return 0;
249        }
250    else
251        switch (hdr)
252        {
253            case (HEADER_TYPE_NONE):
254                ASSERT_COND(FALSE);
255            case (HEADER_TYPE_ETH):
256                return KG_SCH_GEN_ETH_NO_V;
257            case (HEADER_TYPE_LLC_SNAP):
258                return KG_SCH_GEN_SNAP_NO_V;
259            case (HEADER_TYPE_PPPoE):
260                return KG_SCH_GEN_PPP_NO_V;
261            case (HEADER_TYPE_MPLS):
262                 if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
263                    return KG_SCH_GEN_MPLS1_NO_V;
264                if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
265                    return KG_SCH_GEN_MPLS_LAST_NO_V;
266                if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_3) )
267                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Indexed MPLS Extraction not supported"));
268                else
269                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
270                return 0;
271            case (HEADER_TYPE_IPv4):
272            case (HEADER_TYPE_IPv6):
273                if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
274                    return KG_SCH_GEN_L3_NO_V;
275                if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
276                    return KG_SCH_GEN_IP2_NO_V;
277                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
278            case (HEADER_TYPE_MINENCAP):
279                return KG_SCH_GEN_IP2_NO_V;
280            case (HEADER_TYPE_USER_DEFINED_L3):
281                return KG_SCH_GEN_L3_NO_V;
282            case (HEADER_TYPE_GRE):
283                return KG_SCH_GEN_GRE_NO_V;
284            case (HEADER_TYPE_TCP):
285            case (HEADER_TYPE_UDP):
286            case (HEADER_TYPE_IPSEC_AH):
287            case (HEADER_TYPE_IPSEC_ESP):
288            case (HEADER_TYPE_SCTP):
289            case (HEADER_TYPE_DCCP):
290                return KG_SCH_GEN_L4_NO_V;
291            case (HEADER_TYPE_USER_DEFINED_SHIM1):
292                return KG_SCH_GEN_SHIM1;
293            case (HEADER_TYPE_USER_DEFINED_SHIM2):
294                return KG_SCH_GEN_SHIM2;
295            default:
296                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
297                return 0;
298        }
299}
300static t_GenericCodes GetGenFieldCode(e_NetHeaderType hdr, t_FmPcdFields field, bool ignoreProtocolValidation, e_FmPcdHdrIndex hdrIndex)
301{
302    if (!ignoreProtocolValidation)
303        switch (hdr)
304        {
305            case (HEADER_TYPE_NONE):
306                ASSERT_COND(FALSE);
307                break;
308            case (HEADER_TYPE_ETH):
309                switch (field.eth)
310                {
311                    case (NET_HEADER_FIELD_ETH_TYPE):
312                        return KG_SCH_GEN_ETH_TYPE;
313                    default:
314                        REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
315                        return 0;
316                }
317                break;
318            case (HEADER_TYPE_VLAN):
319                switch (field.vlan)
320                {
321                    case (NET_HEADER_FIELD_VLAN_TCI):
322                        if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
323                            return KG_SCH_GEN_VLAN1;
324                        if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
325                            return KG_SCH_GEN_VLAN2;
326                        REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
327                        return 0;
328                }
329                break;
330            case (HEADER_TYPE_MPLS):
331            case (HEADER_TYPE_IPSEC_AH):
332            case (HEADER_TYPE_IPSEC_ESP):
333            case (HEADER_TYPE_LLC_SNAP):
334            case (HEADER_TYPE_PPPoE):
335            case (HEADER_TYPE_IPv4):
336            case (HEADER_TYPE_IPv6):
337            case (HEADER_TYPE_GRE):
338            case (HEADER_TYPE_MINENCAP):
339            case (HEADER_TYPE_USER_DEFINED_L3):
340            case (HEADER_TYPE_TCP):
341            case (HEADER_TYPE_UDP):
342            case (HEADER_TYPE_SCTP):
343            case (HEADER_TYPE_DCCP):
344            case (HEADER_TYPE_USER_DEFINED_L4):
345                REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
346                return 0;
347            default:
348                break;
349
350        }
351        else
352            switch (hdr)
353            {
354                case (HEADER_TYPE_NONE):
355                    ASSERT_COND(FALSE);
356                    break;
357                case (HEADER_TYPE_ETH):
358                    switch (field.eth)
359                    {
360                        case (NET_HEADER_FIELD_ETH_TYPE):
361                            return KG_SCH_GEN_ETH_TYPE_NO_V;
362                        default:
363                            REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
364                            return 0;
365                    }
366                    break;
367                case (HEADER_TYPE_VLAN):
368                    switch (field.vlan)
369                    {
370                        case (NET_HEADER_FIELD_VLAN_TCI) :
371                            if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
372                                return KG_SCH_GEN_VLAN1_NO_V;
373                            if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
374                                return KG_SCH_GEN_VLAN2_NO_V;
375                            REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
376                            return 0;
377                    }
378                    break;
379                case (HEADER_TYPE_IPv4):
380                    switch (field.ipv4)
381                    {
382                        case (NET_HEADER_FIELD_IPv4_PROTO):
383                            return KG_SCH_GEN_IP_PID_NO_V;
384                        default:
385                            REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
386                            return 0;
387                    }
388                    break;
389                case (HEADER_TYPE_IPv6):
390                   switch (field.ipv6)
391                    {
392                        case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
393                            return KG_SCH_GEN_IP_PID_NO_V;
394                        default:
395                            REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
396                            return 0;
397                    }
398                    break;
399                case (HEADER_TYPE_MPLS):
400                case (HEADER_TYPE_LLC_SNAP):
401                case (HEADER_TYPE_PPPoE):
402                case (HEADER_TYPE_GRE):
403                case (HEADER_TYPE_MINENCAP):
404                case (HEADER_TYPE_USER_DEFINED_L3):
405                case (HEADER_TYPE_TCP):
406                case (HEADER_TYPE_UDP):
407                case (HEADER_TYPE_IPSEC_AH):
408                case (HEADER_TYPE_IPSEC_ESP):
409                case (HEADER_TYPE_SCTP):
410                case (HEADER_TYPE_DCCP):
411                case (HEADER_TYPE_USER_DEFINED_L4):
412                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
413                    return 0;
414                default:
415                    break;
416            }
417    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
418    return 0;
419}
420
421static t_KnownFieldsMasks GetKnownProtMask(t_FmPcd *p_FmPcd, e_NetHeaderType hdr, e_FmPcdHdrIndex index, t_FmPcdFields field)
422{
423    UNUSED(p_FmPcd);
424
425    switch (hdr)
426    {
427        case (HEADER_TYPE_NONE):
428            ASSERT_COND(FALSE);
429            break;
430        case (HEADER_TYPE_ETH):
431            switch (field.eth)
432            {
433                case (NET_HEADER_FIELD_ETH_DA):
434                    return KG_SCH_KN_MACDST;
435                case (NET_HEADER_FIELD_ETH_SA):
436                    return KG_SCH_KN_MACSRC;
437                case (NET_HEADER_FIELD_ETH_TYPE):
438                    return KG_SCH_KN_ETYPE;
439                default:
440                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
441                    return 0;
442            }
443        case (HEADER_TYPE_LLC_SNAP):
444            switch (field.llcSnap)
445            {
446                case (NET_HEADER_FIELD_LLC_SNAP_TYPE):
447                    return KG_SCH_KN_ETYPE;
448                default:
449                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
450                    return 0;
451            }
452        case (HEADER_TYPE_VLAN):
453            switch (field.vlan)
454            {
455                case (NET_HEADER_FIELD_VLAN_TCI):
456                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
457                        return KG_SCH_KN_TCI1;
458                    if (index == e_FM_PCD_HDR_INDEX_LAST)
459                        return KG_SCH_KN_TCI2;
460                    else
461                    {
462                        REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
463                        return 0;
464                    }
465                default:
466                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
467                    return 0;
468            }
469        case (HEADER_TYPE_MPLS):
470            switch (field.mpls)
471            {
472                case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
473                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
474                        return KG_SCH_KN_MPLS1;
475                    if (index == e_FM_PCD_HDR_INDEX_2)
476                        return KG_SCH_KN_MPLS2;
477                    if (index == e_FM_PCD_HDR_INDEX_LAST)
478                        return KG_SCH_KN_MPLS_LAST;
479                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
480                    return 0;
481                default:
482                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
483                    return 0;
484            }
485        case (HEADER_TYPE_IPv4):
486            switch (field.ipv4)
487            {
488                case (NET_HEADER_FIELD_IPv4_SRC_IP):
489                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
490                        return KG_SCH_KN_IPSRC1;
491                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
492                        return KG_SCH_KN_IPSRC2;
493                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
494                    return 0;
495                case (NET_HEADER_FIELD_IPv4_DST_IP):
496                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
497                        return KG_SCH_KN_IPDST1;
498                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
499                        return KG_SCH_KN_IPDST2;
500                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
501                    return 0;
502                case (NET_HEADER_FIELD_IPv4_PROTO):
503                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
504                        return KG_SCH_KN_PTYPE1;
505                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
506                        return KG_SCH_KN_PTYPE2;
507                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
508                    return 0;
509                case (NET_HEADER_FIELD_IPv4_TOS):
510                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
511                        return KG_SCH_KN_IPTOS_TC1;
512                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
513                        return KG_SCH_KN_IPTOS_TC2;
514                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
515                    return 0;
516                default:
517                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
518                    return 0;
519            }
520        case (HEADER_TYPE_IPv6):
521             switch (field.ipv6)
522            {
523                case (NET_HEADER_FIELD_IPv6_SRC_IP):
524                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
525                        return KG_SCH_KN_IPSRC1;
526                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
527                        return KG_SCH_KN_IPSRC2;
528                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
529                    return 0;
530                case (NET_HEADER_FIELD_IPv6_DST_IP):
531                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
532                        return KG_SCH_KN_IPDST1;
533                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
534                        return KG_SCH_KN_IPDST2;
535                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
536                    return 0;
537                case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
538                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
539                        return KG_SCH_KN_PTYPE1;
540                    if (index == e_FM_PCD_HDR_INDEX_2)
541                        return KG_SCH_KN_PTYPE2;
542                    if (index == e_FM_PCD_HDR_INDEX_LAST)
543#ifdef FM_KG_NO_IPPID_SUPPORT
544                    if (p_FmPcd->fmRevInfo.majorRev < 6)
545                        return KG_SCH_KN_PTYPE2;
546#endif /* FM_KG_NO_IPPID_SUPPORT */
547                        return KG_SCH_KN_IPPID;
548                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
549                    return 0;
550                case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
551                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
552                        return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1);
553                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
554                        return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2);
555                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
556                    return 0;
557                case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_TC):
558                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
559                        return KG_SCH_KN_IPTOS_TC1;
560                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
561                        return KG_SCH_KN_IPTOS_TC2;
562                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
563                    return 0;
564                case (NET_HEADER_FIELD_IPv6_FL):
565                    if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
566                        return KG_SCH_KN_IPV6FL1;
567                    if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
568                        return KG_SCH_KN_IPV6FL2;
569                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
570                    return 0;
571                default:
572                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
573                    return 0;
574            }
575        case (HEADER_TYPE_GRE):
576            switch (field.gre)
577            {
578                case (NET_HEADER_FIELD_GRE_TYPE):
579                    return KG_SCH_KN_GREPTYPE;
580                default:
581                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
582                    return 0;
583            }
584        case (HEADER_TYPE_MINENCAP):
585            switch (field.minencap)
586            {
587                case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
588                    return KG_SCH_KN_IPSRC2;
589                case (NET_HEADER_FIELD_MINENCAP_DST_IP):
590                    return KG_SCH_KN_IPDST2;
591                case (NET_HEADER_FIELD_MINENCAP_TYPE):
592                    return KG_SCH_KN_PTYPE2;
593                default:
594                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
595                    return 0;
596            }
597        case (HEADER_TYPE_TCP):
598            switch (field.tcp)
599            {
600                case (NET_HEADER_FIELD_TCP_PORT_SRC):
601                    return KG_SCH_KN_L4PSRC;
602                case (NET_HEADER_FIELD_TCP_PORT_DST):
603                    return KG_SCH_KN_L4PDST;
604                case (NET_HEADER_FIELD_TCP_FLAGS):
605                    return KG_SCH_KN_TFLG;
606                default:
607                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
608                    return 0;
609            }
610        case (HEADER_TYPE_UDP):
611            switch (field.udp)
612            {
613                case (NET_HEADER_FIELD_UDP_PORT_SRC):
614                    return KG_SCH_KN_L4PSRC;
615                case (NET_HEADER_FIELD_UDP_PORT_DST):
616                    return KG_SCH_KN_L4PDST;
617                default:
618                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
619                    return 0;
620            }
621        case (HEADER_TYPE_IPSEC_AH):
622            switch (field.ipsecAh)
623            {
624                case (NET_HEADER_FIELD_IPSEC_AH_SPI):
625                    return KG_SCH_KN_IPSEC_SPI;
626                case (NET_HEADER_FIELD_IPSEC_AH_NH):
627                    return KG_SCH_KN_IPSEC_NH;
628                default:
629                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
630                    return 0;
631            }
632        case (HEADER_TYPE_IPSEC_ESP):
633            switch (field.ipsecEsp)
634            {
635                case (NET_HEADER_FIELD_IPSEC_ESP_SPI):
636                    return KG_SCH_KN_IPSEC_SPI;
637                default:
638                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
639                    return 0;
640            }
641        case (HEADER_TYPE_SCTP):
642            switch (field.sctp)
643            {
644                case (NET_HEADER_FIELD_SCTP_PORT_SRC):
645                    return KG_SCH_KN_L4PSRC;
646                case (NET_HEADER_FIELD_SCTP_PORT_DST):
647                    return KG_SCH_KN_L4PDST;
648                default:
649                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
650                    return 0;
651            }
652        case (HEADER_TYPE_DCCP):
653            switch (field.dccp)
654            {
655                case (NET_HEADER_FIELD_DCCP_PORT_SRC):
656                    return KG_SCH_KN_L4PSRC;
657                case (NET_HEADER_FIELD_DCCP_PORT_DST):
658                    return KG_SCH_KN_L4PDST;
659                default:
660                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
661                    return 0;
662            }
663        case (HEADER_TYPE_PPPoE):
664            switch (field.pppoe)
665            {
666                case (NET_HEADER_FIELD_PPPoE_PID):
667                    return KG_SCH_KN_PPPID;
668                case (NET_HEADER_FIELD_PPPoE_SID):
669                    return KG_SCH_KN_PPPSID;
670                default:
671                    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
672                    return 0;
673            }
674        default:
675            break;
676
677    }
678
679    REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
680    return 0;
681}
682
683
684static uint8_t GetKnownFieldId(uint32_t bitMask)
685{
686    uint8_t cnt = 0;
687
688    while (bitMask)
689        if (bitMask & 0x80000000)
690            break;
691        else
692        {
693            cnt++;
694            bitMask <<= 1;
695        }
696    return cnt;
697
698}
699
700static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid)
701{
702    uint8_t i, mask, numOfOnesToClear, walking1Mask = 1;
703
704    /* bitOffset 1-7 --> mask 0x1-0x7F */
705    if (bitOffset<8)
706    {
707        mask = 0;
708        for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1)
709            mask |= walking1Mask;
710    }
711    else
712    {
713       mask = 0xFF;
714       numOfOnesToClear = 0;
715       if (fqid && bitOffset>24)
716           /* bitOffset 25-31 --> mask 0xFE-0x80 */
717           numOfOnesToClear = (uint8_t)(bitOffset-24);
718       else
719          /* bitOffset 9-15 --> mask 0xFE-0x80 */
720          if (!fqid && bitOffset>8)
721               numOfOnesToClear = (uint8_t)(bitOffset-8);
722       for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1)
723           mask &= ~walking1Mask;
724       /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/
725    }
726    return mask;
727}
728
729static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
730{
731    t_FmPcdKg           *p_FmPcdKg;
732    t_FmPcdKgScheme     *p_Scheme;
733    uint32_t            intFlags;
734    uint8_t             relativeSchemeId;
735    int                 i;
736
737    p_FmPcdKg = p_FmPcd->p_FmPcdKg;
738
739    /* for each scheme - update owners counters */
740    for (i = 0; i < p_BindPort->numOfSchemes; i++)
741    {
742        relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
743        ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
744
745        p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
746
747        /* increment owners number */
748        intFlags = KgSchemeLock(p_Scheme);
749        p_Scheme->owners++;
750        KgSchemeUnlock(p_Scheme, intFlags);
751    }
752}
753
754static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
755{
756    t_FmPcdKg           *p_FmPcdKg;
757    t_FmPcdKgScheme     *p_Scheme;
758    uint32_t            intFlags;
759    uint8_t             relativeSchemeId;
760    int                 i;
761
762    p_FmPcdKg = p_FmPcd->p_FmPcdKg;
763
764    /* for each scheme - update owners counters */
765    for (i = 0; i < p_BindPort->numOfSchemes; i++)
766    {
767        relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
768        ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
769
770        p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
771
772        /* increment owners number */
773        ASSERT_COND(p_Scheme->owners);
774        intFlags = KgSchemeLock(p_Scheme);
775        p_Scheme->owners--;
776        KgSchemeUnlock(p_Scheme, intFlags);
777    }
778}
779
780static void UpdateRequiredActionFlag(t_FmPcdKgScheme *p_Scheme, bool set)
781{
782    /* this routine is locked by the calling routine */
783    ASSERT_COND(p_Scheme);
784    ASSERT_COND(p_Scheme->valid);
785
786    if (set)
787        p_Scheme->requiredActionFlag = TRUE;
788    else
789    {
790        p_Scheme->requiredAction = 0;
791        p_Scheme->requiredActionFlag = FALSE;
792    }
793}
794
795static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add)
796{
797    struct fman_kg_regs *p_KgRegs;
798
799    uint32_t                tmpKgarReg = 0, intFlags;
800    t_Error                 err = E_OK;
801
802    /* The calling routine had locked the port, so for each port only one core can access
803     * (so we don't need a lock here) */
804
805    if (p_FmPcd->h_Hc)
806        return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add);
807
808    p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
809
810    tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
811    /* lock a common KG reg */
812    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
813    err = WriteKgarWait(p_FmPcd, tmpKgarReg);
814    if (err)
815    {
816        KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
817        RETURN_ERROR(MINOR, err, NO_MSG);
818    }
819
820    fman_kg_write_sp(p_KgRegs, spReg, add);
821
822    tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
823
824    err = WriteKgarWait(p_FmPcd, tmpKgarReg);
825    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
826    return err;
827}
828
829static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg)
830{
831    struct fman_kg_regs    *p_KgRegs;
832    uint32_t                tmpKgarReg, intFlags;
833    t_Error                 err;
834
835    p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
836
837    if (p_FmPcd->h_Hc)
838    {
839        err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg);
840        return err;
841    }
842
843    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
844    fman_kg_write_cpp(p_KgRegs, cppReg);
845    tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
846    err = WriteKgarWait(p_FmPcd, tmpKgarReg);
847    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
848
849    return err;
850}
851
852static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId)
853{
854    uint32_t    tmpKgpeCpp;
855
856    tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8);
857    tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT);
858
859    return tmpKgpeCpp;
860}
861
862static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
863{
864    uint32_t                tmpKgpeCpp = 0;
865
866    tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId);
867    return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp);
868}
869
870static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
871{
872    KgWriteCpp(p_FmPcd, hardwarePortId, 0);
873}
874
875#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
876static uint32_t __attribute__((unused)) ReadClsPlanBlockActionReg(uint8_t grpId)
877{
878    return (uint32_t)(FM_KG_KGAR_GO |
879                      FM_KG_KGAR_READ |
880                      FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
881                      DUMMY_PORT_ID |
882                      ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
883                      FM_PCD_KG_KGAR_WSEL_MASK);
884
885    /* if we ever want to write 1 by 1, use:
886       sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
887     */
888}
889#endif /* (defined(DEBUG_ERRORS) && ... */
890
891static void PcdKgErrorException(t_Handle h_FmPcd)
892{
893    t_FmPcd                 *p_FmPcd = (t_FmPcd *)h_FmPcd;
894    uint32_t                event,schemeIndexes = 0, index = 0;
895    struct fman_kg_regs    *p_KgRegs;
896
897    ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
898    p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
899    fman_kg_get_event(p_KgRegs, &event, &schemeIndexes);
900
901    if (event & FM_EX_KG_DOUBLE_ECC)
902        p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC);
903    if (event & FM_EX_KG_KEYSIZE_OVERFLOW)
904    {
905        if (schemeIndexes)
906        {
907            while (schemeIndexes)
908            {
909                if (schemeIndexes & 0x1)
910                    p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index));
911                schemeIndexes >>= 1;
912                index+=1;
913            }
914        }
915        else /* this should happen only when interrupt is forced. */
916            p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW);
917    }
918}
919
920static t_Error KgInitGuest(t_FmPcd *p_FmPcd)
921{
922    t_Error                     err = E_OK;
923    t_FmPcdIpcKgSchemesParams   kgAlloc;
924    uint32_t                    replyLength;
925    t_FmPcdIpcReply             reply;
926    t_FmPcdIpcMsg               msg;
927
928    ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID);
929
930    /* in GUEST_PARTITION, we use the IPC  */
931    memset(&reply, 0, sizeof(reply));
932    memset(&msg, 0, sizeof(msg));
933    memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams));
934    kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
935    kgAlloc.guestId = p_FmPcd->guestId;
936    msg.msgId = FM_PCD_ALLOC_KG_SCHEMES;
937    memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
938    replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t);
939    if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
940                                 (uint8_t*)&msg,
941                                 sizeof(msg.msgId) + sizeof(kgAlloc),
942                                 (uint8_t*)&reply,
943                                 &replyLength,
944                                 NULL,
945                                 NULL)) != E_OK)
946        RETURN_ERROR(MAJOR, err, NO_MSG);
947    if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)))
948        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
949    memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t));
950
951    return (t_Error)reply.error;
952}
953
954static t_Error KgInitMaster(t_FmPcd *p_FmPcd)
955{
956    t_Error                     err = E_OK;
957    struct fman_kg_regs         *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
958
959    ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
960
961    if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)
962        FmEnableRamsEcc(p_FmPcd->h_Fm);
963
964    fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd));
965
966    /* register even if no interrupts enabled, to allow future enablement */
967    FmRegisterIntr(p_FmPcd->h_Fm,
968                   e_FM_MOD_KG,
969                   0,
970                   e_FM_INTR_TYPE_ERR,
971                   PcdKgErrorException,
972                   p_FmPcd);
973
974    fman_kg_enable_scheme_interrupts(p_Regs);
975
976    if (p_FmPcd->p_FmPcdKg->numOfSchemes)
977    {
978        err = FmPcdKgAllocSchemes(p_FmPcd,
979                                  p_FmPcd->p_FmPcdKg->numOfSchemes,
980                                  p_FmPcd->guestId,
981                                  p_FmPcd->p_FmPcdKg->schemesIds);
982        if (err)
983            RETURN_ERROR(MINOR, err, NO_MSG);
984    }
985
986    return E_OK;
987}
988
989static void  ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
990{
991    ASSERT_COND(!p_Scheme->valid);
992    if (p_Scheme->netEnvId != ILLEGAL_NETENV)
993        FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
994    p_Scheme->valid = TRUE;
995}
996
997static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
998{
999    if (p_Scheme->owners)
1000       RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to"));
1001
1002    if (p_Scheme->netEnvId != ILLEGAL_NETENV)
1003        FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
1004    p_Scheme->valid = FALSE;
1005
1006    return E_OK;
1007}
1008
1009static t_Error BuildSchemeRegs(t_FmPcdKgScheme            *p_Scheme,
1010                               t_FmPcdKgSchemeParams      *p_SchemeParams,
1011                               struct fman_kg_scheme_regs *p_SchemeRegs)
1012{
1013    t_FmPcd                             *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd);
1014    uint32_t                            grpBits = 0;
1015    uint8_t                             grpBase;
1016    bool                                direct=TRUE, absolute=FALSE;
1017    uint16_t                            profileId=0, numOfProfiles=0, relativeProfileId;
1018    t_Error                             err = E_OK;
1019    int                                 i = 0;
1020    t_NetEnvParams                      netEnvParams;
1021    uint32_t                            tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp;
1022    t_FmPcdKgKeyExtractAndHashParams    *p_KeyAndHash = NULL;
1023    uint8_t                             j, curr, idx;
1024    uint8_t                             id, shift=0, code=0, offset=0, size=0;
1025    t_FmPcdExtractEntry                 *p_Extract = NULL;
1026    t_FmPcdKgExtractedOrParams          *p_ExtractOr;
1027    bool                                generic = FALSE;
1028    t_KnownFieldsMasks                  bitMask;
1029    e_FmPcdKgExtractDfltSelect          swDefault = (e_FmPcdKgExtractDfltSelect)0;
1030    t_FmPcdKgSchemesExtracts            *p_LocalExtractsArray;
1031    uint8_t                             numOfSwDefaults = 0;
1032    t_FmPcdKgExtractDflt                swDefaults[NUM_OF_SW_DEFAULTS];
1033    uint8_t                             currGenId = 0;
1034
1035    memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt));
1036    memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
1037
1038    if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
1039        RETURN_ERROR(MAJOR, E_INVALID_VALUE,
1040                     ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS));
1041
1042    /* by netEnv parameters, get match vector */
1043    if (!p_SchemeParams->alwaysDirect)
1044    {
1045        p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv);
1046        netEnvParams.netEnvId = p_Scheme->netEnvId;
1047        netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits;
1048        memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits);
1049        err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
1050        if (err)
1051            RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
1052        p_Scheme->matchVector = netEnvParams.vector;
1053    }
1054    else
1055    {
1056        p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT;
1057        p_Scheme->netEnvId = ILLEGAL_NETENV;
1058    }
1059
1060    if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID)
1061        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid"));
1062
1063    if (p_SchemeParams->bypassFqidGeneration)
1064    {
1065#ifdef FM_KG_NO_BYPASS_FQID_GEN
1066        if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
1067            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration."));
1068#endif /* FM_KG_NO_BYPASS_FQID_GEN */
1069        if (p_SchemeParams->baseFqid)
1070            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID"));
1071    }
1072    else
1073        if (!p_SchemeParams->baseFqid)
1074            DBG(WARNING, ("baseFqid is 0."));
1075
1076    if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR)
1077    {
1078        direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct;
1079        p_Scheme->directPlcr = direct;
1080        absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE);
1081        if (!direct && absolute)
1082            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared."));
1083
1084        if (direct)
1085        {
1086            profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId;
1087            numOfProfiles = 1;
1088        }
1089        else
1090        {
1091            profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1092            shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
1093            numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
1094        }
1095    }
1096
1097    if (p_SchemeParams->nextEngine == e_FM_PCD_CC)
1098    {
1099#ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN
1100        if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
1101        {
1102            if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
1103                RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration."));
1104        }
1105#endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */
1106
1107        err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree,
1108                             p_SchemeParams->kgNextEngineParams.cc.grpId,
1109                             &grpBits,
1110                             &grpBase);
1111        if (err)
1112            RETURN_ERROR(MAJOR, err, NO_MSG);
1113        p_Scheme->ccUnits = grpBits;
1114
1115        if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
1116           (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
1117        {
1118                if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile)
1119                    RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification."));
1120                absolute = FALSE;
1121                direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct;
1122                if (direct)
1123                {
1124                    profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId;
1125                    numOfProfiles = 1;
1126                }
1127                else
1128                {
1129                    profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1130                    shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
1131                    numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
1132                }
1133        }
1134    }
1135
1136    /* if policer is used directly after KG, or after CC */
1137    if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR)  ||
1138       ((p_SchemeParams->nextEngine == e_FM_PCD_CC) &&
1139        (p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
1140        (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)))
1141    {
1142        /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
1143        if (absolute)
1144        {
1145            /* for absolute direct policy only, */
1146            relativeProfileId = profileId;
1147            err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId);
1148            if (err)
1149                RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset"));
1150            if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId))
1151                RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid."));
1152            p_Scheme->relativeProfileId = profileId;
1153        }
1154        else
1155        {
1156            /* save relative profile id's for later check */
1157            p_Scheme->nextRelativePlcrProfile = TRUE;
1158            p_Scheme->relativeProfileId = profileId;
1159            p_Scheme->numOfProfiles = numOfProfiles;
1160        }
1161    }
1162    else
1163    {
1164        /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration
1165        is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */
1166        if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs)
1167            RETURN_ERROR(MAJOR, E_INVALID_STATE,
1168                    ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID"));
1169        if (p_SchemeParams->bypassFqidGeneration &&
1170                p_SchemeParams->useHash &&
1171                p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids)
1172            RETURN_ERROR(MAJOR, E_INVALID_STATE,
1173                    ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID"));
1174    }
1175
1176    /* configure all 21 scheme registers */
1177    tmpReg =  KG_SCH_MODE_EN;
1178    switch (p_SchemeParams->nextEngine)
1179    {
1180        case (e_FM_PCD_PLCR):
1181            /* add to mode register - NIA */
1182            tmpReg |= KG_SCH_MODE_NIA_PLCR;
1183            tmpReg |= NIA_ENG_PLCR;
1184            tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0);
1185            /* initialize policer profile command - */
1186            /*  configure kgse_ppc  */
1187            if (direct)
1188            /* use profileId as base, other fields are 0 */
1189                p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
1190            else
1191            {
1192                if (shift > MAX_PP_SHIFT)
1193                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
1194
1195                if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1196                    RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1197
1198                ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
1199                ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
1200                ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
1201                ppcTmp |= (uint32_t)profileId;
1202
1203                p_SchemeRegs->kgse_ppc = ppcTmp;
1204            }
1205            break;
1206        case (e_FM_PCD_CC):
1207            /* mode reg - define NIA */
1208            tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
1209
1210            p_SchemeRegs->kgse_ccbs = grpBits;
1211            tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT);
1212
1213            if (p_SchemeParams->kgNextEngineParams.cc.plcrNext)
1214            {
1215                if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)
1216                {
1217                    /* find out if absolute or relative */
1218                    if (absolute)
1219                         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow"));
1220                    if (direct)
1221                    {
1222                        /* mask = 0, base = directProfileId */
1223                        p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
1224                    }
1225                    else
1226                    {
1227                        if (shift > MAX_PP_SHIFT)
1228                            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
1229                        if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1230                            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1231
1232                        ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
1233                        ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
1234                        ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
1235                        ppcTmp |= (uint32_t)profileId;
1236
1237                        p_SchemeRegs->kgse_ppc = ppcTmp;
1238                    }
1239                }
1240            }
1241            break;
1242        case (e_FM_PCD_DONE):
1243            if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME)
1244                tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
1245            else
1246                tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
1247            break;
1248        default:
1249             RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported"));
1250    }
1251    p_SchemeRegs->kgse_mode = tmpReg;
1252
1253    p_SchemeRegs->kgse_mv = p_Scheme->matchVector;
1254
1255#if (DPAA_VERSION >= 11)
1256    if (p_SchemeParams->overrideStorageProfile)
1257    {
1258        p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE;
1259
1260        if (p_SchemeParams->storageProfile.direct)
1261        {
1262            profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId;
1263            shift = 0;
1264            numOfProfiles = 1;
1265        }
1266        else
1267        {
1268            profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
1269            shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift;
1270            numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles;
1271        }
1272        if (shift > MAX_SP_SHIFT)
1273            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT));
1274
1275        if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
1276            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
1277
1278        tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT;
1279        tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT);
1280        tmpReg |= (uint32_t)profileId;
1281
1282
1283        p_SchemeRegs->kgse_vsp = tmpReg;
1284
1285        p_Scheme->vspe = TRUE;
1286
1287    }
1288    else
1289        p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
1290#endif /* (DPAA_VERSION >= 11) */
1291
1292    if (p_SchemeParams->useHash)
1293    {
1294        p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams;
1295
1296        if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
1297             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range"));
1298
1299        /*  configure kgse_dv0  */
1300        p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0;
1301
1302        /*  configure kgse_dv1  */
1303        p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1;
1304
1305        if (!p_SchemeParams->bypassFqidGeneration)
1306        {
1307            if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids))
1308                RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2"));
1309            if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid)
1310                DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues."));
1311        }
1312
1313        /*  configure kgse_ekdv  */
1314        tmpReg = 0;
1315        for ( i=0 ;i<p_KeyAndHash->numOfUsedDflts ; i++)
1316        {
1317            switch (p_KeyAndHash->dflts[i].type)
1318            {
1319                case (e_FM_PCD_KG_MAC_ADDR):
1320                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT);
1321                    break;
1322                case (e_FM_PCD_KG_TCI):
1323                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT);
1324                    break;
1325                case (e_FM_PCD_KG_ENET_TYPE):
1326                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT);
1327                    break;
1328                case (e_FM_PCD_KG_PPP_SESSION_ID):
1329                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT);
1330                    break;
1331                case (e_FM_PCD_KG_PPP_PROTOCOL_ID):
1332                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT);
1333                    break;
1334                case (e_FM_PCD_KG_MPLS_LABEL):
1335                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT);
1336                    break;
1337                case (e_FM_PCD_KG_IP_ADDR):
1338                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT);
1339                    break;
1340                case (e_FM_PCD_KG_PROTOCOL_TYPE):
1341                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT);
1342                    break;
1343                case (e_FM_PCD_KG_IP_TOS_TC):
1344                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT);
1345                    break;
1346                case (e_FM_PCD_KG_IPV6_FLOW_LABEL):
1347                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
1348                    break;
1349                case (e_FM_PCD_KG_IPSEC_SPI):
1350                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT);
1351                    break;
1352                case (e_FM_PCD_KG_L4_PORT):
1353                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
1354                    break;
1355                case (e_FM_PCD_KG_TCP_FLAG):
1356                    tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT);
1357                    break;
1358                case (e_FM_PCD_KG_GENERIC_FROM_DATA):
1359                    swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA;
1360                    swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1361                    numOfSwDefaults ++;
1362                    break;
1363                case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V):
1364                    swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V;
1365                    swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1366                    numOfSwDefaults ++;
1367                    break;
1368                case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA):
1369                    swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA;
1370                    swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
1371                    numOfSwDefaults ++;
1372                   break;
1373                default:
1374                    RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1375            }
1376        }
1377        p_SchemeRegs->kgse_ekdv = tmpReg;
1378
1379        p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts));
1380        if (!p_LocalExtractsArray)
1381            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
1382
1383        /*  configure kgse_ekfc and  kgse_gec */
1384        knownTmp = 0;
1385        for ( i=0 ;i<p_KeyAndHash->numOfUsedExtracts ; i++)
1386        {
1387            p_Extract = &p_KeyAndHash->extractArray[i];
1388            switch (p_Extract->type)
1389            {
1390                case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
1391                    knownTmp |= KG_SCH_KN_PORT_ID;
1392                    /* save in driver structure */
1393                    p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID);
1394                    p_LocalExtractsArray->extractsArray[i].known = TRUE;
1395                    break;
1396                case (e_FM_PCD_EXTRACT_BY_HDR):
1397                    switch (p_Extract->extractByHdr.hdr)
1398                    {
1399#if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT))
1400                        case (HEADER_TYPE_UDP_LITE):
1401                            p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1402                            break;
1403#endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */
1404                        case (HEADER_TYPE_UDP_ENCAP_ESP):
1405                            switch (p_Extract->extractByHdr.type)
1406                            {
1407                                case (e_FM_PCD_EXTRACT_FROM_HDR):
1408                                    /* case where extraction from ESP only */
1409                                    if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE)
1410                                    {
1411                                        p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1412                                        p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE;
1413                                        p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1414                                    }
1415                                    else
1416                                    {
1417                                        p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1418                                        p_Extract->extractByHdr.ignoreProtocolValidation = FALSE;
1419                                    }
1420                                    break;
1421                                case (e_FM_PCD_EXTRACT_FROM_FIELD):
1422                                    switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp)
1423                                    {
1424                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
1425                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
1426                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
1427                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
1428                                            p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1429                                            break;
1430                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
1431                                            p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1432                                            p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1433                                            /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/
1434                                            p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1435                                            break;
1436                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
1437                                            p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1438                                            p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1439                                            p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET;
1440                                            p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1441                                            break;
1442                                    }
1443                                    break;
1444                                case (e_FM_PCD_EXTRACT_FULL_FIELD):
1445                                    switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp)
1446                                    {
1447                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
1448                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
1449                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
1450                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
1451                                            p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
1452                                            break;
1453                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
1454                                            p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1455                                            p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1456                                            p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE;
1457                                            p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET;
1458                                            p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1459                                            break;
1460                                        case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
1461                                            p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
1462                                            p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
1463                                            p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE;
1464                                            p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET;
1465                                            p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
1466                                            break;
1467                                    }
1468                                    break;
1469                            }
1470                            break;
1471                        default:
1472                            break;
1473                    }
1474                    switch (p_Extract->extractByHdr.type)
1475                    {
1476                        case (e_FM_PCD_EXTRACT_FROM_HDR):
1477                            generic = TRUE;
1478                            /* get the header code for the generic extract */
1479                            code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation);
1480                            /* set generic register fields */
1481                            offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset;
1482                            size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size;
1483                            break;
1484                        case (e_FM_PCD_EXTRACT_FROM_FIELD):
1485                            generic = TRUE;
1486                            /* get the field code for the generic extract */
1487                            code = GetGenFieldCode(p_Extract->extractByHdr.hdr,
1488                                        p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex);
1489                            offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset;
1490                            size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
1491                            break;
1492                        case (e_FM_PCD_EXTRACT_FULL_FIELD):
1493                            if (!p_Extract->extractByHdr.ignoreProtocolValidation)
1494                            {
1495                                /* if we have a known field for it - use it, otherwise use generic */
1496                                bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex,
1497                                            p_Extract->extractByHdr.extractByHdrType.fullField);
1498                                if (bitMask)
1499                                {
1500                                    knownTmp |= bitMask;
1501                                    /* save in driver structure */
1502                                    p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask);
1503                                    p_LocalExtractsArray->extractsArray[i].known = TRUE;
1504                                }
1505                                else
1506                                    generic = TRUE;
1507                            }
1508                            else
1509                                generic = TRUE;
1510                            if (generic)
1511                            {
1512                                /* tmp - till we cover more headers under generic */
1513                                XX_Free(p_LocalExtractsArray);
1514                                RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported"));
1515                            }
1516                            break;
1517                        default:
1518                            XX_Free(p_LocalExtractsArray);
1519                            RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1520                    }
1521                    break;
1522                case (e_FM_PCD_EXTRACT_NON_HDR):
1523                    /* use generic */
1524                    generic = TRUE;
1525                    offset = 0;
1526                    /* get the field code for the generic extract */
1527                    code = GetGenCode(p_Extract->extractNonHdr.src, &offset);
1528                    offset += p_Extract->extractNonHdr.offset;
1529                    size = p_Extract->extractNonHdr.size;
1530                    break;
1531                default:
1532                    RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1533            }
1534
1535            if (generic)
1536            {
1537                /* set generic register fields */
1538                if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS)
1539                {
1540                    XX_Free(p_LocalExtractsArray);
1541                    RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
1542                }
1543                if (!code)
1544                {
1545                    XX_Free(p_LocalExtractsArray);
1546                    RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
1547                }
1548
1549                genTmp = KG_SCH_GEN_VALID;
1550                genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
1551                genTmp |= offset;
1552                if ((size > MAX_KG_SCH_SIZE) || (size < 1))
1553                {
1554                    XX_Free(p_LocalExtractsArray);
1555                    RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)"));
1556                }
1557                genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT);
1558                swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code);
1559                if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL)
1560                    DBG(WARNING, ("No sw default configured"));
1561                else
1562                    genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT;
1563
1564                genTmp |= KG_SCH_GEN_MASK;
1565                p_SchemeRegs->kgse_gec[currGenId] = genTmp;
1566                /* save in driver structure */
1567                p_LocalExtractsArray->extractsArray[i].id = currGenId++;
1568                p_LocalExtractsArray->extractsArray[i].known = FALSE;
1569                generic = FALSE;
1570            }
1571        }
1572        p_SchemeRegs->kgse_ekfc = knownTmp;
1573
1574        selectTmp = 0;
1575        maskTmp = 0xFFFFFFFF;
1576        /*  configure kgse_bmch, kgse_bmcl and kgse_fqb */
1577
1578        if (p_KeyAndHash->numOfUsedMasks > FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
1579        {
1580            XX_Free(p_LocalExtractsArray);
1581            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS));
1582        }
1583        for ( i=0 ;i<p_KeyAndHash->numOfUsedMasks ; i++)
1584        {
1585            /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */
1586            id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id;
1587            /* Get the shift of the select field (depending on i) */
1588            GET_MASK_SEL_SHIFT(shift,i);
1589            if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known)
1590                selectTmp |= id << shift;
1591            else
1592                selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift;
1593
1594            /* Get the shift of the offset field (depending on i) - may
1595               be in  kgse_bmch or in kgse_fqb (depending on i) */
1596            GET_MASK_OFFSET_SHIFT(shift,i);
1597            if (i<=1)
1598                selectTmp |= p_KeyAndHash->masks[i].offset << shift;
1599            else
1600                fqbTmp |= p_KeyAndHash->masks[i].offset << shift;
1601
1602            /* Get the shift of the mask field (depending on i) */
1603            GET_MASK_SHIFT(shift,i);
1604            /* pass all bits */
1605            maskTmp |= KG_SCH_BITMASK_MASK << shift;
1606            /* clear bits that need masking */
1607            maskTmp &= ~(0xFF << shift) ;
1608            /* set mask bits */
1609            maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ;
1610        }
1611        p_SchemeRegs->kgse_bmch = selectTmp;
1612        p_SchemeRegs->kgse_bmcl = maskTmp;
1613        /* kgse_fqb will be written t the end of the routine */
1614
1615        /*  configure kgse_hc  */
1616        if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT)
1617        {
1618            XX_Free(p_LocalExtractsArray);
1619            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT));
1620        }
1621        if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT)
1622        {
1623            XX_Free(p_LocalExtractsArray);
1624            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT));
1625        }
1626
1627        tmpReg = 0;
1628
1629        tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift);
1630        tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
1631
1632        if (p_KeyAndHash->symmetricHash)
1633        {
1634            if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) ||
1635                    (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) ||
1636                    (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) ||
1637                    (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST)))
1638            {
1639                XX_Free(p_LocalExtractsArray);
1640                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing"));
1641            }
1642            tmpReg |= KG_SCH_HASH_CONFIG_SYM;
1643        }
1644        p_SchemeRegs->kgse_hc = tmpReg;
1645
1646        /* build the return array describing the order of the extractions */
1647
1648        /* the last currGenId places of the array
1649           are for generic extracts that are always last.
1650           We now sort for the calculation of the order of the known
1651           extractions we sort the known extracts between orderedArray[0] and
1652           orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1].
1653           for the calculation of the order of the generic extractions we use:
1654           num_of_generic - currGenId
1655           num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId
1656           first_generic_index = num_of_known */
1657        curr = 0;
1658        for (i=0;i<p_KeyAndHash->numOfUsedExtracts ; i++)
1659        {
1660            if (p_LocalExtractsArray->extractsArray[i].known)
1661            {
1662                ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId));
1663                j = curr;
1664                /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original
1665                index in the user's extractions array */
1666                /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1]
1667                location */
1668                while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id <
1669                      p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id))
1670                {
1671                    p_Scheme->orderedArray[j] =
1672                        p_Scheme->orderedArray[j-1];
1673                    j--;
1674                }
1675                p_Scheme->orderedArray[j] = (uint8_t)i;
1676                curr++;
1677            }
1678            else
1679            {
1680                /* index is first_generic_index + generic index (id) */
1681                idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id);
1682                ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY);
1683                p_Scheme->orderedArray[idx]= (uint8_t)i;
1684            }
1685        }
1686        XX_Free(p_LocalExtractsArray);
1687    }
1688    else
1689    {
1690        /* clear all unused registers: */
1691        p_SchemeRegs->kgse_ekfc = 0;
1692        p_SchemeRegs->kgse_ekdv = 0;
1693        p_SchemeRegs->kgse_bmch = 0;
1694        p_SchemeRegs->kgse_bmcl = 0;
1695        p_SchemeRegs->kgse_hc = 0;
1696        p_SchemeRegs->kgse_dv0 = 0;
1697        p_SchemeRegs->kgse_dv1 = 0;
1698    }
1699
1700    if (p_SchemeParams->bypassFqidGeneration)
1701        p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID;
1702
1703    /*  configure kgse_spc  */
1704    if ( p_SchemeParams->schemeCounter.update)
1705        p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value;
1706
1707
1708    /* check that are enough generic registers */
1709    if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS)
1710        RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
1711
1712    /* extracted OR mask on Qid */
1713    for ( i=0 ;i<p_SchemeParams->numOfUsedExtractedOrs ; i++)
1714    {
1715
1716        p_Scheme->extractedOrs = TRUE;
1717        /*  configure kgse_gec[i]  */
1718        p_ExtractOr = &p_SchemeParams->extractedOrs[i];
1719        switch (p_ExtractOr->type)
1720        {
1721            case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
1722                code = KG_SCH_GEN_PARSE_RESULT_N_FQID;
1723                offset = 0;
1724                break;
1725            case (e_FM_PCD_EXTRACT_BY_HDR):
1726                /* get the header code for the generic extract */
1727                code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation);
1728                /* set generic register fields */
1729                offset = p_ExtractOr->extractionOffset;
1730                break;
1731            case (e_FM_PCD_EXTRACT_NON_HDR):
1732                /* get the field code for the generic extract */
1733                offset = 0;
1734                code = GetGenCode(p_ExtractOr->src, &offset);
1735                offset += p_ExtractOr->extractionOffset;
1736                break;
1737            default:
1738                RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
1739        }
1740
1741        /* set generic register fields */
1742        if (!code)
1743            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
1744        genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID;
1745        genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
1746        genTmp |= offset;
1747        if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile)
1748            RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile"));
1749
1750        /************************************************************************************
1751            bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter
1752            in the following way:
1753
1754            Driver API and implementation:
1755            ==============================
1756            FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID.
1757            if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that
1758            are not overlapping FQID.
1759                     ------------------------
1760                    |      FQID (24)         |
1761                     ------------------------
1762            --------
1763           |        |  extracted OR byte
1764            --------
1765
1766            Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the
1767            PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that
1768            are not overlapping PP id.
1769
1770                     --------
1771                    | PP (8) |
1772                     --------
1773            --------
1774           |        |  extracted OR byte
1775            --------
1776
1777            HW implementation
1778            =================
1779            FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located
1780            as the highest byte of that word and may be rotated to effect any part os the FQID or
1781            the PP.
1782             ------------------------  --------
1783            |      FQID (24)         || PP (8) |
1784             ------------------------  --------
1785             --------
1786            |        |  extracted OR byte
1787             --------
1788
1789        ************************************************************************************/
1790
1791        if (p_ExtractOr->bitOffsetInFqid)
1792        {
1793            if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET )
1794              RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)"));
1795            if (p_ExtractOr->bitOffsetInFqid<8)
1796                genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT);
1797            else
1798                genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT);
1799            p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE);
1800        }
1801        else /* effect policer profile */
1802        {
1803            if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET )
1804              RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)"));
1805            p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile;
1806            genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT);
1807            p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE);
1808        }
1809
1810        genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT);
1811        /* clear bits that need masking */
1812        genTmp &= ~KG_SCH_GEN_MASK ;
1813        /* set mask bits */
1814        genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT);
1815        p_SchemeRegs->kgse_gec[currGenId++] = genTmp;
1816
1817    }
1818    /* clear all unused GEC registers */
1819    for ( i=currGenId ;i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
1820        p_SchemeRegs->kgse_gec[i] = 0;
1821
1822    /* add base Qid for this scheme */
1823    /* add configuration for kgse_fqb */
1824    if (p_SchemeParams->baseFqid & ~0x00FFFFFF)
1825        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1"));
1826
1827    fqbTmp |= p_SchemeParams->baseFqid;
1828    p_SchemeRegs->kgse_fqb = fqbTmp;
1829
1830    p_Scheme->nextEngine = p_SchemeParams->nextEngine;
1831    p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction;
1832
1833    return E_OK;
1834}
1835
1836
1837/*****************************************************************************/
1838/*              Inter-module API routines                                    */
1839/*****************************************************************************/
1840
1841t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet)
1842{
1843    t_FmPcd                         *p_FmPcd = (t_FmPcd*)h_FmPcd;
1844    t_FmPcdKgClsPlanGrp             *p_ClsPlanGrp;
1845    t_FmPcdIpcKgClsPlanParams       kgAlloc;
1846    t_Error                         err = E_OK;
1847    uint32_t                        oredVectors = 0;
1848    int                             i, j;
1849
1850    /* this routine is protected by the calling routine ! */
1851    if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS))
1852        RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected."));
1853
1854    /* find a new clsPlan group */
1855    for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
1856        if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used)
1857            break;
1858    if (i == FM_MAX_NUM_OF_PORTS)
1859        RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available."));
1860
1861    p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE;
1862
1863    p_Grp->clsPlanGrpId = (uint8_t)i;
1864
1865    if (p_Grp->numOfOptions == 0)
1866        p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i;
1867
1868    p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i];
1869    p_ClsPlanGrp->netEnvId = p_Grp->netEnvId;
1870    p_ClsPlanGrp->owners = 0;
1871    FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId);
1872    if (p_Grp->numOfOptions != 0)
1873        FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId);
1874
1875    p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions);
1876    /* a minimal group of 8 is required */
1877    if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP)
1878        p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP;
1879    if (p_FmPcd->guestId == NCSW_MASTER_ID)
1880    {
1881        err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry);
1882
1883        if (err)
1884            RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
1885    }
1886    else
1887    {
1888        t_FmPcdIpcMsg   msg;
1889        uint32_t        replyLength;
1890        t_FmPcdIpcReply reply;
1891
1892        /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
1893        memset(&reply, 0, sizeof(reply));
1894        memset(&msg, 0, sizeof(msg));
1895        memset(&kgAlloc, 0, sizeof(kgAlloc));
1896        kgAlloc.guestId = p_FmPcd->guestId;
1897        kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
1898        msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN;
1899        memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
1900        replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry));
1901        if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
1902                                     (uint8_t*)&msg,
1903                                     sizeof(msg.msgId) + sizeof(kgAlloc),
1904                                     (uint8_t*)&reply,
1905                                     &replyLength,
1906                                     NULL,
1907                                     NULL)) != E_OK)
1908            RETURN_ERROR(MAJOR, err, NO_MSG);
1909
1910        if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)))
1911            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
1912        if ((t_Error)reply.error != E_OK)
1913            RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG);
1914
1915        p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody);
1916    }
1917
1918    /* build classification plan entries parameters */
1919    p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry;
1920    p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
1921
1922    oredVectors = 0;
1923    for (i = 0; i<p_Grp->numOfOptions; i++)
1924    {
1925        oredVectors |= p_Grp->optVectors[i];
1926        /* save an array of used options - the indexes represent the power of 2 index */
1927        p_ClsPlanGrp->optArray[i] = p_Grp->options[i];
1928    }
1929    /* set the classification plan relevant entries so that all bits
1930     * relevant to the list of options is cleared
1931     */
1932    for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
1933        p_ClsPlanSet->vectors[j] = ~oredVectors;
1934
1935    for (i = 0; i<p_Grp->numOfOptions; i++)
1936    {
1937       /* option i got the place 2^i in the clsPlan array. all entries that
1938         * have bit i set, should have the vector bit cleared. So each option
1939         * has one location that it is exclusive (1,2,4,8...) and represent the
1940         * presence of that option only, and other locations that represent a
1941         * combination of options.
1942         * e.g:
1943         * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2
1944         * now represents a frame with ethernet-BC header - so the bit
1945         * representing ethernet-BC should be set and all other option bits
1946         * should be cleared.
1947         * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit
1948         * vector[1] set, but they also have other bits set:
1949         * 3=1+2, options 0 and 1
1950         * 6=2+4, options 1 and 2
1951         * 7=1+2+4, options 0,1,and 2
1952         * 10=2+8, options 1 and 3
1953         * etc.
1954         * */
1955
1956        /* now for each option (i), we set their bits in all entries (j)
1957         * that contain bit 2^i.
1958         */
1959        for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
1960        {
1961            if (j & (1<<i))
1962                p_ClsPlanSet->vectors[j] |= p_Grp->optVectors[i];
1963        }
1964    }
1965
1966    return E_OK;
1967}
1968
1969void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId)
1970{
1971    t_FmPcd                         *p_FmPcd = (t_FmPcd*)h_FmPcd;
1972    t_FmPcdIpcKgClsPlanParams       kgAlloc;
1973    t_Error                         err;
1974    t_FmPcdIpcMsg                   msg;
1975    uint32_t                        replyLength;
1976    t_FmPcdIpcReply                 reply;
1977
1978    /* check that no port is bound to this clsPlan */
1979    if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners)
1980    {
1981        REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to"));
1982        return;
1983    }
1984
1985    FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN);
1986
1987    if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
1988        p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
1989    else
1990        FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId);
1991
1992    /* free blocks */
1993    if (p_FmPcd->guestId == NCSW_MASTER_ID)
1994        KgFreeClsPlanEntries(h_FmPcd,
1995                             p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp,
1996                             p_FmPcd->guestId,
1997                             p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry);
1998    else    /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
1999    {
2000        memset(&reply, 0, sizeof(reply));
2001        memset(&msg, 0, sizeof(msg));
2002        kgAlloc.guestId = p_FmPcd->guestId;
2003        kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp;
2004        kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry;
2005        msg.msgId = FM_PCD_FREE_KG_CLSPLAN;
2006        memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
2007        replyLength = sizeof(uint32_t);
2008        err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
2009                                (uint8_t*)&msg,
2010                                sizeof(msg.msgId) + sizeof(kgAlloc),
2011                                (uint8_t*)&reply,
2012                                &replyLength,
2013                                NULL,
2014                                NULL);
2015        if (err != E_OK)
2016        {
2017            REPORT_ERROR(MINOR, err, NO_MSG);
2018            return;
2019        }
2020        if (replyLength != sizeof(uint32_t))
2021        {
2022            REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
2023            return;
2024        }
2025        if ((t_Error)reply.error != E_OK)
2026        {
2027            REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed"));
2028            return;
2029        }
2030    }
2031
2032    /* clear clsPlan driver structure */
2033    memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp));
2034}
2035
2036t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add)
2037{
2038    t_FmPcd                 *p_FmPcd = (t_FmPcd*)h_FmPcd;
2039    uint32_t                j, schemesPerPortVector = 0;
2040    t_FmPcdKgScheme         *p_Scheme;
2041    uint8_t                 i, relativeSchemeId;
2042    uint32_t                tmp, walking1Mask;
2043    uint8_t                 swPortIndex = 0;
2044
2045    SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2046    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2047    SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
2048
2049    /* for each scheme */
2050    for (i = 0; i<p_BindPort->numOfSchemes; i++)
2051    {
2052        relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
2053        if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
2054            RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
2055
2056        if (add)
2057        {
2058            p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
2059            if (!FmPcdKgIsSchemeValidSw(p_Scheme))
2060                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
2061            /* check netEnvId  of the port against the scheme netEnvId */
2062            if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV))
2063                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId"));
2064
2065            /* if next engine is private port policer profile, we need to check that it is valid */
2066            HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId);
2067            if (p_Scheme->nextRelativePlcrProfile)
2068            {
2069                for (j = 0;j<p_Scheme->numOfProfiles;j++)
2070                {
2071                    ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort);
2072                    if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles)
2073                        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range"));
2074                     if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j)))
2075                        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid."));
2076                }
2077            }
2078            if (!p_BindPort->useClsPlan)
2079            {
2080                /* This check may be redundant as port is a assigned to the whole NetEnv */
2081
2082                /* if this port does not use clsPlan, it may not be bound to schemes with units that contain
2083                cls plan options. Schemes that are used only directly, should not be checked.
2084                it also may not be bound to schemes that go to CC with units that are options  - so we OR
2085                the match vector and the grpBits (= ccUnits) */
2086                if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits)
2087                {
2088                    uint8_t netEnvId;
2089                    walking1Mask = 0x80000000;
2090                    netEnvId = (p_Scheme->netEnvId == ILLEGAL_NETENV)? p_BindPort->netEnvId:p_Scheme->netEnvId;
2091                    tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector;
2092                    tmp |= p_Scheme->ccUnits;
2093                    while (tmp)
2094                    {
2095                        if (tmp & walking1Mask)
2096                        {
2097                            tmp &= ~walking1Mask;
2098                            if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, netEnvId, walking1Mask))
2099                                RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options"));
2100                        }
2101                        walking1Mask >>= 1;
2102                    }
2103                }
2104            }
2105        }
2106        /* build vector */
2107        schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]);
2108    }
2109
2110    *p_SpReg = schemesPerPortVector;
2111
2112    return E_OK;
2113}
2114
2115t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes  *p_SchemeBind)
2116{
2117    t_FmPcd                 *p_FmPcd = (t_FmPcd*)h_FmPcd;
2118    uint32_t                spReg;
2119    t_Error                 err = E_OK;
2120
2121    err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE);
2122    if (err)
2123        RETURN_ERROR(MAJOR, err, NO_MSG);
2124
2125    err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE);
2126    if (err)
2127        RETURN_ERROR(MAJOR, err, NO_MSG);
2128
2129    IncSchemeOwners(p_FmPcd, p_SchemeBind);
2130
2131    return E_OK;
2132}
2133
2134t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
2135{
2136    t_FmPcd                 *p_FmPcd = (t_FmPcd*)h_FmPcd;
2137    uint32_t                spReg;
2138    t_Error                 err = E_OK;
2139
2140    err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE);
2141    if (err)
2142        RETURN_ERROR(MAJOR, err, NO_MSG);
2143
2144    err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE);
2145    if (err)
2146        RETURN_ERROR(MAJOR, err, NO_MSG);
2147
2148    DecSchemeOwners(p_FmPcd, p_SchemeBind);
2149
2150    return E_OK;
2151}
2152
2153bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme)
2154{
2155    t_FmPcdKgScheme     *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
2156
2157    return p_Scheme->valid;
2158}
2159
2160bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId)
2161{
2162    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2163
2164    if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT)
2165        return TRUE;
2166    else
2167        return FALSE;
2168}
2169
2170t_Error  FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
2171{
2172    t_FmPcd             *p_FmPcd = (t_FmPcd *)h_FmPcd;
2173    uint8_t             i, j;
2174
2175    SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2176    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2177
2178    /* This routine is issued only on master core of master partition -
2179       either directly or through IPC, so no need for lock */
2180
2181    for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++)
2182    {
2183        if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated)
2184        {
2185            p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE;
2186            p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId;
2187            p_SchemesIds[j] = i;
2188            j++;
2189        }
2190    }
2191
2192    if (j != numOfSchemes)
2193    {
2194        /* roll back */
2195        for (j--; j; j--)
2196        {
2197            p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE;
2198            p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0;
2199            p_SchemesIds[j] = 0;
2200        }
2201
2202        RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found"));
2203    }
2204
2205    return E_OK;
2206}
2207
2208t_Error  FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
2209{
2210    t_FmPcd             *p_FmPcd = (t_FmPcd *)h_FmPcd;
2211    uint8_t             i;
2212
2213    SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
2214    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
2215
2216    /* This routine is issued only on master core of master partition -
2217       either directly or through IPC */
2218
2219    for (i = 0; i < numOfSchemes; i++)
2220    {
2221        if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated)
2222        {
2223            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated"));
2224        }
2225        if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId)
2226        {
2227            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. "));
2228        }
2229        p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE;
2230        p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0;
2231    }
2232
2233    return E_OK;
2234}
2235
2236t_Error  KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First)
2237{
2238    t_FmPcd     *p_FmPcd = (t_FmPcd *)h_FmPcd;
2239    uint8_t     numOfBlocks, blocksFound=0, first=0;
2240    uint8_t     i, j;
2241
2242    /* This routine is issued only on master core of master partition -
2243       either directly or through IPC, so no need for lock */
2244
2245    if (!numOfClsPlanEntries)
2246        return E_OK;
2247
2248    if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries)))
2249         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8"));
2250
2251    numOfBlocks =  (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
2252
2253    /* try to find consequent blocks */
2254    first = 0;
2255    for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;)
2256    {
2257        if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated)
2258        {
2259            blocksFound++;
2260            i++;
2261            if (blocksFound == numOfBlocks)
2262                break;
2263        }
2264        else
2265        {
2266            blocksFound = 0;
2267            /* advance i to the next aligned address */
2268            first = i = (uint8_t)(first + numOfBlocks);
2269        }
2270    }
2271
2272    if (blocksFound == numOfBlocks)
2273    {
2274        *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP);
2275        for (j = first; j < (first + numOfBlocks); j++)
2276        {
2277            p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE;
2278            p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId;
2279        }
2280        return E_OK;
2281    }
2282    else
2283        RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan"));
2284}
2285
2286void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base)
2287{
2288    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2289    uint8_t     numOfBlocks;
2290    uint8_t     i, baseBlock;
2291
2292#ifdef DISABLE_ASSERTIONS
2293UNUSED(guestId);
2294#endif /* DISABLE_ASSERTIONS */
2295
2296    /* This routine is issued only on master core of master partition -
2297       either directly or through IPC, so no need for lock */
2298
2299    numOfBlocks =  (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
2300    ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP));
2301
2302    baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP);
2303    for (i=baseBlock;i<baseBlock+numOfBlocks;i++)
2304    {
2305        ASSERT_COND(p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated);
2306        ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId);
2307        p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE;
2308        p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0;
2309    }
2310}
2311
2312void KgEnable(t_FmPcd *p_FmPcd)
2313{
2314    struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
2315
2316    ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2317    fman_kg_enable(p_Regs);
2318}
2319
2320void KgDisable(t_FmPcd *p_FmPcd)
2321{
2322    struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
2323
2324    ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2325    fman_kg_disable(p_Regs);
2326}
2327
2328void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set)
2329{
2330    t_FmPcd                 *p_FmPcd = (t_FmPcd *)h_FmPcd;
2331    struct fman_kg_cp_regs  *p_FmPcdKgPortRegs;
2332    uint32_t                tmpKgarReg = 0, intFlags;
2333    uint16_t                i, j;
2334
2335    /* This routine is protected by the calling routine ! */
2336    ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
2337    p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs;
2338
2339    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2340    for (i=p_Set->baseEntry;i<p_Set->baseEntry+p_Set->numOfClsPlanEntries;i+=8)
2341    {
2342        tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
2343
2344        for (j = i; j < i+8; j++)
2345        {
2346            ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1));
2347            WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]);
2348        }
2349
2350        if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
2351        {
2352            REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED"));
2353            KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2354            return;
2355        }
2356    }
2357    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2358}
2359
2360t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
2361{
2362    t_FmPcdKg   *p_FmPcdKg;
2363
2364    UNUSED(p_FmPcd);
2365
2366    if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES)
2367    {
2368        REPORT_ERROR(MAJOR, E_INVALID_VALUE,
2369                     ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES));
2370        return NULL;
2371    }
2372
2373    p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg));
2374    if (!p_FmPcdKg)
2375    {
2376        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED"));
2377        return NULL;
2378    }
2379    memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg));
2380
2381
2382    if (FmIsMaster(p_FmPcd->h_Fm))
2383    {
2384        p_FmPcdKg->p_FmPcdKgRegs  = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm));
2385        p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions;
2386        p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0];
2387    }
2388
2389    p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes;
2390    if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes)
2391    {
2392        p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
2393        DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES"));
2394    }
2395
2396    p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
2397
2398    return p_FmPcdKg;
2399}
2400
2401t_Error KgInit(t_FmPcd *p_FmPcd)
2402{
2403    t_Error err = E_OK;
2404
2405    p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock();
2406    if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2407        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock"));
2408
2409    if (p_FmPcd->guestId == NCSW_MASTER_ID)
2410        err =  KgInitMaster(p_FmPcd);
2411    else
2412        err =  KgInitGuest(p_FmPcd);
2413
2414    if (err != E_OK)
2415    {
2416        if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2417            XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2418    }
2419
2420    return err;
2421}
2422
2423t_Error KgFree(t_FmPcd *p_FmPcd)
2424{
2425    t_FmPcdIpcKgSchemesParams       kgAlloc;
2426    t_Error                         err = E_OK;
2427    t_FmPcdIpcMsg                   msg;
2428    uint32_t                        replyLength;
2429    t_FmPcdIpcReply                 reply;
2430
2431    FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR);
2432
2433    if (p_FmPcd->guestId == NCSW_MASTER_ID)
2434    {
2435        err = FmPcdKgFreeSchemes(p_FmPcd,
2436                                    p_FmPcd->p_FmPcdKg->numOfSchemes,
2437                                    p_FmPcd->guestId,
2438                                    p_FmPcd->p_FmPcdKg->schemesIds);
2439        if (err)
2440            RETURN_ERROR(MAJOR, err, NO_MSG);
2441
2442        if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2443            XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2444
2445        return E_OK;
2446    }
2447
2448    /* guest */
2449    memset(&reply, 0, sizeof(reply));
2450    memset(&msg, 0, sizeof(msg));
2451    kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
2452    kgAlloc.guestId = p_FmPcd->guestId;
2453    ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES);
2454    memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes);
2455    msg.msgId = FM_PCD_FREE_KG_SCHEMES;
2456    memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
2457    replyLength = sizeof(uint32_t);
2458    if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
2459                                 (uint8_t*)&msg,
2460                                 sizeof(msg.msgId) + sizeof(kgAlloc),
2461                                 (uint8_t*)&reply,
2462                                 &replyLength,
2463                                 NULL,
2464                                 NULL)) != E_OK)
2465        RETURN_ERROR(MAJOR, err, NO_MSG);
2466    if (replyLength != sizeof(uint32_t))
2467        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
2468
2469    if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
2470        XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
2471
2472    return (t_Error)reply.error;
2473}
2474
2475t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp)
2476{
2477    t_FmPcd                                 *p_FmPcd = (t_FmPcd *)h_FmPcd;
2478    t_FmPcdKgInterModuleClsPlanGrpParams    grpParams, *p_GrpParams;
2479    t_FmPcdKgClsPlanGrp                     *p_ClsPlanGrp;
2480    t_FmPcdKgInterModuleClsPlanSet          *p_ClsPlanSet;
2481    t_Error                                 err;
2482
2483    /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules,
2484       so no need for lock here */
2485
2486    memset(&grpParams, 0, sizeof(grpParams));
2487    grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN;
2488    p_GrpParams = &grpParams;
2489
2490    p_GrpParams->netEnvId = netEnvId;
2491
2492    /* Get from the NetEnv the information of the clsPlan (can be already created,
2493     * or needs to build) */
2494    err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams);
2495    if (err)
2496        RETURN_ERROR(MINOR,err,NO_MSG);
2497
2498    if (p_GrpParams->grpExists)
2499    {
2500        /* this group was already updated (at least) in SW */
2501        *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
2502    }
2503    else
2504    {
2505        p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
2506        if (!p_ClsPlanSet)
2507            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
2508        memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
2509        /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */
2510        err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet);
2511        if (err)
2512        {
2513            XX_Free(p_ClsPlanSet);
2514            RETURN_ERROR(MINOR, err, NO_MSG);
2515        }
2516        *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
2517
2518        if (p_FmPcd->h_Hc)
2519        {
2520            /* write clsPlan entries to memory */
2521            err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet);
2522            if (err)
2523            {
2524                XX_Free(p_ClsPlanSet);
2525                RETURN_ERROR(MAJOR, err, NO_MSG);
2526            }
2527        }
2528        else
2529            /* write clsPlan entries to memory */
2530            KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
2531
2532        XX_Free(p_ClsPlanSet);
2533    }
2534
2535    /* Set caller parameters     */
2536
2537    /* mark if this is an empty classification group */
2538    if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
2539        *p_IsEmptyClsPlanGrp = TRUE;
2540    else
2541        *p_IsEmptyClsPlanGrp = FALSE;
2542
2543    p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId];
2544
2545   /* increment owners number */
2546    p_ClsPlanGrp->owners++;
2547
2548    /* copy options array for port */
2549    memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t));
2550
2551    /* bind port to the new or existing group */
2552    err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId);
2553    if (err)
2554        RETURN_ERROR(MINOR, err, NO_MSG);
2555
2556    return E_OK;
2557}
2558
2559t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
2560{
2561    t_FmPcd                         *p_FmPcd = (t_FmPcd *)h_FmPcd;
2562    t_FmPcdKgClsPlanGrp             *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId];
2563    t_FmPcdKgInterModuleClsPlanSet  *p_ClsPlanSet;
2564    t_Error                         err;
2565
2566    /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules,
2567       so no need for lock here */
2568
2569    UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId);
2570
2571    /* decrement owners number */
2572    ASSERT_COND(p_ClsPlanGrp->owners);
2573    p_ClsPlanGrp->owners--;
2574
2575    if (!p_ClsPlanGrp->owners)
2576    {
2577        if (p_FmPcd->h_Hc)
2578        {
2579            err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId);
2580            return err;
2581        }
2582        else
2583        {
2584            /* clear clsPlan entries in memory */
2585            p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
2586            if (!p_ClsPlanSet)
2587            {
2588                RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
2589            }
2590            memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
2591
2592            p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry;
2593            p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp;
2594            KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
2595            XX_Free(p_ClsPlanSet);
2596
2597            FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId);
2598       }
2599    }
2600    return E_OK;
2601}
2602
2603uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId)
2604{
2605    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2606    ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2607
2608    return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction;
2609}
2610
2611uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId)
2612{
2613    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2614
2615   ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2616
2617    return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredActionFlag;
2618}
2619
2620bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId)
2621{
2622    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2623
2624   ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2625
2626    return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr;
2627}
2628
2629
2630uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId)
2631{
2632    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2633
2634   ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2635
2636    return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId;
2637}
2638
2639bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId)
2640{
2641    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2642
2643   ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2644
2645    if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs &&
2646        p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) ||
2647        p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile)
2648        return TRUE;
2649    else
2650        return FALSE;
2651
2652}
2653
2654e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId)
2655{
2656    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2657
2658    ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid);
2659
2660    return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine;
2661}
2662
2663e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId)
2664{
2665    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2666
2667    ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
2668
2669    return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction;
2670}
2671
2672void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction)
2673{
2674    t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
2675
2676    /* this routine is protected by calling routine */
2677
2678    ASSERT_COND(p_Scheme->valid);
2679
2680    p_Scheme->requiredAction |= requiredAction;
2681}
2682
2683bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg)
2684{
2685    return (bool)!!(schemeModeReg & KG_SCH_MODE_EN);
2686}
2687
2688uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter)
2689{
2690    return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2691                      FM_KG_KGAR_GO |
2692                      FM_KG_KGAR_WRITE |
2693                      FM_KG_KGAR_SEL_SCHEME_ENTRY |
2694                      DUMMY_PORT_ID |
2695                      (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0));
2696}
2697
2698uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId)
2699{
2700    return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2701                      FM_KG_KGAR_GO |
2702                      FM_KG_KGAR_READ |
2703                      FM_KG_KGAR_SEL_SCHEME_ENTRY |
2704                      DUMMY_PORT_ID |
2705                      FM_KG_KGAR_SCM_WSEL_UPDATE_CNT);
2706
2707}
2708
2709uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId)
2710{
2711    return (uint32_t)(FM_KG_KGAR_GO |
2712                      FM_KG_KGAR_WRITE |
2713                      FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
2714                      DUMMY_PORT_ID |
2715                      ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
2716                      FM_PCD_KG_KGAR_WSEL_MASK);
2717
2718    /* if we ever want to write 1 by 1, use:
2719       sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
2720     */
2721}
2722
2723uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId)
2724{
2725
2726    return (uint32_t)(FM_KG_KGAR_GO |
2727                      FM_KG_KGAR_WRITE |
2728                      FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2729                      hardwarePortId |
2730                      FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
2731}
2732
2733uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId)
2734{
2735
2736    return (uint32_t)(FM_KG_KGAR_GO |
2737                      FM_KG_KGAR_READ |
2738                      FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2739                      hardwarePortId |
2740                      FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
2741}
2742
2743uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId)
2744{
2745
2746    return (uint32_t)(FM_KG_KGAR_GO |
2747                      FM_KG_KGAR_WRITE |
2748                      FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
2749                      hardwarePortId |
2750                      FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
2751}
2752
2753uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp)
2754{
2755    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2756
2757    return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry;
2758}
2759
2760uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp)
2761{
2762    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2763
2764    return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp;
2765}
2766
2767
2768uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme)
2769{
2770    return ((t_FmPcdKgScheme*)h_Scheme)->schemeId;
2771
2772}
2773
2774#if (DPAA_VERSION >= 11)
2775bool FmPcdKgGetVspe(t_Handle h_Scheme)
2776{
2777    return ((t_FmPcdKgScheme*)h_Scheme)->vspe;
2778
2779}
2780#endif /* (DPAA_VERSION >= 11) */
2781
2782uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId)
2783{
2784    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2785    uint8_t     i;
2786
2787    for (i = 0;i<p_FmPcd->p_FmPcdKg->numOfSchemes;i++)
2788        if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId)
2789            return i;
2790
2791    if (i == p_FmPcd->p_FmPcdKg->numOfSchemes)
2792        REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range"));
2793
2794    return FM_PCD_KG_NUM_OF_SCHEMES;
2795}
2796
2797t_Handle FmPcdKgGetSchemeHandle(t_Handle h_FmPcd, uint8_t relativeSchemeId)
2798{
2799    t_FmPcd     *p_FmPcd = (t_FmPcd*)h_FmPcd;
2800
2801    ASSERT_COND(p_FmPcd);
2802
2803    /* check that schemeId is in range */
2804    if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
2805    {
2806        REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
2807        return NULL;
2808    }
2809
2810    if (!FmPcdKgIsSchemeValidSw(&p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]))
2811        return NULL;
2812
2813    return &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
2814}
2815
2816bool FmPcdKgIsSchemeHasOwners(t_Handle h_Scheme)
2817{
2818    return (((t_FmPcdKgScheme*)h_Scheme)->owners == 0)?FALSE:TRUE;
2819}
2820
2821t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
2822{
2823    t_FmPcd             *p_FmPcd = (t_FmPcd*)h_FmPcd;
2824    uint8_t             relativeSchemeId, physicalSchemeId;
2825    uint32_t            tmpKgarReg, tmpReg32 = 0, intFlags;
2826    t_Error             err;
2827    t_FmPcdKgScheme     *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
2828
2829    SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
2830    SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0);
2831    SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
2832
2833    /* Calling function locked all PCD modules, so no need to lock here */
2834
2835    if (!FmPcdKgIsSchemeValidSw(h_Scheme))
2836        RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
2837
2838    if (p_FmPcd->h_Hc)
2839    {
2840        err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value);
2841
2842        UpdateRequiredActionFlag(h_Scheme,TRUE);
2843        FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction);
2844        return err;
2845    }
2846
2847    physicalSchemeId = p_Scheme->schemeId;
2848
2849    relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
2850    if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
2851        RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
2852
2853    if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredActionFlag ||
2854        !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction))
2855    {
2856        if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
2857        {
2858            switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine)
2859            {
2860                case (e_FM_PCD_DONE):
2861                    if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME)
2862                    {
2863                        tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2864                        intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2865                        WriteKgarWait(p_FmPcd, tmpKgarReg);
2866                        tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2867                        ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
2868                        WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA);
2869                        /* call indirect command for scheme write */
2870                        tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2871                        WriteKgarWait(p_FmPcd, tmpKgarReg);
2872                        KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2873                    }
2874                break;
2875                case (e_FM_PCD_PLCR):
2876                    if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr ||
2877                       (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs &&
2878                        p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) ||
2879                        p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile)
2880                        {
2881                            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
2882                        }
2883                        err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction);
2884                        if (err)
2885                        {
2886                            RETURN_ERROR(MAJOR, err, NO_MSG);
2887                        }
2888               break;
2889               default:
2890                    RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME"));
2891            }
2892        }
2893        if (requiredAction & UPDATE_KG_NIA_CC_WA)
2894        {
2895            if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC)
2896            {
2897                tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2898                intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2899                WriteKgarWait(p_FmPcd, tmpKgarReg);
2900                tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2901                ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
2902                tmpReg32 &= ~NIA_FM_CTL_AC_CC;
2903                WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC);
2904                /* call indirect command for scheme write */
2905                tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2906                WriteKgarWait(p_FmPcd, tmpKgarReg);
2907                KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2908           }
2909        }
2910        if (requiredAction & UPDATE_KG_OPT_MODE)
2911        {
2912            tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2913            intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2914            WriteKgarWait(p_FmPcd, tmpKgarReg);
2915            WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value);
2916            /* call indirect command for scheme write */
2917            tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2918            WriteKgarWait(p_FmPcd, tmpKgarReg);
2919            KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2920        }
2921        if (requiredAction & UPDATE_KG_NIA)
2922        {
2923            tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
2924            intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
2925            WriteKgarWait(p_FmPcd, tmpKgarReg);
2926            tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
2927            tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
2928            tmpReg32 |= value;
2929            WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32);
2930            /* call indirect command for scheme write */
2931            tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
2932            WriteKgarWait(p_FmPcd, tmpKgarReg);
2933            KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
2934        }
2935    }
2936
2937    UpdateRequiredActionFlag(h_Scheme, TRUE);
2938    FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction);
2939
2940    return E_OK;
2941}
2942/*********************** End of inter-module routines ************************/
2943
2944
2945/****************************************/
2946/*  API routines                        */
2947/****************************************/
2948
2949t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd,  t_FmPcdKgSchemeParams *p_SchemeParams)
2950{
2951    t_FmPcd                             *p_FmPcd;
2952    struct fman_kg_scheme_regs          schemeRegs;
2953    struct fman_kg_scheme_regs          *p_MemRegs;
2954    uint8_t                             i;
2955    t_Error                             err = E_OK;
2956    uint32_t                            tmpKgarReg;
2957    uint32_t                            intFlags;
2958    uint8_t                             physicalSchemeId, relativeSchemeId = 0;
2959    t_FmPcdKgScheme                     *p_Scheme;
2960
2961    if (p_SchemeParams->modify)
2962    {
2963        p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme;
2964        p_FmPcd = p_Scheme->h_FmPcd;
2965
2966        SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
2967        SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
2968
2969        if (!FmPcdKgIsSchemeValidSw(p_Scheme))
2970        {
2971            REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
2972                         ("Scheme is invalid"));
2973            return NULL;
2974        }
2975
2976        if (!KgSchemeFlagTryLock(p_Scheme))
2977        {
2978            DBG(TRACE, ("Scheme Try Lock - BUSY"));
2979            /* Signal to caller BUSY condition */
2980            p_SchemeParams->id.h_Scheme = NULL;
2981            return NULL;
2982        }
2983    }
2984    else
2985    {
2986        p_FmPcd = (t_FmPcd*)h_FmPcd;
2987
2988        SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
2989        SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
2990
2991        relativeSchemeId = p_SchemeParams->id.relativeSchemeId;
2992        /* check that schemeId is in range */
2993        if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
2994        {
2995            REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
2996            return NULL;
2997        }
2998
2999        p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
3000        if (FmPcdKgIsSchemeValidSw(p_Scheme))
3001        {
3002            REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
3003                         ("Scheme id (%d)!", relativeSchemeId));
3004            return NULL;
3005        }
3006        /* Clear all fields, scheme may have beed previously used */
3007        memset(p_Scheme, 0, sizeof(t_FmPcdKgScheme));
3008
3009        p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId];
3010        p_Scheme->h_FmPcd = p_FmPcd;
3011
3012        p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd);
3013        if (!p_Scheme->p_Lock)
3014            REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!"));
3015    }
3016
3017    err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs);
3018    if (err)
3019    {
3020        REPORT_ERROR(MAJOR, err, NO_MSG);
3021        if (p_SchemeParams->modify)
3022            KgSchemeFlagUnlock(p_Scheme);
3023        if (!p_SchemeParams->modify &&
3024            p_Scheme->p_Lock)
3025            FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3026        return NULL;
3027    }
3028
3029    if (p_FmPcd->h_Hc)
3030    {
3031        err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc,
3032                                 (t_Handle)p_Scheme,
3033                                 &schemeRegs,
3034                                 p_SchemeParams->schemeCounter.update);
3035        if (p_SchemeParams->modify)
3036            KgSchemeFlagUnlock(p_Scheme);
3037        if (err)
3038        {
3039            if (!p_SchemeParams->modify &&
3040                p_Scheme->p_Lock)
3041                FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3042            return NULL;
3043        }
3044        if (!p_SchemeParams->modify)
3045            ValidateSchemeSw(p_Scheme);
3046        return (t_Handle)p_Scheme;
3047    }
3048
3049    physicalSchemeId = p_Scheme->schemeId;
3050
3051    /* configure all 21 scheme registers */
3052    p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs;
3053    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3054    WRITE_UINT32(p_MemRegs->kgse_ppc,   schemeRegs.kgse_ppc);
3055    WRITE_UINT32(p_MemRegs->kgse_ccbs,  schemeRegs.kgse_ccbs);
3056    WRITE_UINT32(p_MemRegs->kgse_mode,  schemeRegs.kgse_mode);
3057    WRITE_UINT32(p_MemRegs->kgse_mv,    schemeRegs.kgse_mv);
3058    WRITE_UINT32(p_MemRegs->kgse_dv0,   schemeRegs.kgse_dv0);
3059    WRITE_UINT32(p_MemRegs->kgse_dv1,   schemeRegs.kgse_dv1);
3060    WRITE_UINT32(p_MemRegs->kgse_ekdv,  schemeRegs.kgse_ekdv);
3061    WRITE_UINT32(p_MemRegs->kgse_ekfc,  schemeRegs.kgse_ekfc);
3062    WRITE_UINT32(p_MemRegs->kgse_bmch,  schemeRegs.kgse_bmch);
3063    WRITE_UINT32(p_MemRegs->kgse_bmcl,  schemeRegs.kgse_bmcl);
3064    WRITE_UINT32(p_MemRegs->kgse_hc,    schemeRegs.kgse_hc);
3065    WRITE_UINT32(p_MemRegs->kgse_spc,   schemeRegs.kgse_spc);
3066    WRITE_UINT32(p_MemRegs->kgse_fqb,   schemeRegs.kgse_fqb);
3067    WRITE_UINT32(p_MemRegs->kgse_om,    schemeRegs.kgse_om);
3068    WRITE_UINT32(p_MemRegs->kgse_vsp,   schemeRegs.kgse_vsp);
3069    for (i=0 ; i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
3070        WRITE_UINT32(p_MemRegs->kgse_gec[i], schemeRegs.kgse_gec[i]);
3071
3072    /* call indirect command for scheme write */
3073    tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update);
3074
3075    WriteKgarWait(p_FmPcd, tmpKgarReg);
3076    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3077
3078    if (!p_SchemeParams->modify)
3079        ValidateSchemeSw(p_Scheme);
3080    else
3081        KgSchemeFlagUnlock(p_Scheme);
3082
3083    return (t_Handle)p_Scheme;
3084}
3085
3086t_Error  FM_PCD_KgSchemeDelete(t_Handle h_Scheme)
3087{
3088    t_FmPcd             *p_FmPcd;
3089    uint8_t             physicalSchemeId;
3090    uint32_t            tmpKgarReg, intFlags;
3091    t_Error             err = E_OK;
3092    t_FmPcdKgScheme     *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
3093
3094    SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE);
3095
3096    p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd);
3097
3098    UpdateRequiredActionFlag(h_Scheme, FALSE);
3099
3100    /* check that no port is bound to this scheme */
3101    err = InvalidateSchemeSw(h_Scheme);
3102    if (err)
3103        RETURN_ERROR(MINOR, err, NO_MSG);
3104
3105    if (p_FmPcd->h_Hc)
3106    {
3107        err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme);
3108        if (p_Scheme->p_Lock)
3109            FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3110        return err;
3111    }
3112
3113    physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3114
3115    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3116    /* clear mode register, including enable bit */
3117    WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0);
3118
3119    /* call indirect command for scheme write */
3120    tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
3121
3122    WriteKgarWait(p_FmPcd, tmpKgarReg);
3123    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3124
3125    if (p_Scheme->p_Lock)
3126        FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
3127
3128    return E_OK;
3129}
3130
3131uint32_t  FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme)
3132{
3133    t_FmPcd             *p_FmPcd;
3134    uint32_t            tmpKgarReg, spc, intFlags;
3135    uint8_t             physicalSchemeId;
3136
3137    SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
3138
3139    p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
3140    if (p_FmPcd->h_Hc)
3141        return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme);
3142
3143    physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3144
3145    if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
3146        REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
3147
3148    tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
3149    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3150    WriteKgarWait(p_FmPcd, tmpKgarReg);
3151    if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
3152       REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
3153    spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc);
3154    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3155
3156    return spc;
3157}
3158
3159t_Error  FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value)
3160{
3161    t_FmPcd             *p_FmPcd;
3162    uint32_t            tmpKgarReg, intFlags;
3163    uint8_t             physicalSchemeId;
3164
3165    SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
3166
3167    p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
3168
3169    if (!FmPcdKgIsSchemeValidSw(h_Scheme))
3170        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
3171
3172    if (p_FmPcd->h_Hc)
3173        return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value);
3174
3175    physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
3176    /* check that schemeId is in range */
3177    if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
3178        REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
3179
3180    /* read specified scheme into scheme registers */
3181    tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
3182    intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
3183    WriteKgarWait(p_FmPcd, tmpKgarReg);
3184    if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
3185    {
3186       KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3187       RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
3188    }
3189
3190    /* change counter value */
3191    WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value);
3192
3193    /* call indirect command for scheme write */
3194    tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
3195
3196    WriteKgarWait(p_FmPcd, tmpKgarReg);
3197    KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
3198
3199    return E_OK;
3200}
3201
3202t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset)
3203{
3204   t_FmPcd              *p_FmPcd = (t_FmPcd*)h_FmPcd;
3205   struct fman_kg_regs  *p_Regs;
3206
3207    SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
3208    SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
3209    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
3210    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
3211
3212    p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
3213    if (!FmIsMaster(p_FmPcd->h_Fm))
3214        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!"));
3215
3216    WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset);
3217
3218    return E_OK;
3219}
3220
3221t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value)
3222{
3223   t_FmPcd              *p_FmPcd = (t_FmPcd*)h_FmPcd;
3224   struct fman_kg_regs  *p_Regs;
3225
3226    SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
3227    SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE);
3228    SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
3229    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
3230    SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
3231
3232    p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
3233
3234    if (!FmIsMaster(p_FmPcd->h_Fm))
3235        RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!"));
3236
3237    if (valueId == 0)
3238        WRITE_UINT32(p_Regs->fmkg_gdv0r,value);
3239    else
3240        WRITE_UINT32(p_Regs->fmkg_gdv1r,value);
3241    return E_OK;
3242}
3243