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