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