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