drvmem.c (121845B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Memory address and field manipulations. 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <assert.h> 13 14 #include <sal/core/libc.h> 15 16 #include <soc/dnxc/multithread_analyzer.h> 17 18 #include <soc/drv.h> 19 #include <soc/mem.h> 20 #include <soc/error.h> 21 #ifdef BCM_ESW_SUPPORT 22 #include <soc/er_tcam.h> 23 #endif 24 #ifdef BCM_DFE_SUPPORT 25 #include <soc/dfe/cmn/dfe_drv.h> 26 #endif 27 #ifdef BCM_ESW_SUPPORT 28 #include <soc/format.h> 29 #endif 30 #ifdef BCM_TOMAHAWK3_SUPPORT 31 #include <soc/tomahawk3.h> 32 #endif 33 #ifdef BCM_TRIDENT3_SUPPORT 34 #include <soc/esw/flow_db.h> 35 #endif 36 37 /* 38 * save the last memory used in direct access (usually used for cache) 39 * No init required since no harm is done if invalid memory saved here. 40 * Thread safe - since the last memory used first copied to a local variable and then used. 41 */ 42 soc_mem_t drvmem_last_used_mem_direct_acc[SOC_MAX_NUM_DEVICES] = {0}; 43 44 45 /* 46 * Macro used by memory accessor functions to fix order 47 */ 48 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \ 49 BYTES2WORDS((m)->bytes)-1-(v) : \ 50 (v)) 51 52 #ifdef BCM_TRIDENT3_SUPPORT 53 /* 54 * Function: soc_meminfo_field_get_helper 55 * Purpose: Get a memory field without reference to chip. 56 * Parameters: meminfo -- direct reference to memory description 57 */ 58 STATIC uint32 * 59 soc_meminfo_field_get_helper(soc_mem_info_t *meminfo, 60 const uint32 *entbuf, 61 soc_field_info_t *fieldinfo, 62 uint32 *fldbuf, uint32 fldbuf_size) 63 { 64 int len; 65 66 assert(fieldinfo); 67 68 len = fieldinfo->len; 69 assert(len / 32 <= fldbuf_size); /* assert we do not write beyond the end of the output buffer */ 70 71 return soc_meminfo_fieldinfo_field_get(entbuf, 72 meminfo, 73 fieldinfo, 74 fldbuf); 75 } 76 #endif 77 78 /* 79 * Function: _soc_field_value_fit 80 * Purpose: Check if value will fit into a memory field. 81 * Parameters: fieldinfo -- (IN)Direct reference to field description. 82 * value -- (IN)Value to be checked. 83 * Returns: 84 * TRUE - buffer fits into the field. 85 * FALSE - Otherwise. 86 */ 87 STATIC int 88 _soc_field_value_fit(soc_field_info_t *fieldinfo, uint32 *value) 89 { 90 uint32 mask; /* Value mask */ 91 uint16 len; /* Bits in field */ 92 int idx; /* Iteration index. */ 93 94 idx = (fieldinfo->len - 1) >> 5; 95 len = fieldinfo->len % 32; 96 97 if (!len) { 98 return TRUE; 99 } 100 101 mask = (1 << len) - 1; 102 if((value[idx] & ~mask) != 0) { 103 return (FALSE); 104 } 105 return (TRUE); 106 } 107 108 109 #ifdef BCM_TRIDENT3_SUPPORT 110 111 /* 112 * Function: _soc_mem_view_sub_field_set 113 * Purpose: Write to a sub field specified by the start and end positions 114 * to the given user field. 115 * 116 * Parameters: usr_field -- the given user field that sub field written to 117 * pos_min -- the start bit position in the given field. 118 * pos_max -- The end bit position in the given field. 119 * frag_field -- point to the sub_field value 120 * Returns: 121 * SOC_E_XXX. 122 */ 123 124 STATIC int 125 _soc_mem_view_sub_field_set(uint32 *usr_field, 126 int pos_min, int pos_max, 127 uint32 *frag_field) 128 { 129 int i; 130 int word_start; 131 int bit_start; 132 int bit_end; 133 int word_num; 134 int r_shifter; 135 int l_shifter; 136 int last_idx; 137 138 word_start = pos_min/32; 139 bit_start = pos_min%32; 140 bit_end = pos_max%32; 141 word_num = pos_max/32 - pos_min/32; 142 l_shifter = bit_start; 143 r_shifter = 32 - l_shifter; 144 145 /* safety check */ 146 if (pos_min > pos_max) { 147 return SOC_E_INTERNAL; 148 } 149 /* frag_field must have exact number of bits value. extra bits 150 * in the 32-bit word must be cleared 151 */ 152 if ((pos_max - pos_min + 1)%32) { 153 frag_field[(pos_max - pos_min + 1)/32] &= 154 ((1 << ((pos_max - pos_min + 1)%32)) - 1); 155 } 156 for (last_idx = 0, i = 0; i < word_num; i++) { 157 usr_field[word_start + i] |= (frag_field[i] << l_shifter); 158 if (l_shifter) { 159 usr_field[word_start + i + 1] |= (frag_field[i] >> r_shifter); 160 } 161 last_idx = i + 1; 162 } 163 if (bit_end >= l_shifter) { 164 usr_field[word_start + last_idx] |= (frag_field[last_idx] << 165 l_shifter); 166 } 167 return SOC_E_NONE; 168 } 169 170 /* 171 * Function: _soc_mem_view_sub_field_get 172 * Purpose: Retrieve a sub field specified by the start and end positions of 173 * the given user field. 174 * 175 * Parameters: usr_field -- the given user field that sub field resides in 176 * pos_min -- the start bit position in the given field. 177 * pos_max -- the end bit position in the given field. 178 * frag_field -- point to the retrieved sub_field value 179 * Returns: 180 * SOC_E_XXX. 181 */ 182 183 STATIC int 184 _soc_mem_view_sub_field_get(uint32 *usr_field, int pos_min, 185 int pos_max, uint32 *frag_field) 186 { 187 int i; 188 uint32 mask; 189 int last_idx; 190 int word_start; 191 int bit_start; 192 int bit_end; 193 int word_num; 194 int r_shifter; 195 int l_shfter; 196 197 word_start = pos_min/32; 198 bit_start = pos_min%32; 199 bit_end = pos_max%32; 200 word_num = pos_max/32 - pos_min/32; 201 r_shifter = bit_start; 202 l_shfter = 32 - r_shifter; 203 204 /* safety check */ 205 if (pos_min > pos_max) { 206 return SOC_E_INTERNAL; 207 } 208 for (i = 0; i < word_num; i++) { 209 frag_field[i] = usr_field[word_start + i] >> r_shifter; 210 if (r_shifter) { 211 frag_field[i] |= usr_field[word_start + i + 1] << l_shfter; 212 } 213 } 214 last_idx = i - 1; 215 if (r_shifter > bit_end) { 216 /* last_idx < 0 should never happen if r_shifter > bit_end */ 217 if (last_idx >= 0) { /* safety check */ 218 mask = ((uint32)0xFFFFFFFF) >> (r_shifter - (bit_end + 1)); 219 frag_field[last_idx] &= mask; 220 } 221 } else { 222 mask = ((uint32)0xFFFFFFFF) >> (31 - (bit_end - r_shifter)); 223 frag_field[last_idx+1] = (usr_field[word_start + last_idx + 1] >> 224 r_shifter) & mask; 225 } 226 return SOC_E_NONE; 227 } 228 229 /* 230 * Function: _soc_mem_view_field_set 231 * Purpose: Set a memory field (of a memory view) 232 * Parameters: unit - device 233 * mem_view - mem view 234 * entbuf - table entry buffer 235 * field - which field to set 236 * fldbuf - field buffer 237 */ 238 STATIC void 239 _soc_mem_view_field_set(int unit, soc_mem_t mem_view, uint32 *entbuf, soc_field_t field, 240 uint32 *fldbuf) 241 { 242 int rv = SOC_E_NONE; 243 soc_mem_t phy_mem; 244 soc_field_info_t fieldinfo; 245 soc_mem_view_split_field_info_t *sf_info; /* split field info */ 246 soc_mem_info_t *meminfo; 247 uint32 *val_field; 248 int i; 249 char *buf_ptr; 250 int alloc_size; 251 252 if (!soc_feature(unit, soc_feature_flex_flow)) { 253 return; 254 } 255 256 if (!SOC_MEM_IS_VIEW(unit, mem_view)) { 257 return; 258 } 259 260 rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 261 if (rv != SOC_E_NONE) { 262 return; 263 } 264 meminfo = &SOC_MEM_INFO(unit, phy_mem); 265 266 /* check if it is virtual field */ 267 rv = soc_flow_db_mem_view_field_is_virtual(unit, mem_view,field); 268 269 if (rv) { 270 271 /* use malloc to avoid coverity stack overflow issue */ 272 alloc_size = sizeof(soc_mem_view_split_field_info_t); 273 alloc_size += SOC_MAX_MEM_WORDS * sizeof(uint32); 274 275 buf_ptr = sal_alloc(alloc_size, "Temp buffer for _soc_mem_view_field_set"); 276 sal_memset((void *)buf_ptr,0,alloc_size); 277 sf_info = (soc_mem_view_split_field_info_t *)buf_ptr; 278 val_field = (uint32 *)(sf_info + 1); 279 280 rv = soc_mem_view_split_field_info_get(unit,mem_view,field,sf_info); 281 if (rv != SOC_E_NONE) { 282 sal_free(buf_ptr); 283 return; 284 } 285 286 for (i = 0; i < sf_info->num_fld; i++) { 287 rv = _soc_mem_view_sub_field_get(fldbuf, 288 sf_info->fld[i].v_offset, 289 sf_info->fld[i].field.len + sf_info->fld[i].v_offset - 1, 290 val_field); 291 if (rv != SOC_E_NONE) { 292 sal_free(buf_ptr); 293 return; 294 } 295 soc_meminfo_fieldinfo_field_set(entbuf, meminfo, 296 &sf_info->fld[i].field, val_field); 297 } 298 sal_free(buf_ptr); 299 300 } else { 301 sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo)); 302 rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo); 303 if (rv != SOC_E_NONE) { 304 return; 305 } 306 soc_meminfo_fieldinfo_field_set(entbuf, meminfo, &fieldinfo, fldbuf); 307 } 308 309 return; 310 } 311 312 /* 313 * Function: _soc_mem_view_field_get 314 * Purpose: Get a memory field 315 * Parameters: unit - device 316 * mem_view - table 317 * entbuf - table entry buffer 318 * field - which field to get 319 * fldbuf - field buffer 320 */ 321 STATIC uint32* 322 _soc_mem_view_field_get(int unit, soc_mem_t mem_view, const uint32 *entbuf, 323 soc_field_t field, uint32 *fldbuf, uint32 words) 324 { 325 int rv = SOC_E_NONE; 326 soc_mem_t phy_mem; 327 soc_field_info_t fieldinfo; 328 soc_mem_info_t *meminfo; 329 uint32 *val_field; 330 soc_mem_view_split_field_info_t *sf_info; /* split field info */ 331 int i; 332 int fld_word_len; 333 char *buf_ptr; 334 int alloc_size; 335 336 if (!soc_feature(unit, soc_feature_flex_flow)) { 337 return fldbuf; 338 } 339 340 if (!SOC_MEM_IS_VIEW(unit, mem_view)) { 341 return fldbuf; 342 } 343 344 rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 345 if (rv != SOC_E_NONE) { 346 return fldbuf; 347 } 348 349 rv = soc_flow_db_mem_view_field_is_virtual(unit, mem_view,field); 350 351 if (rv) { 352 353 /* use malloc to avoid coverity stack overflow issue */ 354 alloc_size = sizeof(soc_mem_view_split_field_info_t); 355 alloc_size += SOC_MAX_MEM_WORDS * sizeof(uint32); 356 357 buf_ptr = sal_alloc(alloc_size, "Temp buffer for _soc_mem_view_field_get"); 358 sal_memset((void *)buf_ptr,0,alloc_size); 359 sf_info = (soc_mem_view_split_field_info_t *)buf_ptr; 360 val_field = (uint32 *)(sf_info + 1); 361 362 rv = soc_mem_view_split_field_info_get(unit,mem_view,field,sf_info); 363 if (rv != SOC_E_NONE) { 364 sal_free(buf_ptr); 365 return fldbuf; 366 } 367 368 /* initialize the fldbuf */ 369 fld_word_len = (sf_info->width + 31)/32; 370 assert (fld_word_len <= words); 371 for (i = 0; i < fld_word_len; i++) { 372 fldbuf[i] = 0; 373 } 374 meminfo = &SOC_MEM_INFO(unit, phy_mem); 375 376 for (i = 0; i < sf_info->num_fld; i++) { 377 (void)soc_meminfo_field_get_helper(meminfo, entbuf, &sf_info->fld[i].field, 378 val_field, words); 379 380 rv = _soc_mem_view_sub_field_set(fldbuf, sf_info->fld[i].v_offset, 381 sf_info->fld[i].v_offset + sf_info->fld[i].field.len - 1, 382 val_field); 383 if (rv != SOC_E_NONE) { 384 sal_free(buf_ptr); 385 return fldbuf; 386 } 387 } 388 sal_free(buf_ptr); 389 390 } else { 391 392 sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo)); 393 rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo); 394 if (rv != SOC_E_NONE) { 395 return fldbuf; 396 } 397 398 meminfo = &SOC_MEM_INFO(unit, phy_mem); 399 return soc_meminfo_field_get_helper(meminfo, entbuf, &fieldinfo, fldbuf, words); 400 } 401 return fldbuf; 402 } 403 404 /* 405 * Function: 406 * _soc_mem_view_field_valid 407 * Purpose: 408 * Verify if field is valid & present in memory view 409 * Parameters: 410 * mem_view - (IN)Memory view id 411 * field - (IN)Field id. 412 * Return: 413 * TRUE -If field is present & valid. 414 * FALSE -Otherwise. 415 */ 416 STATIC int 417 _soc_mem_view_field_valid(int unit, soc_mem_t mem_view, soc_field_t field) 418 { 419 return soc_mem_view_field_valid(unit, mem_view, field); 420 } 421 422 /* 423 * Function: 424 * _soc_mem_view_field32_fit 425 * Purpose: 426 * Check if uint32 value fits into a memory view field. 427 * Parameters: 428 * unit - (IN)SOC unit number. 429 * mem - (IN)Memory view id. 430 * field - (IN)Field id. 431 * value - (IN)Value to be checked. 432 * Return: 433 * SOC_E_PARAM -If value is too big for field, or some other error. 434 * SOC_E_NONE -Otherwise. 435 */ 436 STATIC int 437 _soc_mem_view_field32_fit(int unit, soc_mem_t mem_view, 438 soc_field_t field, uint32 value) 439 { 440 int rv = SOC_E_NONE; 441 soc_mem_t phy_mem; 442 soc_field_info_t fieldinfo; 443 444 rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 445 if (rv != SOC_E_NONE) { 446 return rv; 447 } 448 449 sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo)); 450 rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo); 451 if (rv != SOC_E_NONE) { 452 return rv; 453 } 454 455 return (_soc_field_value_fit(&fieldinfo, &value)) ? 456 SOC_E_NONE : SOC_E_PARAM; 457 } 458 459 /* 460 * Function: 461 * _soc_mem_view_field_length 462 * Purpose: 463 * the length of a memory view field in bits. 464 * Parameters: 465 * unit - (IN)SOC unit number. 466 * mem - (IN)Memory view id. 467 * field - (IN)Field id. 468 * Return: 469 * bits in field. 470 * 0 if the field is not found. 471 */ 472 STATIC int 473 _soc_mem_view_field_length(int unit, soc_mem_t mem_view, soc_field_t field) 474 { 475 int rv = SOC_E_NONE; 476 soc_field_info_t fieldinfo; 477 478 sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo)); 479 rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo); 480 if (rv != SOC_E_NONE) { 481 return 0; 482 } 483 return fieldinfo.len; 484 } 485 486 /* 487 * Function: _soc_mem_view_fields32_modify 488 * Purpose: Modify the value of a fields in a memory view 489 * Parameters: 490 * unit - (IN) SOC unit number. 491 * mem - (IN) Memory view 492 * index - (IN) Memory entry index. 493 * field_count - (IN) Number of fields to modify. 494 * fields - (IN) Modified fields array. 495 * values - (IN) New value for each member of fields array. 496 * Returns: 497 * SOC_E_XXX 498 */ 499 int 500 _soc_mem_view_fields32_modify(int unit, soc_mem_t mem_view, int index, 501 int field_count, soc_field_t *fields, uint32 *values) 502 { 503 uint32 buf[SOC_MAX_MEM_WORDS]; /* Buffer to read memory entry. */ 504 int idx; /* Iteration index. */ 505 int rv; /* Operation return status. */ 506 int value_changed = 0; /* Flag of value changed comparing 507 between input and current reading*/ 508 soc_mem_t phy_mem; 509 510 /* Field count check before continue. */ 511 if (field_count == 0) { 512 return (SOC_E_NONE); 513 } 514 515 rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem); 516 if (rv != SOC_E_NONE) { 517 return rv; 518 } 519 520 /* Check entry index range. */ 521 if ((index > soc_mem_index_max(unit, phy_mem)) || 522 (index < soc_mem_index_min(unit, phy_mem))) { 523 return (SOC_E_PARAM); 524 } 525 526 /* Fields & values sanity check. */ 527 for (idx = 0; idx < field_count; idx++) { 528 if ((NULL == fields + idx) || (NULL == values + idx)) { 529 /* 530 * COVERITY 531 * This is kept intentional for future use 532 * or as defensive statement. 533 */ 534 /* coverity[dead_error_line] */ 535 return (SOC_E_PARAM); 536 } 537 538 /* Make sure value fits into memory field. */ 539 SOC_IF_ERROR_RETURN 540 (soc_mem_field32_fit(unit, mem_view, fields[idx], values[idx])); 541 } 542 543 /* Lock the memory. */ 544 soc_mem_lock(unit, phy_mem); 545 rv = soc_mem_read(unit, mem_view, MEM_BLOCK_ANY, index, buf); 546 if (SOC_FAILURE(rv)) { 547 soc_mem_unlock(unit, phy_mem); 548 return (rv); 549 } 550 551 /* Set updated values in the buffer. */ 552 for (idx = 0; idx < field_count; idx ++) { 553 if(values[idx] != soc_mem_field32_get(unit, mem_view, buf, fields[idx])) { 554 value_changed = 1; 555 soc_mem_field32_set(unit, mem_view, buf, fields[idx], values[idx]); 556 } 557 } 558 559 /* Write buffer back to memory. */ 560 if(value_changed) { 561 rv = soc_mem_write(unit, mem_view, MEM_BLOCK_ALL, index, buf); 562 } 563 564 soc_mem_unlock(unit, phy_mem); 565 return (rv); 566 } 567 #endif 568 569 /* 570 * Function: soc_mem_field_length 571 * Purpose: Return the length of a memory field in bits. 572 * Value is 0 if field is not found. 573 * Returns: bits in field 574 */ 575 int 576 soc_mem_field_length(int unit, soc_mem_t mem, soc_field_t field) 577 { 578 soc_field_info_t *fld; 579 580 #ifdef BCM_TRIDENT3_SUPPORT 581 if (soc_feature(unit, soc_feature_flex_flow)) { 582 if (SOC_MEM_IS_VIEW(unit, mem)) { 583 return _soc_mem_view_field_length(unit, mem, field); 584 } 585 } 586 #endif 587 588 SOC_FIND_FIELD(field, 589 SOC_MEM_INFO(unit, mem).fields, 590 SOC_MEM_INFO(unit, mem).nFields, 591 fld); 592 if (fld == NULL) { 593 return 0; 594 } 595 return fld->len; 596 } 597 598 /**************************************************************** 599 * 600 * MEMORY ENTRY VALUE MANIPULATION FUNCTIONS 601 */ 602 603 /* 604 * Function: soc_memacc_get 605 * Purpose: Get a (memory, field) access information structure 606 * Parameters: unit - device 607 * mem - table 608 * field - which field to get 609 * memacc - (OUT) Memory access structure 610 */ 611 int 612 soc_memacc_init(int unit, soc_mem_t mem, soc_field_t fld, 613 soc_memacc_t *memacc) 614 { 615 soc_mem_info_t *meminfo; 616 soc_field_info_t *finfop; 617 618 if (!SOC_MEM_IS_VALID(unit, mem)) { 619 return SOC_E_PARAM; 620 } 621 622 meminfo = &SOC_MEM_INFO(unit, mem); 623 624 SOC_FIND_FIELD(fld, 625 meminfo->fields, 626 meminfo->nFields, 627 finfop); 628 629 if (finfop == NULL) { 630 return SOC_E_PARAM; 631 } 632 633 memacc->minfo = meminfo; 634 memacc->finfo = finfop; 635 636 return SOC_E_NONE; 637 } 638 639 /* 640 * Function: soc_memacc_field_get 641 * Purpose: Get a memory field without reference to chip. 642 * Parameters: memacc - Memory access structure 643 */ 644 uint32 * 645 soc_memacc_field_get(soc_memacc_t *memacc, const uint32 *entbuf, 646 uint32 *fldbuf) 647 { 648 soc_mem_info_t *meminfo = memacc->minfo; 649 soc_field_info_t *fieldinfo = memacc->finfo; 650 int i, wp, bp, len; 651 652 bp = fieldinfo->bp; 653 len = fieldinfo->len; 654 655 if (len == 1) { /* special case single bits */ 656 wp = bp / 32; 657 bp = bp & (32 - 1); 658 if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) { 659 fldbuf[0] = 1; 660 } else { 661 fldbuf[0] = 0; 662 } 663 return fldbuf; 664 } 665 666 if (fieldinfo->flags & SOCF_LE) { 667 wp = bp / 32; 668 bp = bp & (32 - 1); 669 i = 0; 670 671 for (; len > 0; len -= 32) { 672 if (bp) { 673 fldbuf[i] = 674 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp & 675 ((1 << (32 - bp)) - 1); 676 if ( len > (32 - bp) ) { 677 fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] << 678 (32 - bp); 679 } 680 } else { 681 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)]; 682 } 683 684 if (len < 32) { 685 fldbuf[i] &= ((1 << len) - 1); 686 } 687 688 i++; 689 } 690 } else { 691 i = (len - 1) / 32; 692 693 while (len > 0) { 694 assert(i >= 0); 695 696 fldbuf[i] = 0; 697 698 do { 699 fldbuf[i] = 700 (fldbuf[i] << 1) | 701 ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >> 702 (bp & (32 - 1))) & 1); 703 len--; 704 bp++; 705 } while (len & (32 - 1)); 706 707 i--; 708 } 709 } 710 711 return fldbuf; 712 } 713 714 uint32 715 soc_memacc_field32_get(soc_memacc_t *memacc, void *entry) 716 { 717 uint32 value; 718 719 /* 720 * COVERITY 721 * 722 * We do this intentionally to use the generic function 723 * soc_memacc_field_get() which does the necessary handling. 724 */ 725 /* coverity[address_of] */ 726 /* coverity[callee_ptr_arith] */ 727 soc_memacc_field_get(memacc, entry, &value); 728 729 return value; 730 } 731 732 void 733 soc_memacc_field64_get(soc_memacc_t *memacc, void *entry, uint64 *val64) 734 { 735 uint32 val64_field[2] = {0, 0}; 736 737 soc_memacc_field_get(memacc, entry, val64_field); 738 739 COMPILER_64_SET(*val64, val64_field[1], val64_field[0]); 740 } 741 742 /* 743 * Function: soc_memacc_mac_addr_get 744 * Purpose: Get a mac address field in a memory from a mac addr type 745 * Returns: SOC_E_xxx 746 */ 747 void 748 soc_memacc_mac_addr_get(soc_memacc_t *memacc, void *entry, sal_mac_addr_t mac) 749 { 750 uint32 mac_field[2]; 751 752 soc_memacc_field_get(memacc, entry, mac_field); 753 754 SAL_MAC_ADDR_FROM_UINT32(mac, mac_field); 755 } 756 757 /* 758 * Function: soc_mem_fieldinfo_get 759 * Purpose: Get a memory field's fieldinfo reference. 760 * Parameters: unit - device 761 * mem - table 762 * field - which field to get 763 * NB: 764 * This function is designed for cases where many entries of the 765 * same table and fields are processed in a batch, such as 766 * for traverse functions and tables of counter values. It provides 767 * the necessary info structure for using 768 * soc_mem_fieldinfo_field_get below. 769 */ 770 soc_field_info_t * 771 soc_mem_fieldinfo_get(int unit, soc_mem_t mem, soc_field_t field) 772 { 773 soc_mem_info_t *meminfo; 774 soc_field_info_t *finfop; /* Field information structure. */ 775 776 /* Verify that memory is present on the device. */ 777 if (!SOC_MEM_IS_VALID(unit, mem)) { 778 return NULL; 779 } 780 781 meminfo = &SOC_MEM_INFO(unit, mem); 782 SOC_FIND_FIELD(field, 783 meminfo->fields, 784 meminfo->nFields, 785 finfop); 786 787 return finfop; 788 } 789 790 /* 791 * Function: soc_meminfo_fieldinfo_field_get 792 * Purpose: Get a memory field without reference to chip. 793 * Parameters: meminfo -- direct reference to memory description 794 * fieldinfo -- direct reference to field description 795 * NB: 796 * Callee must verify that the requested memory and 797 * field specification are valid on the device from which the 798 * entry was read. 799 * This function is designed for cases where many entries of the 800 * same table and fields are processed in a batch, such as 801 * for traverse functions and tables of counter values. 802 */ 803 uint32 * 804 soc_meminfo_fieldinfo_field_get(const uint32 *entbuf, 805 soc_mem_info_t *meminfo, 806 soc_field_info_t *fieldinfo, 807 uint32 *fldbuf) 808 { 809 int i, wp, bp, len; 810 811 bp = fieldinfo->bp; 812 len = fieldinfo->len; 813 814 if (len == 1) { /* special case single bits */ 815 wp = bp / 32; 816 bp = bp & (32 - 1); 817 if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) { 818 fldbuf[0] = 1; 819 } else { 820 fldbuf[0] = 0; 821 } 822 return fldbuf; 823 } 824 825 if (fieldinfo->flags & SOCF_LE) { 826 wp = bp / 32; 827 bp = bp & (32 - 1); 828 i = 0; 829 830 for (; len > 0; len -= 32) { 831 if (bp) { 832 fldbuf[i] = 833 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp & 834 ((1 << (32 - bp)) - 1); 835 if ( len > (32 - bp) ) { 836 fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] << 837 (32 - bp); 838 } 839 } else { 840 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)]; 841 } 842 843 if (len < 32) { 844 fldbuf[i] &= ((1 << len) - 1); 845 } 846 847 i++; 848 } 849 } else { 850 i = (len - 1) / 32; 851 852 while (len > 0) { 853 assert(i >= 0); 854 855 fldbuf[i] = 0; 856 857 do { 858 fldbuf[i] = 859 (fldbuf[i] << 1) | 860 ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >> 861 (bp & (32 - 1))) & 1); 862 len--; 863 bp++; 864 } while (len & (32 - 1)); 865 866 i--; 867 } 868 } 869 870 return fldbuf; 871 } 872 873 /* 874 * Function: soc_meminfo_fieldinfo_field32_get 875 * Purpose: Get a <=32 bit field out of a memory entry 876 * Returns: The value of the field 877 */ 878 uint32 879 soc_meminfo_fieldinfo_field32_get(soc_mem_info_t *meminfo, 880 void *entry, 881 soc_field_info_t *fieldinfo) 882 { 883 uint32 value; 884 885 /* 886 * COVERITY 887 * 888 * We do this intentionally to use the generic function 889 * soc_meminfo_fieldinfo_field_get() which does the necessary handling. 890 */ 891 /* coverity[address_of] */ 892 /* coverity[callee_ptr_arith] */ 893 soc_meminfo_fieldinfo_field_get(entry, meminfo, fieldinfo, &value); 894 895 return value; 896 } 897 898 /* 899 * Function: 900 * soc_meminfo_fieldinfo_field64_get 901 * Purpose: 902 * Get a field in a memory for a uint64 type 903 * Parameters: 904 * unit - (IN) BCM device number. 905 * meminfo - (IN) direct reference to memory description 906 * entry - (IN) HW entry buffer. 907 * fieldinfo - direct reference to field description - (IN) 908 * val64 - (OUT) SW uint64 field buffer. 909 * Returns: void 910 */ 911 void 912 soc_meminfo_fieldinfo_field64_get(soc_mem_info_t *meminfo, 913 void *entry, 914 soc_field_info_t *fieldinfo, 915 uint64 *val64) 916 { 917 uint32 val64_field[2] = {0, 0}; 918 919 soc_meminfo_fieldinfo_field_get(entry, meminfo, 920 fieldinfo, val64_field); 921 922 COMPILER_64_SET(*val64, val64_field[1], val64_field[0]); 923 } 924 925 /* 926 * Function: soc_meminfo_field_get 927 * Purpose: Get a memory field without reference to chip. 928 * Parameters: meminfo -- direct reference to memory description 929 */ 930 uint32 * 931 soc_meminfo_field_get(soc_mem_t mem, soc_mem_info_t *meminfo, 932 const uint32 *entbuf, soc_field_t field, uint32 *fldbuf, 933 uint32 fldbuf_size) /* The number of uint32s in fldbuf */ 934 { 935 soc_field_info_t *fieldinfo; 936 int i, wp, bp, len; 937 938 SOC_FIND_FIELD(field, 939 meminfo->fields, 940 meminfo->nFields, 941 fieldinfo); 942 if (NULL == fieldinfo) { 943 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 944 LOG_CLI((BSL_META("mem %s field %s is invalid\n"), 945 soc_mem_name[mem], soc_fieldnames[field])); 946 #endif 947 assert(fieldinfo); 948 } 949 950 /* 951 * COVERITY 952 * 953 * assert validates the input for NULL 954 */ 955 /* coverity[var_deref_op : FALSE] */ 956 bp = fieldinfo->bp; 957 len = fieldinfo->len; 958 assert(len / 32 <= fldbuf_size); /* assert we do not write beyond the end of the output buffer */ 959 960 if (len == 1) { /* special case single bits */ 961 wp = bp / 32; 962 bp = bp & (32 - 1); 963 if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) { 964 fldbuf[0] = 1; 965 } else { 966 fldbuf[0] = 0; 967 } 968 return fldbuf; 969 } 970 971 if (fieldinfo->flags & SOCF_LE) { 972 wp = bp / 32; 973 bp = bp & (32 - 1); 974 i = 0; 975 976 for (; len > 0; len -= 32) { 977 if (bp) { 978 fldbuf[i] = 979 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp & 980 ((1 << (32 - bp)) - 1); 981 if ( len > (32 - bp) ) { 982 fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] << 983 (32 - bp); 984 } 985 } else { 986 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)]; 987 } 988 989 if (len < 32) { 990 fldbuf[i] &= ((1 << len) - 1); 991 } 992 993 i++; 994 } 995 } else { 996 i = (len - 1) / 32; 997 998 while (len > 0) { 999 assert(i >= 0); 1000 1001 fldbuf[i] = 0; 1002 1003 do { 1004 fldbuf[i] = 1005 (fldbuf[i] << 1) | 1006 ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >> 1007 (bp & (32 - 1))) & 1); 1008 len--; 1009 bp++; 1010 } while (len & (32 - 1)); 1011 1012 i--; 1013 } 1014 } 1015 1016 return fldbuf; 1017 } 1018 1019 /* 1020 * Function: _soc_field_value_chop 1021 * Purpose: Chop field value so it will fit into a memory field. 1022 * Parameters: fieldinfo -- (IN)Direct reference to field description. 1023 * value -- (IN)Value to be checked. 1024 * Returns: 1025 * SOC_E_XXX 1026 */ 1027 STATIC int 1028 _soc_field_value_chop(soc_field_info_t *fieldinfo, uint32 *value) 1029 { 1030 uint32 mask; /* Value mask */ 1031 uint16 len; /* Bits in field */ 1032 int idx; /* Iteration index. */ 1033 1034 if ((NULL == fieldinfo) || (NULL == value)) { 1035 return (SOC_E_PARAM); 1036 } 1037 1038 idx = (fieldinfo->len - 1) >> 5; 1039 len = fieldinfo->len % 32; 1040 1041 if (len) { 1042 mask = (1 << len) - 1; 1043 value[idx] &= mask; 1044 } 1045 return (SOC_E_NONE); 1046 } 1047 1048 /* 1049 * Function: 1050 * soc_mem_field_pbmp_fit 1051 * Purpose: 1052 * Check if pbmp fits into a memory field. 1053 * Parameters: 1054 * unit - (IN)SOC unit number. 1055 * mem - (IN)Memory id. 1056 * field - (IN)Field id. 1057 * value - (IN)Value to be checked. 1058 * Return: 1059 * SOC_E_PARAM -If value is too big for field, or some other error. 1060 * SOC_E_NONE -Otherwise. 1061 */ 1062 int 1063 soc_mem_field_pbmp_fit(int unit, soc_mem_t mem, 1064 soc_field_t field, uint32 *value) 1065 { 1066 soc_mem_info_t *meminfo; 1067 soc_field_info_t *fieldinfo; 1068 1069 /* Get memory info. */ 1070 if (!SOC_MEM_IS_VALID(unit, mem)){ 1071 return SOC_E_PARAM; 1072 } 1073 meminfo = &SOC_MEM_INFO(unit, mem); 1074 1075 /* Get field properties. */ 1076 SOC_FIND_FIELD(field, 1077 meminfo->fields, 1078 meminfo->nFields, 1079 fieldinfo); 1080 if (!fieldinfo) { 1081 return SOC_E_PARAM; 1082 } 1083 1084 return (_soc_field_value_fit(fieldinfo, value)) ? SOC_E_NONE : SOC_E_PARAM; 1085 } 1086 1087 /* 1088 * Function: 1089 * soc_mem_field32_fit 1090 * Purpose: 1091 * Check if uint32 value fits into a memory field. 1092 * Parameters: 1093 * unit - (IN)SOC unit number. 1094 * mem - (IN)Memory id. 1095 * field - (IN)Field id. 1096 * value - (IN)Value to be checked. 1097 * Return: 1098 * SOC_E_PARAM -If value is too big for field, or some other error. 1099 * SOC_E_NONE -Otherwise. 1100 */ 1101 int 1102 soc_mem_field32_fit(int unit, soc_mem_t mem, 1103 soc_field_t field, uint32 value) 1104 { 1105 soc_mem_info_t *meminfo; 1106 soc_field_info_t *fieldinfo; 1107 1108 #ifdef BCM_TRIDENT3_SUPPORT 1109 if (soc_feature(unit, soc_feature_flex_flow)) { 1110 if (SOC_MEM_IS_VIEW(unit, mem)) { 1111 return _soc_mem_view_field32_fit(unit, mem, field, value); 1112 } 1113 } 1114 #endif 1115 1116 /* Get memory info. */ 1117 if (!SOC_MEM_IS_VALID(unit, mem)){ 1118 return SOC_E_PARAM; 1119 } 1120 meminfo = &SOC_MEM_INFO(unit, mem); 1121 1122 /* Get field properties. */ 1123 SOC_FIND_FIELD(field, 1124 meminfo->fields, 1125 meminfo->nFields, 1126 fieldinfo); 1127 if (!fieldinfo) { 1128 return (SOC_E_PARAM); 1129 } 1130 1131 /* coverity[callee_ptr_arith : FALSE] */ 1132 return (_soc_field_value_fit(fieldinfo, &value)) ? 1133 SOC_E_NONE : SOC_E_PARAM; 1134 } 1135 1136 /* 1137 * Function: soc_memacc_field_set 1138 * Purpose: Set a <=32 bit field out of a memory entry 1139 */ 1140 void 1141 soc_memacc_field_set(soc_memacc_t *memacc, uint32 *entbuf, uint32 *fldbuf) 1142 { 1143 soc_mem_info_t *meminfo = memacc->minfo; 1144 soc_field_info_t *fieldinfo = memacc->finfo; 1145 uint32 mask; 1146 int i, wp, bp, len; 1147 1148 if (NULL == fieldinfo) { 1149 assert(fieldinfo); 1150 } 1151 1152 /* Make sure value fits into the field. */ 1153 /* 1154 * COVERITY 1155 * 1156 * assert validates the input for NULL 1157 */ 1158 /* coverity[var_deref_model : FALSE] */ 1159 if (!_soc_field_value_fit(fieldinfo, fldbuf)) { 1160 assert(_soc_field_value_fit(fieldinfo, fldbuf)); 1161 } 1162 1163 bp = fieldinfo->bp; 1164 1165 if (fieldinfo->flags & SOCF_LE) { 1166 wp = bp / 32; 1167 bp = bp & (32 - 1); 1168 i = 0; 1169 1170 for (len = fieldinfo->len; len > 0; len -= 32) { 1171 if (bp) { 1172 if (len < 32) { 1173 mask = (1 << len) - 1; 1174 } else { 1175 mask = -1; 1176 } 1177 1178 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp); 1179 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 1180 if (len > (32 - bp)) { 1181 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= 1182 ~(mask >> (32 - bp)); 1183 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |= 1184 fldbuf[i] >> (32 - bp) & ((1 << bp) - 1); 1185 } 1186 } else { 1187 if (len < 32) { 1188 mask = (1 << len) - 1; 1189 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask; 1190 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= 1191 fldbuf[i] << bp; 1192 } else { 1193 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i]; 1194 } 1195 } 1196 1197 i++; 1198 } 1199 } else { /* Big endian: swap bits */ 1200 len = fieldinfo->len; 1201 1202 while (len > 0) { 1203 len--; 1204 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= 1205 ~(1 << (bp & (32-1))); 1206 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |= 1207 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1)); 1208 bp++; 1209 } 1210 } 1211 } 1212 /* 1213 * Function: soc_memacc_field32_set 1214 * Purpose: Set a <=32 bit field out of a memory entry 1215 */ 1216 void 1217 soc_memacc_field32_set(soc_memacc_t *memacc, void *entry, uint32 value) 1218 { 1219 /* 1220 * COVERITY 1221 * 1222 * We do this intentionally to use the generic function 1223 * soc_memacc_field_set() which does the necessary handling. 1224 */ 1225 /* coverity[address_of] */ 1226 /* coverity[callee_ptr_arith] */ 1227 soc_memacc_field_set(memacc, entry, &value); 1228 } 1229 1230 /* 1231 * Function: soc_memacc_field64_set 1232 * Purpose: Set a <=64 bit field out of a memory entry 1233 */ 1234 void 1235 soc_memacc_field64_set(soc_memacc_t *memacc, void *entry, uint64 val64) 1236 { 1237 uint32 val64_field[2]; 1238 1239 val64_field[0] = COMPILER_64_LO(val64); 1240 val64_field[1] = COMPILER_64_HI(val64); 1241 1242 soc_memacc_field_set(memacc, entry, val64_field); 1243 } 1244 1245 /* 1246 * Function: soc_memacc_mac_addr_set 1247 * Purpose: Set a mac address field in a memory from a mac addr type 1248 */ 1249 void 1250 soc_memacc_mac_addr_set(soc_memacc_t *memacc, void *entry, 1251 const sal_mac_addr_t mac) 1252 { 1253 uint32 mac_field[2]; 1254 1255 SAL_MAC_ADDR_TO_UINT32(mac, mac_field); 1256 1257 soc_memacc_field_set(memacc, entry, mac_field); 1258 } 1259 1260 /* 1261 * Function: soc_meminfo_fieldinfo_field_set 1262 * Purpose: Set a <=32 bit field out of a memory entry 1263 */ 1264 void 1265 soc_meminfo_fieldinfo_field_set(uint32 *entbuf, 1266 soc_mem_info_t *meminfo, 1267 soc_field_info_t *fieldinfo, 1268 uint32 *fldbuf) 1269 { 1270 uint32 mask; 1271 int i, wp, bp, len; 1272 1273 if (NULL == fieldinfo) { 1274 assert(fieldinfo); 1275 } 1276 1277 /* Make sure value fits into the field. */ 1278 /* 1279 * COVERITY 1280 * 1281 * assert validates the input for NULL 1282 */ 1283 /* coverity[var_deref_model : FALSE] */ 1284 if (!_soc_field_value_fit(fieldinfo, fldbuf)) { 1285 assert(_soc_field_value_fit(fieldinfo, fldbuf)); 1286 } 1287 1288 bp = fieldinfo->bp; 1289 1290 if (fieldinfo->flags & SOCF_LE) { 1291 wp = bp / 32; 1292 bp = bp & (32 - 1); 1293 i = 0; 1294 1295 for (len = fieldinfo->len; len > 0; len -= 32) { 1296 if (bp) { 1297 if (len < 32) { 1298 mask = (1 << len) - 1; 1299 } else { 1300 mask = -1; 1301 } 1302 1303 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp); 1304 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 1305 if (len > (32 - bp)) { 1306 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp)); 1307 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |= 1308 fldbuf[i] >> (32 - bp) & ((1 << bp) - 1); 1309 } 1310 } else { 1311 if (len < 32) { 1312 mask = (1 << len) - 1; 1313 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask; 1314 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 1315 } else { 1316 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i]; 1317 } 1318 } 1319 1320 i++; 1321 } 1322 } else { /* Big endian: swap bits */ 1323 len = fieldinfo->len; 1324 1325 while (len > 0) { 1326 len--; 1327 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1))); 1328 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |= 1329 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1)); 1330 bp++; 1331 } 1332 } 1333 } 1334 /* 1335 * Function: soc_meminfo_fieldinfo_field32_set 1336 * Purpose: Set a <=32 bit field out of a memory entry 1337 */ 1338 void 1339 soc_meminfo_fieldinfo_field32_set(soc_mem_info_t *meminfo, 1340 void *entry, 1341 soc_field_info_t *fieldinfo, 1342 uint32 value) 1343 { 1344 /* 1345 * COVERITY 1346 * 1347 * We do this intentionally to use the generic function 1348 * soc_meminfo_fieldinfo_field_set() which does the necessary handling. 1349 */ 1350 /* coverity[address_of] */ 1351 /* coverity[callee_ptr_arith] */ 1352 soc_meminfo_fieldinfo_field_set(entry, meminfo, fieldinfo, &value); 1353 } 1354 1355 /* 1356 * Function: soc_meminfo_fieldinfo_field64_get 1357 * Purpose: Get a <=64 bit field out of a memory entry 1358 */ 1359 void 1360 soc_meminfo_fieldinfo_field64_set(soc_mem_info_t *meminfo, 1361 void *entry, 1362 soc_field_info_t *fieldinfo, 1363 uint64 val64) 1364 { 1365 uint32 val64_field[2]; 1366 1367 val64_field[0] = COMPILER_64_LO(val64); 1368 val64_field[1] = COMPILER_64_HI(val64); 1369 1370 soc_meminfo_fieldinfo_field_set(entry, meminfo, 1371 fieldinfo, val64_field); 1372 } 1373 1374 /* 1375 * Function: soc_meminfo_field_set 1376 * Purpose: Set a memory field without reference to chip. 1377 * Parameters: meminfo -- direct reference to memory description 1378 */ 1379 void 1380 soc_meminfo_field_set(soc_mem_t mem, soc_mem_info_t *meminfo, uint32 *entbuf, 1381 soc_field_t field, uint32 *fldbuf) 1382 { 1383 soc_field_info_t *fieldinfo; 1384 uint32 mask; 1385 int i, wp, bp, len; 1386 1387 SOC_FIND_FIELD(field, 1388 meminfo->fields, 1389 meminfo->nFields, 1390 fieldinfo); 1391 if (NULL == fieldinfo) { 1392 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1393 LOG_CLI((BSL_META("mem %s field %s is invalid\n"), 1394 soc_mem_name[mem], soc_fieldnames[field])); 1395 #endif 1396 assert(fieldinfo); 1397 } 1398 1399 /* Make sure value fits into the field. */ 1400 /* 1401 * COVERITY 1402 * 1403 * assert validates the input for NULL 1404 */ 1405 /* coverity[var_deref_model : FALSE] */ 1406 if (!_soc_field_value_fit(fieldinfo, fldbuf)) { 1407 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1408 LOG_CLI((BSL_META("mem %s field %s value does not fit\n"), 1409 soc_mem_name[mem], soc_fieldnames[field])); 1410 #endif 1411 assert(_soc_field_value_fit(fieldinfo, fldbuf)); 1412 } 1413 1414 bp = fieldinfo->bp; 1415 1416 if (fieldinfo->flags & SOCF_LE) { 1417 wp = bp / 32; 1418 bp = bp & (32 - 1); 1419 i = 0; 1420 1421 for (len = fieldinfo->len; len > 0; len -= 32) { 1422 if (bp) { 1423 if (len < 32) { 1424 mask = (1 << len) - 1; 1425 } else { 1426 mask = -1; 1427 } 1428 1429 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp); 1430 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 1431 if (len > (32 - bp)) { 1432 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp)); 1433 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |= 1434 fldbuf[i] >> (32 - bp) & ((1 << bp) - 1); 1435 } 1436 } else { 1437 if (len < 32) { 1438 mask = (1 << len) - 1; 1439 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask; 1440 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 1441 } else { 1442 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i]; 1443 } 1444 } 1445 1446 i++; 1447 } 1448 } else { /* Big endian: swap bits */ 1449 len = fieldinfo->len; 1450 1451 while (len > 0) { 1452 len--; 1453 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1))); 1454 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |= 1455 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1)); 1456 bp++; 1457 } 1458 } 1459 } 1460 /* 1461 * Function: 1462 * soc_mem_field_valid 1463 * Purpose: 1464 * Verify if field is valid & present in memory 1465 * Parameters: 1466 * mem - (IN)Memory id. 1467 * field - (IN)Field id. 1468 * Return: 1469 * TRUE -If field is present & valid. 1470 * FALSE -Otherwise. 1471 */ 1472 int 1473 soc_mem_field_valid(int unit, soc_mem_t mem, soc_field_t field) 1474 { 1475 soc_mem_info_t *meminfo; 1476 soc_field_info_t *finfop; /* Field information structure. */ 1477 1478 #ifdef BCM_TRIDENT3_SUPPORT 1479 if (soc_feature(unit, soc_feature_flex_flow)) { 1480 if (SOC_MEM_IS_VIEW(unit, mem)) { 1481 return _soc_mem_view_field_valid(unit, mem, field); 1482 } 1483 } 1484 #endif 1485 1486 /* Verify that memory is present on the device. */ 1487 if (!SOC_MEM_IS_VALID(unit, mem)) { 1488 return FALSE; 1489 } 1490 1491 meminfo = &SOC_MEM_INFO(unit, mem); 1492 SOC_FIND_FIELD(field, 1493 meminfo->fields, 1494 meminfo->nFields, 1495 finfop); 1496 return (finfop != NULL) ? TRUE : FALSE; 1497 } 1498 1499 /* 1500 * Function: soc_mem_field_get 1501 * Purpose: Get a memory field 1502 * Parameters: unit - device 1503 * mem - table 1504 * entbuf - table entry buffer 1505 * field - which field to get 1506 * fldbuf - field buffer 1507 */ 1508 uint32 * 1509 soc_mem_field_get(int unit, soc_mem_t mem, const uint32 *entbuf, 1510 soc_field_t field, uint32 *fldbuf) 1511 { 1512 soc_mem_info_t *meminfo; 1513 1514 #ifdef BCM_TRIDENT3_SUPPORT 1515 if (soc_feature(unit, soc_feature_flex_flow)) { 1516 if (SOC_MEM_IS_VIEW(unit, mem)) { 1517 return _soc_mem_view_field_get(unit, mem, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS); 1518 } 1519 } 1520 #endif 1521 1522 if (!SOC_MEM_IS_VALID(unit, mem)) { 1523 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1524 LOG_CLI((BSL_META_U(unit, 1525 "mem %s is invalid\n"), soc_mem_name[mem])); 1526 #endif 1527 assert(SOC_MEM_IS_VALID(unit, mem)); 1528 } 1529 1530 meminfo = &SOC_MEM_INFO(unit, mem); 1531 1532 return soc_meminfo_field_get(mem, meminfo, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS); 1533 } 1534 1535 /* 1536 * Function: soc_mem_field_set 1537 * Purpose: Set a memory field 1538 * Parameters: unit - device 1539 * mem - table 1540 * entbuf - table entry buffer 1541 * field - which field to set 1542 * fldbuf - field buffer 1543 */ 1544 void 1545 soc_mem_field_set(int unit, soc_mem_t mem, uint32 *entbuf, soc_field_t field, 1546 uint32 *fldbuf) 1547 { 1548 soc_mem_info_t *meminfo; 1549 1550 #ifdef BCM_TRIDENT3_SUPPORT 1551 if (soc_feature(unit, soc_feature_flex_flow)) { 1552 if (SOC_MEM_IS_VIEW(unit, mem)) { 1553 _soc_mem_view_field_set(unit, mem, entbuf, field, fldbuf); 1554 return; 1555 } 1556 } 1557 #endif 1558 1559 if (!SOC_MEM_IS_VALID(unit, mem)) { 1560 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1561 LOG_CLI((BSL_META_U(unit, 1562 "mem %s is invalid\n"), soc_mem_name[mem])); 1563 #endif 1564 assert(SOC_MEM_IS_VALID(unit, mem)); 1565 } 1566 1567 meminfo = &SOC_MEM_INFO(unit, mem); 1568 1569 soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf); 1570 } 1571 1572 1573 /* 1574 * Function: soc_mem_field_width_fit_set 1575 * Purpose: Set a memory field 1576 * Chop the value if fld_buf doesn't fit into the entry. 1577 * Parameters: unit - device 1578 * mem - table 1579 * entbuf - table entry buffer 1580 * field - which field to set 1581 * fldbuf - field buffer 1582 */ 1583 void 1584 soc_mem_field_width_fit_set(int unit, soc_mem_t mem, uint32 *entbuf, 1585 soc_field_t field, uint32 *fldbuf) 1586 { 1587 soc_mem_info_t *meminfo; 1588 soc_field_info_t *fieldinfo; 1589 1590 if (!SOC_MEM_IS_VALID(unit, mem)) { 1591 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1592 LOG_CLI((BSL_META_U(unit, 1593 "mem %s is invalid\n"), soc_mem_name[mem])); 1594 #endif 1595 assert(SOC_MEM_IS_VALID(unit, mem)); 1596 } 1597 1598 meminfo = &SOC_MEM_INFO(unit, mem); 1599 1600 SOC_FIND_FIELD(field, 1601 meminfo->fields, 1602 meminfo->nFields, 1603 fieldinfo); 1604 if (NULL == fieldinfo) { 1605 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1606 LOG_CLI((BSL_META_U(unit, 1607 "mem %s field %s is invalid\n"), 1608 soc_mem_name[mem], soc_fieldnames[field])); 1609 #endif 1610 assert(fieldinfo); 1611 } 1612 1613 /* Chop the value so it fits into the field. */ 1614 _soc_field_value_chop(fieldinfo, fldbuf); 1615 1616 soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf); 1617 } 1618 1619 /* 1620 * Function: soc_mem_field32_get 1621 * Purpose: Get a <=32 bit field out of a memory entry 1622 * Returns: The value of the field 1623 */ 1624 uint32 1625 soc_mem_field32_get(int unit, soc_mem_t mem, const void *entbuf, 1626 soc_field_t field) 1627 { 1628 uint32 value; 1629 1630 #ifdef BCM_TRIDENT3_SUPPORT 1631 if (soc_feature(unit, soc_feature_flex_flow)) { 1632 if (SOC_MEM_IS_VIEW(unit, mem)) { 1633 _soc_mem_view_field_get(unit, mem, entbuf, field, &value, 1); 1634 return value; 1635 } 1636 } 1637 #endif 1638 1639 if (!SOC_MEM_IS_VALID(unit, mem)) { 1640 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1641 LOG_CLI((BSL_META_U(unit, "mem %s is invalid\n"), soc_mem_name[mem])); 1642 #endif 1643 assert(SOC_MEM_IS_VALID(unit, mem)); 1644 } 1645 soc_meminfo_field_get(mem, &SOC_MEM_INFO(unit, mem), entbuf, field, &value, 1); 1646 1647 return value; 1648 } 1649 1650 /* 1651 * Function: soc_mem_field32_get_def 1652 * Purpose: Get a <=32 bit field out of a memory entry, 1653 * or a default value if the memory or field does not exist 1654 * Returns: The value of the field, or the given default value 1655 */ 1656 uint32 1657 soc_mem_field32_get_def(int unit, 1658 soc_mem_t mem, 1659 const void *entbuf, 1660 soc_field_t field, 1661 uint32 def 1662 ) 1663 { 1664 if (soc_mem_field_valid(unit, mem, field)) { 1665 uint32 value; 1666 1667 soc_mem_field_get(unit, mem, entbuf, field, &value); 1668 1669 return value; 1670 } 1671 1672 return (def); 1673 } 1674 1675 /* 1676 * Function: soc_mem_field32_set 1677 * Purpose: Set a <=32 bit field out of a memory entry 1678 * Returns: void 1679 */ 1680 void 1681 soc_mem_field32_set(int unit, soc_mem_t mem, void *entbuf, 1682 soc_field_t field, uint32 value) 1683 { 1684 soc_mem_field_set(unit, mem, entbuf, field, &value); 1685 } 1686 1687 /* 1688 * Function: soc_mem_field32_force 1689 * Purpose: Set a <=32 bit field out of a memory entry 1690 * without checking for field width. Lower 1691 * bits of value are taken. 1692 * Returns: void 1693 */ 1694 void 1695 soc_mem_field32_force(int unit, soc_mem_t mem, void *entry, 1696 soc_field_t field, uint32 value) 1697 { 1698 soc_mem_info_t *meminfo; 1699 1700 if (!SOC_MEM_IS_VALID(unit, mem)) { 1701 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1702 LOG_CLI((BSL_META_U(unit, 1703 "mem %s is invalid\n"), soc_mem_name[mem])); 1704 #endif 1705 assert(SOC_MEM_IS_VALID(unit, mem)); 1706 } 1707 1708 meminfo = &SOC_MEM_INFO(unit, mem); 1709 1710 soc_meminfo_field32_force(mem, meminfo, entry, field, value); 1711 } 1712 1713 /* 1714 * Function: soc_meminfo_field32_force 1715 * Purpose: Set a <=32 bit field out of a memory entry 1716 * without checking for field width. Lower 1717 * bits of value are taken. 1718 * Returns: Value put in field. 1719 */ 1720 void 1721 soc_meminfo_field32_force(soc_mem_t mem, soc_mem_info_t *meminfo, void *entry, 1722 soc_field_t field, uint32 value) 1723 { 1724 soc_field_info_t *fieldinfo; 1725 int len; 1726 1727 SOC_FIND_FIELD(field, 1728 meminfo->fields, 1729 meminfo->nFields, 1730 fieldinfo); 1731 if (NULL == fieldinfo) { 1732 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1733 LOG_CLI((BSL_META("mem %s field %s is invalid\n"), 1734 soc_mem_name[mem], soc_fieldnames[field])); 1735 #endif 1736 assert(fieldinfo); 1737 } 1738 1739 /* 1740 * COVERITY 1741 * 1742 * assert validates the input for NULL 1743 */ 1744 /* coverity[var_deref_opl : FALSE] */ 1745 len = fieldinfo->len; 1746 1747 assert(len <= 32); 1748 1749 if (len < 32) { /* Force value to fit in field width */ 1750 value &= (1 << len) - 1; 1751 } 1752 1753 /* 1754 * COVERITY 1755 * 1756 * We do this intentionally to use the generic function 1757 * soc_meminfo_field_set() which does the necessary handling. 1758 */ 1759 /* coverity[address_of] */ 1760 /* coverity[callee_ptr_arith] */ 1761 soc_meminfo_field_set(mem, meminfo, entry, field, &value); 1762 } 1763 1764 /* 1765 * Function: soc_mem_mask_field_get 1766 * Purpose: Get a memory mask field 1767 * Parameters: unit - device 1768 * mem - table 1769 * entbuf - table entry buffer 1770 * field - which field to get 1771 * fldbuf - field buffer 1772 */ 1773 uint32 * 1774 soc_mem_mask_field_get(int unit, soc_mem_t mem, const uint32 *entbuf, 1775 soc_field_t field, uint32 *fldbuf) 1776 { 1777 soc_mem_info_t *meminfo; 1778 uint32 *rfldbuf; 1779 #if defined(BCM_ESW_SUPPORT) 1780 int dc_val, len, i; 1781 #endif 1782 1783 if (!SOC_MEM_IS_VALID(unit, mem)) { 1784 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1785 LOG_CLI((BSL_META_U(unit, 1786 "mem %s is invalid\n"), soc_mem_name[mem])); 1787 #endif 1788 assert(SOC_MEM_IS_VALID(unit, mem)); 1789 } 1790 1791 meminfo = &SOC_MEM_INFO(unit, mem); 1792 1793 rfldbuf = soc_meminfo_field_get(mem, meminfo, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS); 1794 1795 #if defined(BCM_ESW_SUPPORT) 1796 soc_tcam_get_info(unit, NULL, NULL, &dc_val, NULL); 1797 if (dc_val) { 1798 /* TCAM mask polarity is different than software representation */ 1799 i = 0; 1800 len = soc_mem_field_length(unit, mem, field); 1801 for (; len > 0; len -= 32) { 1802 rfldbuf[i++] ^= 0xffffffff; 1803 } 1804 if (len & 0x1f) { 1805 rfldbuf[i - 1] &= (1 << (len & 0x1f)) - 1; 1806 } 1807 } 1808 #endif 1809 1810 return rfldbuf; 1811 } 1812 1813 /* 1814 * Function: soc_mem_mask_field_set 1815 * Purpose: Set a memory mask field 1816 * Parameters: unit - device 1817 * mem - table 1818 * entbuf - table entry buffer 1819 * field - which field to set 1820 * fldbuf - field buffer 1821 */ 1822 void 1823 soc_mem_mask_field_set(int unit, soc_mem_t mem, uint32 *entbuf, 1824 soc_field_t field, uint32 *fldbuf) 1825 { 1826 soc_mem_info_t *meminfo; 1827 #if defined(BCM_ESW_SUPPORT) 1828 uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; 1829 int dc_val, len, i, rv; 1830 #endif 1831 1832 if (!SOC_MEM_IS_VALID(unit, mem)) { 1833 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 1834 LOG_CLI((BSL_META_U(unit, 1835 "mem %s is invalid\n"), soc_mem_name[mem])); 1836 #endif 1837 assert(SOC_MEM_IS_VALID(unit, mem)); 1838 } 1839 1840 meminfo = &SOC_MEM_INFO(unit, mem); 1841 1842 #if defined(BCM_ESW_SUPPORT) 1843 rv = soc_tcam_get_info(unit, NULL, NULL, &dc_val, NULL); 1844 if (SOC_SUCCESS(rv) && dc_val) { 1845 /* TCAM mask polarity is different than software representation */ 1846 i = 0; 1847 len = soc_mem_field_length(unit, mem, field); 1848 for (; len > 0; len -= 32) { 1849 buf[i] = fldbuf[i] ^ 0xffffffff; 1850 i++; 1851 } 1852 if (len & 0x1f) { 1853 buf[i - 1] &= (1 << (len & 0x1f)) - 1; 1854 } 1855 soc_meminfo_field_set(mem, meminfo, entbuf, field, buf); 1856 } 1857 else 1858 #endif 1859 { 1860 soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf); 1861 } 1862 1863 } 1864 1865 /* 1866 * Function: soc_mem_mask_field32_get 1867 * Purpose: Get a <= 32 bit mask field out of a memory entry 1868 * Returns: The value of the mask field 1869 */ 1870 uint32 1871 soc_mem_mask_field32_get(int unit, soc_mem_t mem, const void *entbuf, 1872 soc_field_t field) 1873 { 1874 uint32 value; 1875 1876 /* coverity[callee_ptr_arith : FALSE] */ 1877 soc_mem_mask_field_get(unit, mem, entbuf, field, &value); 1878 1879 return value; 1880 } 1881 1882 /* 1883 * Function: soc_mem_mask_field32_set 1884 * Purpose: Set a <= 32 bit mask field of a memory entry 1885 * Returns: void 1886 */ 1887 void 1888 soc_mem_mask_field32_set(int unit, soc_mem_t mem, void *entbuf, 1889 soc_field_t field, uint32 value) 1890 { /* coverity[callee_ptr_arith : FALSE] */ 1891 soc_mem_mask_field_set(unit, mem, entbuf, field, &value); 1892 } 1893 1894 1895 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 1896 /* 1897 * Function: soc_mem_fields32_modify 1898 * Purpose: Modify the value of a fields in a memory. 1899 * Parameters: 1900 * unit - (IN) SOC unit number. 1901 * mem - (IN) Memory. 1902 * index - (IN) Memory entry index. 1903 * field_count - (IN) Number of fields to modify. 1904 * fields - (IN) Modified fields array. 1905 * values - (IN) New value for each member of fields array. 1906 * Returns: 1907 * SOC_E_XXX 1908 */ 1909 int 1910 soc_mem_fields32_modify(int unit, soc_mem_t mem, int index, 1911 int field_count, soc_field_t *fields, uint32 *values) 1912 { 1913 uint32 buf[SOC_MAX_MEM_WORDS]; /* Buffer to read memory entry. */ 1914 int idx; /* Iteration index. */ 1915 int rv; /* Operation return status. */ 1916 int value_changed = 0; /* Flag of value changed comparing 1917 between input and current reading*/ 1918 1919 /* Field count check before continue. */ 1920 if (field_count == 0) { 1921 return (SOC_E_NONE); 1922 } 1923 1924 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 1925 1926 #ifdef BCM_TRIDENT3_SUPPORT 1927 if (soc_feature(unit, soc_feature_flex_flow)) { 1928 if (SOC_MEM_IS_VIEW(unit, mem)) { 1929 return _soc_mem_view_fields32_modify(unit, mem, index, field_count, fields, values); 1930 } 1931 } 1932 #endif 1933 1934 /* Check that memory is a valid one for this unit. */ 1935 if (!SOC_MEM_IS_VALID(unit, mem)) { 1936 return (SOC_E_UNAVAIL); 1937 } 1938 1939 /* Check entry index range. */ 1940 if ((index > soc_mem_index_max(unit, mem)) || 1941 (index < soc_mem_index_min(unit, mem))) { 1942 return (SOC_E_PARAM); 1943 } 1944 1945 /* Fields & values sanity check. */ 1946 for (idx = 0; idx < field_count; idx++) { 1947 if ((NULL == fields + idx) || (NULL == values + idx)) { 1948 /* 1949 * COVERITY 1950 * This is kept intentional for future use 1951 * or as defensive statement. 1952 */ 1953 /* coverity[dead_error_line] */ 1954 return (SOC_E_PARAM); 1955 } 1956 1957 /* Make sure value fits into memory field. */ 1958 SOC_IF_ERROR_RETURN 1959 (soc_mem_field32_fit(unit, mem, fields[idx], values[idx])); 1960 } 1961 1962 /* Lock the memory. */ 1963 soc_mem_lock(unit, mem); 1964 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, buf); 1965 if (SOC_FAILURE(rv)) { 1966 soc_mem_unlock(unit, mem); 1967 return (rv); 1968 } 1969 1970 /* Set updated values in the buffer. */ 1971 for (idx = 0; idx < field_count; idx ++) { 1972 if(values[idx] != soc_mem_field32_get(unit, mem, buf, fields[idx])) { 1973 value_changed = 1; 1974 soc_mem_field32_set(unit, mem, buf, fields[idx], values[idx]); 1975 } 1976 } 1977 1978 /* Write buffer back to memory. */ 1979 if(value_changed) { 1980 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, buf); 1981 } 1982 1983 soc_mem_unlock(unit, mem); 1984 return (rv); 1985 } 1986 1987 /* 1988 * Function: soc_mem_field32_modify 1989 * Purpose: Modify the value of a field in a memory entry. 1990 * Parameters: 1991 * unit - (IN) SOC unit number. 1992 * mem - (IN) Memory. 1993 * index - (IN) Memory entry index number. 1994 * field - (IN) Modified field. 1995 * value - (IN) New field value. 1996 * Returns: 1997 * SOC_E_XXX 1998 */ 1999 int 2000 soc_mem_field32_modify(int unit, soc_mem_t mem, int index, 2001 soc_field_t field, uint32 value) 2002 { 2003 2004 DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE)); 2005 return soc_mem_fields32_modify(unit, mem, index, 1, &field, &value); 2006 } 2007 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) */ 2008 2009 /* 2010 * Function: 2011 * soc_mem_field64_set 2012 * Purpose: 2013 * Set a field in a memory from a uint64 type 2014 * Parameters: 2015 * unit - (IN) BCM device number. 2016 * mem - (IN) Memory id. 2017 * entry - (IN) HW entry buffer. 2018 * field - (IN) Memory field id. 2019 * val64 - (IN) SW uint64 field buffer. 2020 * Returns: void 2021 */ 2022 void 2023 soc_mem_field64_set(int unit, soc_mem_t mem, void *entry, 2024 soc_field_t field, const uint64 val64) 2025 { 2026 uint32 val64_field[2]; 2027 2028 val64_field[0] = COMPILER_64_LO(val64); 2029 val64_field[1] = COMPILER_64_HI(val64); 2030 2031 soc_mem_field_set(unit, mem, entry, field, val64_field); 2032 } 2033 2034 /* 2035 * Function: 2036 * soc_mem_field64_get 2037 * Purpose: 2038 * Get a field in a memory for a uint64 type 2039 * Parameters: 2040 * unit - (IN) BCM device number. 2041 * mem - (IN) Memory id. 2042 * entry - (IN) HW entry buffer. 2043 * field - (IN) Memory field id. 2044 * val64 - (OUT) SW uint64 field buffer. 2045 * Returns: void 2046 */ 2047 void 2048 soc_mem_field64_get(int unit, soc_mem_t mem, void *entry, 2049 soc_field_t field, uint64 *val64) 2050 { 2051 uint32 val64_field[2] = {0, 0}; 2052 2053 soc_mem_field_get(unit, mem, entry, field, val64_field); 2054 2055 COMPILER_64_SET(*val64, val64_field[1], val64_field[0]); 2056 } 2057 2058 /* 2059 * Function: soc_mem_mac_addr_set 2060 * Purpose: Set a mac address field in a memory from a mac addr type 2061 * Returns: void 2062 */ 2063 void 2064 soc_mem_mac_addr_set(int unit, soc_mem_t mem, void *entry, 2065 soc_field_t field, const sal_mac_addr_t mac) 2066 { 2067 uint32 mac_field[2]; 2068 2069 SAL_MAC_ADDR_TO_UINT32(mac, mac_field); 2070 2071 soc_mem_field_set(unit, mem, entry, field, mac_field); 2072 } 2073 2074 /* 2075 * Function: soc_mem_mac_addr_get 2076 * Purpose: Get a mac address field in a memory from a mac addr type 2077 * Returns: SOC_E_xxx 2078 */ 2079 void 2080 soc_mem_mac_addr_get(int unit, soc_mem_t mem, const void *entry, 2081 soc_field_t field, sal_mac_addr_t mac) 2082 { 2083 uint32 mac_field[2]; 2084 2085 soc_mem_field_get(unit, mem, entry, field, mac_field); 2086 2087 SAL_MAC_ADDR_FROM_UINT32(mac, mac_field); 2088 } 2089 2090 /* 2091 * Function: soc_mem_mac_address_set 2092 * Purpose: Set a MAC address field in a memory from a macaddr type 2093 * Use SOC_MEM_MAC_UPPER_ONLY to set upper 24 bits 2094 * or SOC_MEM_MAC_LOWER_ONLY to set lower 24 bits 2095 * Default to set 48 bits. 2096 * Returns: void 2097 */ 2098 void 2099 soc_mem_mac_address_set(int unit, soc_mem_t mem, void *entry, 2100 soc_field_t field, const sal_mac_addr_t mac, int flags) 2101 { 2102 uint32 mac_addr; 2103 2104 if (flags == SOC_MEM_MAC_UPPER_ONLY) { 2105 mac_addr = ((mac[0] << 16) | (mac[1] << 8) | (mac[2] << 0)); 2106 soc_mem_field_set(unit, mem, entry, field, &mac_addr); 2107 } else if (flags == SOC_MEM_MAC_LOWER_ONLY) { 2108 mac_addr = ((mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0)); 2109 soc_mem_field_set(unit, mem, entry, field, &mac_addr); 2110 } else { 2111 soc_mem_mac_addr_set(unit, mem, entry, field, mac); 2112 } 2113 } 2114 2115 /* 2116 * Function: soc_mem_mac_address_get 2117 * Purpose: Get a MAC address field in a memory from a mac addr type 2118 * Use SOC_MEM_MAC_UPPER_ONLY to get upper 64 bits 2119 * or SOC_MEM_MAC_LOWER_ONLY to get lower 64 bits 2120 * Default to get 48 bits. 2121 * Returns: void 2122 */ 2123 void 2124 soc_mem_mac_address_get(int unit, soc_mem_t mem, const void *entry, 2125 soc_field_t field, sal_mac_addr_t mac, int flags) 2126 { 2127 uint32 mac_field; 2128 2129 if (flags == SOC_MEM_MAC_UPPER_ONLY) { 2130 soc_mem_field_get(unit, mem, entry, field, &mac_field); 2131 mac[0] = (uint8) (mac_field >> 16 & 0xff); 2132 mac[1] = (uint8) (mac_field >> 8 & 0xff); 2133 mac[2] = (uint8) (mac_field & 0xff); 2134 } else if (flags == SOC_MEM_MAC_LOWER_ONLY) { 2135 soc_mem_field_get(unit, mem, entry, field, &mac_field); 2136 mac[3] = (uint8) (mac_field >> 16 & 0xff); 2137 mac[4] = (uint8) (mac_field >> 8 & 0xff); 2138 mac[5] = (uint8) (mac_field & 0xff); 2139 } else { 2140 soc_mem_mac_addr_get(unit, mem, entry, field, mac); 2141 } 2142 } 2143 2144 /* 2145 * Function: soc_meminfo_mac_addr_set 2146 * Purpose: Set a mac address field in a memory from a mac addr type 2147 * Returns: void 2148 */ 2149 void 2150 soc_meminfo_mac_addr_set(soc_mem_t mem, soc_mem_info_t *meminfo, void *entry, 2151 soc_field_t field, const sal_mac_addr_t mac) 2152 { 2153 uint32 mac_field[2]; 2154 2155 SAL_MAC_ADDR_TO_UINT32(mac, mac_field); 2156 2157 soc_meminfo_field_set(mem, meminfo, entry, field, mac_field); 2158 } 2159 2160 /* 2161 * Function: 2162 * soc_mem_ip6_addr_set 2163 * Purpose: 2164 * Set an IP6 address field in a memory from a ip6 addr type 2165 * Parameters: 2166 * unit - (IN) BCM device number. 2167 * mem - (IN) Memory id. 2168 * entry - (IN) HW entry buffer. 2169 * field - (IN) Memory field id. 2170 * ip6 - (IN) SW ip6 address buffer. 2171 * flags - (IN) SOC_MEM_IP6_UPPER_ONLY to set upper 64 bits 2172 * SOC_MEM_IP6_LOWER_ONLY to set lower 64 bits 2173 * SOC_MEM_IP6_UPPER_96BIT to set upper 96 bits 2174 * 0 - set all 128 bits. 2175 * Returns: void 2176 */ 2177 void 2178 soc_mem_ip6_addr_set(int unit, soc_mem_t mem, void *entry, 2179 soc_field_t field, const ip6_addr_t ip6, int flags) 2180 { 2181 uint32 ip6_field[4]; 2182 2183 2184 2185 if (flags == SOC_MEM_IP6_UPPER_ONLY) { 2186 ip6_field[1] = ((ip6[0] << 24) | (ip6[1] << 16) | 2187 (ip6[2] << 8) | (ip6[3] << 0)); 2188 ip6_field[0] = ((ip6[4] << 24) | (ip6[5] << 16) | 2189 (ip6[6] << 8) | (ip6[7] << 0)); 2190 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2191 } else if (flags == SOC_MEM_IP6_LOWER_ONLY) { 2192 ip6_field[3] = ((ip6[8] << 24) | (ip6[9] << 16) | 2193 (ip6[10] << 8) | (ip6[11] << 0)); 2194 ip6_field[2] = ((ip6[12] << 24)| (ip6[13] << 16) | 2195 (ip6[14] << 8) | (ip6[15] << 0)); 2196 soc_mem_field_set(unit, mem, entry, field, (uint32 *)&ip6_field[2]); 2197 } else if (flags == SOC_MEM_IP6_UPPER_96BIT) { 2198 ip6_field[2] = ((ip6[0] << 24) | (ip6[1] << 16) | 2199 (ip6[2] << 8) | (ip6[3] << 0)); 2200 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 2201 (ip6[6] << 8) | (ip6[7] << 0)); 2202 ip6_field[0] = ((ip6[8] << 24) | (ip6[9] << 16) | 2203 (ip6[10] << 8) | (ip6[11] << 0)); 2204 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2205 } else if (flags == SOC_MEM_IP6_LOWER_96BIT) { 2206 ip6_field[2] = ((ip6[4] << 24) | (ip6[5] << 16) | 2207 (ip6[6] << 8) | (ip6[7] << 0)); 2208 ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) | 2209 (ip6[10] << 8) | (ip6[11] << 0)); 2210 ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) | 2211 (ip6[14] << 8) | (ip6[15] << 0)); 2212 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2213 } else if (flags == SOC_MEM_IP6_BITS_119_96) { 2214 ip6_field[0] = ((ip6[1] << 16) | (ip6[2] << 8) | 2215 (ip6[3] << 0)); 2216 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2217 } else if (flags == SOC_MEM_IP6_BITS_63_32) { 2218 ip6_field[0] = ((ip6[8] << 24) | (ip6[9] << 16) | 2219 (ip6[10] << 8) | (ip6[11] << 0)); 2220 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2221 } else if (flags == SOC_MEM_IP6_BITS_31_0) { 2222 ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) | 2223 (ip6[14] << 8) | (ip6[15] << 0)); 2224 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2225 } else { 2226 ip6_field[3] = ((ip6[0] << 24) | (ip6[1] << 16) | 2227 (ip6[2] << 8) | (ip6[3] << 0)); 2228 ip6_field[2] = ((ip6[4] << 24) | (ip6[5] << 16) | 2229 (ip6[6] << 8) | (ip6[7] << 0)); 2230 ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) | 2231 (ip6[10] << 8) | (ip6[11] << 0)); 2232 ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) | 2233 (ip6[14] << 8) | (ip6[15] << 0)); 2234 soc_mem_field_set(unit, mem, entry, field, ip6_field); 2235 } 2236 } 2237 2238 /* 2239 * Function: 2240 * soc_mem_ip6_addr_get 2241 * Purpose: 2242 * Read IP6 address field from memory field to ip6_addr_t buffer. 2243 * Parameters: 2244 * unit - (IN) BCM device number. 2245 * mem - (IN) Memory id. 2246 * entry - (IN) HW entry buffer. 2247 * field - (IN) Memory field id. 2248 * ip6 - (OUT) SW ip6 address buffer. 2249 * flags - (IN) SOC_MEM_IP6_UPPER_ONLY to get upper 64 bits 2250 * SOC_MEM_IP6_LOWER_ONLY to get lower 64 bits 2251 * SOC_MEM_IP6_UPPER_96BIT to get upper 96 bits 2252 * 0 - get all 128 bits. 2253 * Returns: void 2254 */ 2255 void 2256 soc_mem_ip6_addr_get(int unit, soc_mem_t mem, const void *entry, 2257 soc_field_t field, ip6_addr_t ip6, int flags) 2258 { 2259 uint32 ip6_field[4]; 2260 2261 2262 2263 if (flags == SOC_MEM_IP6_UPPER_ONLY) { 2264 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2265 ip6[0] = (uint8) (ip6_field[1] >> 24); 2266 ip6[1] = (uint8) (ip6_field[1] >> 16 & 0xff); 2267 ip6[2] = (uint8) (ip6_field[1] >> 8 & 0xff); 2268 ip6[3] = (uint8) (ip6_field[1] & 0xff); 2269 ip6[4] = (uint8) (ip6_field[0] >> 24); 2270 ip6[5] = (uint8) (ip6_field[0] >> 16 & 0xff); 2271 ip6[6] = (uint8) (ip6_field[0] >> 8 & 0xff); 2272 ip6[7] = (uint8) (ip6_field[0] & 0xff); 2273 } else if (flags == SOC_MEM_IP6_LOWER_ONLY) { 2274 soc_mem_field_get(unit, mem, entry, field, (uint32 *)&ip6_field[2]); 2275 ip6[8] = (uint8) (ip6_field[3] >> 24); 2276 ip6[9] = (uint8) (ip6_field[3] >> 16 & 0xff); 2277 ip6[10] =(uint8) (ip6_field[3] >> 8 & 0xff); 2278 ip6[11] =(uint8) (ip6_field[3] & 0xff); 2279 ip6[12] =(uint8) (ip6_field[2] >> 24); 2280 ip6[13] =(uint8) (ip6_field[2] >> 16 & 0xff); 2281 ip6[14] =(uint8) (ip6_field[2] >> 8 & 0xff); 2282 ip6[15] =(uint8) (ip6_field[2] & 0xff); 2283 } else if (flags == SOC_MEM_IP6_UPPER_96BIT) { 2284 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2285 ip6[0] = (uint8) (ip6_field[2] >> 24); 2286 ip6[1] = (uint8) (ip6_field[2] >> 16 & 0xff); 2287 ip6[2] = (uint8) (ip6_field[2] >> 8 & 0xff); 2288 ip6[3] = (uint8) (ip6_field[2] & 0xff); 2289 ip6[4] = (uint8) (ip6_field[1] >> 24); 2290 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 2291 ip6[6] = (uint8) (ip6_field[1] >> 8 & 0xff); 2292 ip6[7] = (uint8) (ip6_field[1] & 0xff); 2293 ip6[8] = (uint8) (ip6_field[0] >> 24); 2294 ip6[9] = (uint8) (ip6_field[0] >> 16 & 0xff); 2295 ip6[10] =(uint8) (ip6_field[0] >> 8 & 0xff); 2296 ip6[11] =(uint8) (ip6_field[0] & 0xff); 2297 } else if (flags == SOC_MEM_IP6_BITS_119_96) { 2298 soc_mem_field_get(unit, mem, entry, field, (uint32 *)&ip6_field[3]); 2299 ip6[1] = (uint8) (ip6_field[3] >> 16 & 0xff); 2300 ip6[2] = (uint8) (ip6_field[3] >> 8 & 0xff); 2301 ip6[3] = (uint8) (ip6_field[3] & 0xff); 2302 } else if (flags == SOC_MEM_IP6_BITS_63_32) { 2303 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2304 ip6[8] = (uint8) (ip6_field[0] >> 24); 2305 ip6[9] = (uint8) (ip6_field[0] >> 16 & 0xff); 2306 ip6[10] =(uint8) (ip6_field[0] >> 8 & 0xff); 2307 ip6[11] =(uint8) (ip6_field[0] & 0xff); 2308 } else if (flags == SOC_MEM_IP6_BITS_31_0) { 2309 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2310 ip6[12] =(uint8) (ip6_field[0] >> 24); 2311 ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff); 2312 ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff); 2313 ip6[15] =(uint8) (ip6_field[0] & 0xff); 2314 } else if (flags == SOC_MEM_IP6_LOWER_96BIT) { 2315 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2316 ip6[4] = (uint8) (ip6_field[2] >> 24); 2317 ip6[5] = (uint8) (ip6_field[2] >> 16 & 0xff); 2318 ip6[6] = (uint8) (ip6_field[2] >> 8 & 0xff); 2319 ip6[7] = (uint8) (ip6_field[2] & 0xff); 2320 ip6[8] = (uint8) (ip6_field[1] >> 24); 2321 ip6[9] = (uint8) (ip6_field[1] >> 16 & 0xff); 2322 ip6[10] =(uint8) (ip6_field[1] >> 8 & 0xff); 2323 ip6[11] =(uint8) (ip6_field[1] & 0xff); 2324 ip6[12] =(uint8) (ip6_field[0] >> 24); 2325 ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff); 2326 ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff); 2327 ip6[15] =(uint8) (ip6_field[0] & 0xff); 2328 } else { 2329 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2330 ip6[0] = (uint8) (ip6_field[3] >> 24); 2331 ip6[1] = (uint8) (ip6_field[3] >> 16 & 0xff); 2332 ip6[2] = (uint8) (ip6_field[3] >> 8 & 0xff); 2333 ip6[3] = (uint8) (ip6_field[3] & 0xff); 2334 ip6[4] = (uint8) (ip6_field[2] >> 24); 2335 ip6[5] = (uint8) (ip6_field[2] >> 16 & 0xff); 2336 ip6[6] = (uint8) (ip6_field[2] >> 8 & 0xff); 2337 ip6[7] = (uint8) (ip6_field[2] & 0xff); 2338 ip6[8] = (uint8) (ip6_field[1] >> 24); 2339 ip6[9] = (uint8) (ip6_field[1] >> 16 & 0xff); 2340 ip6[10] =(uint8) (ip6_field[1] >> 8 & 0xff); 2341 ip6[11] =(uint8) (ip6_field[1] & 0xff); 2342 ip6[12] =(uint8) (ip6_field[0] >> 24); 2343 ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff); 2344 ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff); 2345 ip6[15] =(uint8) (ip6_field[0] & 0xff); 2346 } 2347 } 2348 2349 void 2350 soc_mem_ip6_addr_mask_set(int unit, soc_mem_t mem, void *entry, 2351 soc_field_t field, const ip6_addr_t ip6, int flags) 2352 { 2353 uint32 ip6_field[4]; 2354 2355 if (flags == SOC_MEM_IP6_UPPER_ONLY) { 2356 SAL_IP6_ADDR_HALF_TO_UINT32(ip6, ip6_field); 2357 soc_mem_mask_field_set(unit, mem, entry, field, ip6_field); 2358 } else if (flags == SOC_MEM_IP6_LOWER_ONLY) { 2359 SAL_IP6_ADDR_HALF_TO_UINT32(&ip6[8], &ip6_field[2]); 2360 soc_mem_mask_field_set(unit, mem, entry, field, &ip6_field[2]); 2361 } else { 2362 SAL_IP6_ADDR_TO_UINT32(ip6, ip6_field); 2363 soc_mem_mask_field_set(unit, mem, entry, field, ip6_field); 2364 } 2365 } 2366 2367 void 2368 soc_mem_ip6_addr_mask_get(int unit, soc_mem_t mem, const void *entry, 2369 soc_field_t field, ip6_addr_t ip6, int flags) 2370 { 2371 uint32 ip6_field[4]; 2372 2373 if (flags == SOC_MEM_IP6_UPPER_ONLY) { 2374 soc_mem_mask_field_get(unit, mem, entry, field, ip6_field); 2375 SAL_IP6_ADDR_HALF_FROM_UINT32(ip6, ip6_field); 2376 } else if (flags == SOC_MEM_IP6_LOWER_ONLY) { 2377 soc_mem_mask_field_get(unit, mem, entry, field, &ip6_field[2]); 2378 SAL_IP6_ADDR_HALF_FROM_UINT32(&ip6[8], &ip6_field[2]); 2379 } else { 2380 soc_mem_field_get(unit, mem, entry, field, ip6_field); 2381 SAL_IP6_ADDR_FROM_UINT32(ip6, ip6_field); 2382 } 2383 } 2384 2385 void 2386 soc_mem_pbmp_field_set(int unit, soc_mem_t mem, void *entbuf, 2387 soc_field_t field, soc_pbmp_t *pbmp) 2388 { 2389 uint32 fldbuf[SOC_PBMP_WORD_MAX]; 2390 int i; 2391 2392 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) { 2393 fldbuf[i] = SOC_PBMP_WORD_GET(*pbmp, i); 2394 } 2395 2396 soc_mem_field_set(unit, mem, entbuf, field, fldbuf); 2397 } 2398 2399 void 2400 soc_mem_pbmp_field_get(int unit, soc_mem_t mem, const void *entbuf, 2401 soc_field_t field, soc_pbmp_t *pbmp) 2402 { 2403 uint32 fldbuf[SOC_PBMP_WORD_MAX]; 2404 int i; 2405 2406 sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32)); 2407 soc_mem_field_get(unit, mem, entbuf, field, fldbuf); 2408 2409 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) { 2410 SOC_PBMP_WORD_SET(*pbmp, i, fldbuf[i]); 2411 } 2412 } 2413 2414 /* 2415 * Function: soc_mem_datamask_get 2416 * Purpose: Get a bit mask for a particular field in a memory entry 2417 */ 2418 void 2419 soc_mem_datamask_get(int unit, soc_mem_t mem, uint32 *buf) 2420 { 2421 int f, b, start, end; 2422 soc_field_info_t *fieldp; 2423 soc_mem_info_t *memp; 2424 uint32 tmp; 2425 uint32 field_ignore = 0; 2426 2427 if (!SOC_MEM_IS_VALID(unit, mem)) { 2428 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 2429 LOG_CLI((BSL_META_U(unit, 2430 "mem %s is invalid\n"), soc_mem_name[mem])); 2431 #endif 2432 assert(SOC_MEM_IS_VALID(unit, mem)); 2433 } 2434 2435 memp = &SOC_MEM_INFO(unit, mem); 2436 sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes)); 2437 2438 for (f = 0; f < memp->nFields; f++) { 2439 fieldp = &(memp->fields[f]); 2440 field_ignore = 0; 2441 #ifdef BCM_TRIUMPH_SUPPORT 2442 /*global field overlay with view reserved filed and cause mask error. */ 2443 if (SOC_IS_TRIUMPH3(unit) && 2444 (mem == MPLS_ENTRY_EXTDm) && 2445 (fieldp->field == ENTRY_2_FROM_ENTRY_1_PART1f)) { 2446 field_ignore = 1; 2447 } 2448 #endif 2449 2450 if ((!(fieldp->flags & SOCF_RES)) && /* not reserved */ 2451 (!field_ignore)) { 2452 start = fieldp->bp; 2453 end = fieldp->bp + fieldp->len - 1; 2454 for (b = start / 32; b <= end / 32; b++) { 2455 tmp = -1; 2456 2457 if (b == start / 32) { 2458 tmp &= -1 << (start % 32); 2459 } 2460 2461 if (b == end / 32) { 2462 tmp &= (1 << (end % 32) << 1) - 1; 2463 } 2464 2465 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2466 } 2467 } 2468 } 2469 2470 #ifdef BCM_TRIDENT_SUPPORT 2471 if (SOC_IS_TD_TT(unit)) { 2472 if (mem == FP_GLOBAL_MASK_TCAM_Xm) { 2473 soc_mem_pbmp_field_set(unit, mem, buf, IPBMf, &PBMP_XPIPE(unit)); 2474 soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf, 2475 &PBMP_XPIPE(unit)); 2476 } else if (mem == FP_GLOBAL_MASK_TCAM_Ym) { 2477 soc_mem_pbmp_field_set(unit, mem, buf, IPBMf, &PBMP_YPIPE(unit)); 2478 soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf, 2479 &PBMP_YPIPE(unit)); 2480 } else if (mem == EGR_VLANm) { 2481 if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) { 2482 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf, 2483 &PBMP_ALL(unit)); 2484 } 2485 if (soc_mem_field_valid(unit, mem, UT_PORT_BITMAPf)) { 2486 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf, 2487 &PBMP_ALL(unit)); 2488 } 2489 } else if (mem == EGR_VLAN_Xm) { 2490 if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) { 2491 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf, 2492 &PBMP_XPIPE(unit)); 2493 } 2494 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf, 2495 &PBMP_XPIPE(unit)); 2496 } else if (mem == EGR_VLAN_Ym) { 2497 if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) { 2498 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf, 2499 &PBMP_YPIPE(unit)); 2500 } 2501 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf, 2502 &PBMP_YPIPE(unit)); 2503 } else if (mem == EGR_VLAN_VFI_MEMBERSHIPm) { 2504 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf, 2505 &PBMP_ALL(unit)); 2506 } else if (mem == SRC_MODID_INGRESS_BLOCKm) { 2507 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf, 2508 &PBMP_ALL(unit)); 2509 } else if (mem == L3_TUNNELm) { 2510 if (soc_mem_field_valid (unit, mem, ALLOWED_PORT_BITMAPf)) { 2511 soc_mem_pbmp_field_set(unit, mem, buf, ALLOWED_PORT_BITMAPf, 2512 &PBMP_ALL(unit)); 2513 } 2514 } else if (mem == L3_TUNNEL_DATA_ONLYm) { 2515 if (soc_mem_field_valid (unit, mem, ALLOWED_PORT_BITMAPf)) { 2516 soc_mem_pbmp_field_set(unit, mem, buf, ALLOWED_PORT_BITMAPf, 2517 &PBMP_ALL(unit)); 2518 } 2519 } else if (mem == EGR_VLAN_VFI_UNTAGm) { 2520 if (soc_mem_field_valid(unit, mem, UT_PORT_BITMAPf)) { 2521 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf, 2522 &PBMP_ALL(unit)); 2523 } 2524 } 2525 } 2526 #endif /* BCM_TRIDENT_SUPPORT */ 2527 } 2528 2529 /* 2530 * Function: soc_mem_datamask_rw_get 2531 * Purpose: Get a bit mask for a particular field in a memory entry 2532 */ 2533 void 2534 soc_mem_datamask_rw_get(int unit, soc_mem_t mem, uint32 *buf) 2535 { 2536 int f, b, start, end; 2537 soc_field_info_t *fieldp; 2538 soc_mem_info_t *memp; 2539 uint32 tmp; 2540 uint16 access_flag; 2541 if (!SOC_MEM_IS_VALID(unit, mem)) { 2542 assert(SOC_MEM_IS_VALID(unit, mem)); 2543 } 2544 2545 memp = &SOC_MEM_INFO(unit, mem); 2546 sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes)); 2547 2548 for (f = 0; f < memp->nFields; f++) { 2549 fieldp = &(memp->fields[f]); 2550 access_flag = fieldp->flags & (SOCF_RES | SOCF_RO | SOCF_SIG | SOCF_WO); 2551 /* if ((!(fieldp->flags & SOCF_RES)) && (!(fieldp->flags & SOCF_RO)) && (!(fieldp->flags & SOCF_SIG))) { */ /* not reserved */ 2552 if (access_flag == 0) { /* Get field mask just in case if the field is not read only, is not write only, not a signal and not reserved*/ 2553 start = fieldp->bp; 2554 end = fieldp->bp + fieldp->len - 1; 2555 for (b = start / 32; b <= end / 32; b++) { 2556 tmp = -1; 2557 2558 if (b == start / 32) { 2559 tmp &= -1 << (start % 32); 2560 } 2561 2562 if (b == end / 32) { 2563 tmp &= (1 << (end % 32) << 1) - 1; 2564 } 2565 2566 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2567 } 2568 } 2569 } 2570 } 2571 2572 /* 2573 * Function: soc_mem_tcammask_get 2574 * Purpose: Get a bit mask for TCAM mask field in a memory entry 2575 */ 2576 void 2577 soc_mem_tcammask_get(int unit, soc_mem_t mem, uint32 *buf) 2578 { 2579 soc_mem_info_t *memp; 2580 2581 if (!SOC_MEM_IS_VALID(unit, mem)) { 2582 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 2583 LOG_CLI((BSL_META_U(unit, 2584 "mem %s is invalid\n"), soc_mem_name[mem])); 2585 #endif 2586 assert(SOC_MEM_IS_VALID(unit, mem)); 2587 } 2588 2589 memp = &SOC_MEM_INFO(unit, mem); 2590 sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes)); 2591 2592 #if defined(BCM_TRIUMPH_SUPPORT) 2593 if (soc_feature(unit, soc_feature_esm_support)) { 2594 int f, b, start, end; 2595 soc_field_info_t *fieldp; 2596 uint32 tmp; 2597 2598 for (f = 0; f < memp->nFields; f++) { 2599 fieldp = &(memp->fields[f]); 2600 2601 if (fieldp->flags & SOCF_RES) { 2602 continue; 2603 } 2604 2605 switch (fieldp->field) { 2606 case TMW0f: 2607 case TMW1f: 2608 case TMW2f: 2609 case TMW3f: 2610 case TMW4f: 2611 case TMW5f: 2612 break; 2613 default: 2614 continue; 2615 } 2616 2617 start = fieldp->bp; 2618 end = fieldp->bp + fieldp->len - 1; 2619 2620 for (b = start / 32; b <= end / 32; b++) { 2621 tmp = -1; 2622 2623 if (b == start / 32) { 2624 tmp &= -1 << (start % 32); 2625 } 2626 2627 if (b == end / 32) { 2628 tmp &= (1 << (end % 32) << 1) - 1; 2629 } 2630 2631 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2632 } 2633 } 2634 } 2635 #endif /* BCM_TRIUMPH_SUPPORT */ 2636 #if defined(BCM_SHADOW_SUPPORT) 2637 if (SOC_IS_SHADOW(unit)) { 2638 int f, b, start, end; 2639 soc_field_info_t *fieldp; 2640 uint32 tmp; 2641 2642 if (memp->flags & SOC_MEM_FLAG_CAM) { 2643 for (f = 0; f < memp->nFields; f++) { 2644 fieldp = &(memp->fields[f]); 2645 2646 if (fieldp->flags & SOCF_RES) { 2647 continue; 2648 } 2649 2650 switch (fieldp->field) { 2651 case MASKf: 2652 case MASK0f: 2653 case MASK1f: 2654 case FULL_MASKf: 2655 break; 2656 default: 2657 continue; 2658 } 2659 2660 start = fieldp->bp; 2661 end = fieldp->bp + fieldp->len - 1; 2662 2663 for (b = start / 32; b <= end / 32; b++) { 2664 tmp = -1; 2665 2666 if (b == start / 32) { 2667 tmp &= -1 << (start % 32); 2668 } 2669 2670 if (b == end / 32) { 2671 tmp &= (1 << (end % 32) << 1) - 1; 2672 } 2673 2674 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2675 } 2676 } 2677 } 2678 } 2679 #endif /* BCM_SHADOW_SUPPORT */ 2680 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 2681 if (soc_feature(unit, soc_feature_xy_tcam)) { 2682 int f, b, start, end; 2683 soc_field_info_t *fieldp; 2684 uint32 tmp; 2685 2686 if (memp->flags & SOC_MEM_FLAG_CAM) { 2687 for (f = 0; f < memp->nFields; f++) { 2688 fieldp = &(memp->fields[f]); 2689 2690 if (fieldp->flags & SOCF_RES) { 2691 continue; 2692 } 2693 2694 switch (fieldp->field) { 2695 case MASKf: 2696 case MASK0f: 2697 case MASK1f: 2698 case MASK0_UPRf: 2699 case MASK1_UPRf: 2700 case MASK0_LWRf: 2701 case MASK1_LWRf: 2702 case DATA_MASKf: 2703 case FULL_MASKf: 2704 break; 2705 default: 2706 continue; 2707 } 2708 2709 start = fieldp->bp; 2710 end = fieldp->bp + fieldp->len - 1; 2711 for (b = start / 32; b <= end / 32; b++) { 2712 tmp = -1; 2713 2714 if (b == start / 32) { 2715 tmp &= -1 << (start % 32); 2716 } 2717 2718 if (b == end / 32) { 2719 tmp &= (1 << (end % 32) << 1) - 1; 2720 } 2721 2722 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2723 } 2724 } 2725 if (SOC_IS_TD_TT(unit)) { 2726 if (mem == FP_GLOBAL_MASK_TCAM_Xm) { 2727 soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf, 2728 &PBMP_XPIPE(unit)); 2729 } else if (mem == FP_GLOBAL_MASK_TCAM_Ym) { 2730 soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf, 2731 &PBMP_YPIPE(unit)); 2732 } 2733 } 2734 } 2735 } 2736 #endif /* BCM_TRIDENT_SUPPORT */ 2737 } 2738 2739 /* 2740 * Function: soc_mem_eccmask_get 2741 * Purpose: Get a bit mask for ECC mask field in a memory entry 2742 */ 2743 void 2744 soc_mem_eccmask_get(int unit, soc_mem_t mem, uint32 *buf) 2745 { 2746 soc_mem_info_t *memp; 2747 2748 if (!SOC_MEM_IS_VALID(unit, mem)) { 2749 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 2750 LOG_CLI((BSL_META_U(unit, 2751 "mem %s is invalid\n"), soc_mem_name[mem])); 2752 #endif 2753 assert(SOC_MEM_IS_VALID(unit, mem)); 2754 } 2755 2756 memp = &SOC_MEM_INFO(unit, mem); 2757 sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes)); 2758 2759 #if defined(BCM_TRIUMPH_SUPPORT) 2760 if (soc_feature(unit, soc_feature_esm_support)) { 2761 int f, b, start, end; 2762 soc_field_info_t *fieldp; 2763 uint32 tmp; 2764 2765 for (f = 0; f < memp->nFields; f++) { 2766 fieldp = &(memp->fields[f]); 2767 2768 if (fieldp->flags & SOCF_RES) { 2769 continue; 2770 } 2771 2772 switch (fieldp->field) { 2773 case ECC_ALLf: 2774 case ECC0_ALLf: 2775 case ECC1_ALLf: 2776 case ECC2_ALLf: 2777 case ECC3_ALLf: 2778 case ECC4_ALLf: 2779 case ECC5_ALLf: 2780 case ECC6_ALLf: 2781 case ECC7_ALLf: 2782 break; 2783 default: 2784 continue; 2785 } 2786 2787 start = fieldp->bp; 2788 end = fieldp->bp + fieldp->len - 1; 2789 2790 for (b = start / 32; b <= end / 32; b++) { 2791 tmp = -1; 2792 2793 if (b == start / 32) { 2794 tmp &= -1 << (start % 32); 2795 } 2796 2797 if (b == end / 32) { 2798 tmp &= (1 << (end % 32) << 1) - 1; 2799 } 2800 2801 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2802 } 2803 } 2804 } 2805 #endif /* BCM_TRIUMPH_SUPPORT */ 2806 2807 if (soc_feature(unit, soc_feature_mem_parity_eccmask)) { 2808 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || \ 2809 defined(BCM_ESW_SUPPORT) 2810 2811 int f, b, start, end; 2812 soc_field_info_t *fieldp; 2813 uint32 tmp; 2814 2815 for (f = 0; f < memp->nFields; f++) { 2816 fieldp = &(memp->fields[f]); 2817 2818 if (fieldp->flags & SOCF_RES) { 2819 continue; 2820 } 2821 2822 switch (fieldp->field) { 2823 case ECCPf: 2824 case ECCf: 2825 case PARITYf: 2826 case ECCP0f: 2827 case ECCP1f: 2828 case ECCP2f: 2829 case ECCP3f: 2830 case ECC0f: 2831 case ECC1f: 2832 case ECC2f: 2833 case ECC3f: 2834 case PARITY0f: 2835 case PARITY1f: 2836 case PARITY2f: 2837 case PARITY3f: 2838 case EVEN_PARITYf: 2839 case ECCP_0f: 2840 case ECCP_1f: 2841 case ECCP_2f: 2842 case ECCP_3f: 2843 case ECC_0f: 2844 case ECC_1f: 2845 case ECC_2f: 2846 case ECC_3f: 2847 case PARITY_0f: 2848 case PARITY_1f: 2849 case PARITY_2f: 2850 case PARITY_3f: 2851 case ECCP_P0f: 2852 case ECCP_P1f: 2853 case ECCP_P2f: 2854 case ECCP_P3f: 2855 case ECC_P0f: 2856 case ECC_P1f: 2857 case ECC_P2f: 2858 case ECC_P3f: 2859 case PARITY_P0f: 2860 case PARITY_P1f: 2861 case PARITY_P2f: 2862 case PARITY_P3f: 2863 case EVEN_PARITY_P0f: 2864 case EVEN_PARITY_P1f: 2865 case EVEN_PARITY_P2f: 2866 case EVEN_PARITY_P3f: 2867 case ECCP_PBM_0f: 2868 case ECCP_PBM_1f: 2869 case ECCP_PBM_2f: 2870 case ECCP_PBM_3f: 2871 case ECC_PBM_0f: 2872 case ECC_PBM_1f: 2873 case ECC_PBM_2f: 2874 case ECC_PBM_3f: 2875 case PARITY_PBM_0f: 2876 case PARITY_PBM_1f: 2877 case PARITY_PBM_2f: 2878 case PARITY_PBM_3f: 2879 case TCAM_PARITY_MASKf: 2880 case TCAM_PARITY_KEYf: 2881 break; 2882 default: 2883 continue; 2884 } 2885 2886 start = fieldp->bp; 2887 end = fieldp->bp + fieldp->len - 1; 2888 2889 for (b = start / 32; b <= end / 32; b++) { 2890 tmp = -1; 2891 2892 if (b == start / 32) { 2893 tmp &= -1 << (start % 32); 2894 } 2895 2896 if (b == end / 32) { 2897 tmp &= (1 << (end % 32) << 1) - 1; 2898 } 2899 2900 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp; 2901 } 2902 } 2903 #endif /* BCM_KATANA2_SUPPORT || BCM_GREYHOUND_SUPPORT || BCM_ESW_SUPPORT */ 2904 } 2905 } 2906 2907 /* 2908 * Function: soc_mem_forcedata_get 2909 * Purpose: Get a bit mask and value for non-zero sticky fields in a 2910 * memory entry 2911 */ 2912 void 2913 soc_mem_forcedata_get(int unit, soc_mem_t mem, uint32 *maskbuf, 2914 uint32 *databuf) 2915 { 2916 if (!SOC_MEM_IS_VALID(unit, mem)) { 2917 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 2918 LOG_CLI((BSL_META_U(unit, 2919 "mem %s is invalid\n"), soc_mem_name[mem])); 2920 #endif 2921 assert(SOC_MEM_IS_VALID(unit, mem)); 2922 } 2923 2924 sal_memset(maskbuf, 0, sizeof(*maskbuf) * soc_mem_entry_words(unit, mem)); 2925 sal_memset(databuf, 0, sizeof(*databuf) * soc_mem_entry_words(unit, mem)); 2926 2927 #if defined(BCM_TRIDENT_SUPPORT) 2928 if (mem == HG_TRUNK_GROUPm && 2929 soc_feature(unit, soc_feature_hg_trunk_16_members)) { 2930 int field_len; 2931 field_len = soc_mem_field_length(unit, mem, TG_SIZEf); 2932 soc_mem_field32_set(unit, mem, maskbuf, TG_SIZEf, 2933 (1 << field_len) - 1); 2934 soc_mem_field32_set(unit, mem, databuf, TG_SIZEf, 0xf); 2935 } 2936 #endif /* BCM_TRIDENT_SUPPORT */ 2937 #ifdef BCM_GREYHOUND2_SUPPORT 2938 if (SOC_IS_GREYHOUND2(unit) && ( 2939 mem == SR_SN_HISTORY_0m || mem == SR_SN_HISTORY_1m || mem == SR_SN_HISTORY_2m || 2940 mem == SR_SN_HISTORY_3m || mem == SR_SN_HISTORY_4m || mem == SR_SN_HISTORY_5m || 2941 mem == SR_SN_HISTORY_6m || mem == SR_SN_HISTORY_7m || mem == SR_SN_HISTORY_8m || 2942 mem == SR_SN_HISTORY_9m || mem == SR_SN_HISTORY_10m || mem == SR_SN_HISTORY_11m || 2943 mem == SR_SN_HISTORY_12m || mem == SR_SN_HISTORY_13m || mem == SR_SN_HISTORY_14m || 2944 mem == SR_SN_HISTORY_15m )) { 2945 soc_mem_field32_set(unit, mem, databuf, BLOCK_SELECTf, 2946 ((1 << soc_mem_field_length(unit, mem, BLOCK_SELECTf)) - 1)); 2947 soc_mem_field32_set(unit, mem, maskbuf, BLOCK_SELECTf, 2948 ((1 << soc_mem_field_length(unit, mem, BLOCK_SELECTf)) - 1)); 2949 } 2950 #endif /* BCM_GREYHOUND2_SUPPORT */ 2951 2952 } 2953 2954 #if defined(BCM_ESW_SUPPORT) 2955 void 2956 soc_mem_base_to_wide_entry_conv(int unit, soc_mem_t dest_mem, soc_mem_t src_mem, 2957 uint32 *dest, uint32 *src[4], uint8 conv_type) 2958 { 2959 uint32 field[SOC_MAX_MEM_FIELD_WORDS]; 2960 switch (conv_type) { 2961 case TYPE_1_TO_TYPE_2: 2962 soc_mem_field_set(unit, dest_mem, dest, ENTRY_2_FROM_ENTRY_1_PART0f, 2963 soc_mem_field_get(unit, src_mem, src[0], 2964 WIDE_ENTRY_BITSf, field)); 2965 soc_mem_field_set(unit, dest_mem, dest, ENTRY_2_FROM_ENTRY_1_PART1f, 2966 soc_mem_field_get(unit, src_mem, src[1], 2967 WIDE_ENTRY_BITSf, field)); 2968 soc_mem_field32_set(unit, dest_mem, dest, HIT_BITSf, 2969 soc_mem_field32_get(unit, src_mem, src[0], 2970 HIT_BITSf)); 2971 return; 2972 case TYPE_1_TO_TYPE_4: 2973 soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART0f, 2974 soc_mem_field_get(unit, src_mem, src[0], 2975 WIDE_ENTRY_BITSf, field)); 2976 soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART1f, 2977 soc_mem_field_get(unit, src_mem, src[1], 2978 WIDE_ENTRY_BITSf, field)); 2979 soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART2f, 2980 soc_mem_field_get(unit, src_mem, src[2], 2981 WIDE_ENTRY_BITSf, field)); 2982 soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART3f, 2983 soc_mem_field_get(unit, src_mem, src[3], 2984 WIDE_ENTRY_BITSf, field)); 2985 soc_mem_field32_set(unit, dest_mem, dest, HIT_BITSf, 2986 soc_mem_field32_get(unit, src_mem, src[0], 2987 HIT_BITSf)); 2988 return; 2989 default: 2990 LOG_CLI((BSL_META_U(unit, 2991 "Unimplemented convertion type: %d\n"), conv_type)); 2992 assert(0); 2993 } 2994 } 2995 #endif 2996 2997 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) 2998 2999 /* 3000 * Function: soc_mem_addr 3001 * Purpose: Turn a memory, block, and index into a memory address 3002 * Returns: address to send off in an schannel message 3003 */ 3004 /* 3005 * Regular: | Table(8) | Block(4) | Region(4) | Index(16) | 3006 * Monolithic: | Table(8) | Index(24) | 3007 */ 3008 uint32 3009 soc_mem_addr(int unit, soc_mem_t mem, unsigned array_index, int blk, int index) 3010 { 3011 uint32 blkoff; 3012 soc_mem_info_t *mip; 3013 soc_mem_array_info_t *maip; 3014 uint32 base; 3015 3016 if (!SOC_MEM_IS_VALID(unit, mem)) { 3017 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 3018 LOG_CLI((BSL_META_U(unit, 3019 "mem %s is invalid\n"), soc_mem_name[mem])); 3020 #endif 3021 assert(SOC_MEM_IS_VALID(unit, mem)); 3022 } 3023 3024 assert(blk >= 0 && blk < SOC_MAX_NUM_BLKS); 3025 assert(index >= 0); 3026 3027 #if defined(BCM_TRIUMPH_SUPPORT) 3028 if (soc_feature(unit, soc_feature_esm_support)) { 3029 if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ESM) || 3030 (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ETU)) { 3031 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit, 3032 mem, 3033 index, 3034 &mem, 3035 &index)); 3036 } 3037 } 3038 #endif 3039 3040 mip = &SOC_MEM_INFO(unit, mem); 3041 3042 #if defined(BCM_TRIUMPH3_SUPPORT) 3043 if (soc_feature(unit, soc_feature_etu_support)) { 3044 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ISM) { 3045 if (mip->flags & (SOC_MEM_FLAG_CAM | SOC_MEM_FLAG_EXT_CAM)) { 3046 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit, 3047 mem, 3048 index, 3049 &mem, 3050 &index)); 3051 } 3052 } 3053 /* do it again if returned mem is different */ 3054 mip = &SOC_MEM_INFO(unit, mem); 3055 } 3056 #endif 3057 if ((blk>=32)?(mip->blocks_hi & (1 << (blk&0x1F))):(mip->blocks & (1 << blk))) { 3058 blkoff = ((SOC_BLOCK2OFFSET(unit, blk) & 0xf) << SOC_BLOCK_BP) | 3059 (((SOC_BLOCK2OFFSET(unit, blk) >> 4) & 0x3) << SOC_BLOCK_MSB_BP); 3060 } else { 3061 blkoff = 0; 3062 } 3063 3064 base = mip->base; 3065 3066 #ifdef BCM_DFE_SUPPORT 3067 if(SOC_IS_FE1600(unit)) { 3068 base = (((mip->base >> 20) & 0x3F) << 24) | (mip->base & 0xFFFFF); 3069 } 3070 #endif 3071 3072 if (array_index) { 3073 /* non zero array index, implying this is a memory array */ 3074 assert (mip->flags & SOC_MEM_FLAG_IS_ARRAY); /* verify this is really a memory array */ 3075 maip = SOC_MEM_ARRAY_INFOP(unit, mem); 3076 assert(maip); /* verify this is memory array information exists */ 3077 assert(array_index >= maip->first_array_index && array_index < maip->numels + maip->first_array_index); /* verify that the array index is in range */ 3078 LOG_INFO(BSL_LS_SOC_MEM, 3079 (BSL_META_U(unit, 3080 "addr: %x, mip->base: %x, blkoff: %x, " 3081 "index = %d, mip->gran: %d, * = %x, arr_in = %u, skip = %u\n"), 3082 base+blkoff+(index * mip->gran) + (array_index * maip->element_skip), 3083 mip->base,blkoff, index, mip->gran, 3084 (index * mip->gran), array_index, maip->element_skip)); 3085 return base + blkoff + (index * mip->gran) + (array_index * maip->element_skip); 3086 } 3087 3088 LOG_INFO(BSL_LS_SOC_MEM, 3089 (BSL_META_U(unit, 3090 "addr: %x, mip->base: %x, blkoff: %x, " 3091 "index = %d, mip->gran: %d, * = %x\n"), 3092 base+blkoff+(index * mip->gran), 3093 mip->base,blkoff, index, mip->gran, 3094 (index * mip->gran))); 3095 return base + blkoff + (index * mip->gran); 3096 } 3097 3098 /* 3099 * Function: soc_mem_addr_get 3100 * Purpose: Turn a memory, block, and index into a memory address 3101 * Returns: address to send off in an schannel message 3102 */ 3103 /* 3104 * Regular: | Table(8) | Block(4) | Region(4) | Index(16) | 3105 * Monolithic: | Table(8) | Index(24) | 3106 */ 3107 uint32 3108 soc_mem_addr_get(int unit, soc_mem_t mem, unsigned array_index, soc_block_t block, 3109 int index, uint8 *acc_type) 3110 { 3111 soc_mem_info_t *mip; 3112 soc_mem_array_info_t *maip; 3113 3114 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 3115 return soc_mem_addr(unit, mem, array_index, block, index); 3116 } 3117 if (!SOC_MEM_IS_VALID(unit, mem)) { 3118 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 3119 LOG_CLI((BSL_META_U(unit, 3120 "mem %s is invalid\n"), soc_mem_name[mem])); 3121 #endif 3122 assert(SOC_MEM_IS_VALID(unit, mem)); 3123 } 3124 3125 assert(block >= 0 && block < SOC_MAX_NUM_BLKS); 3126 assert(index >= 0); 3127 3128 *acc_type = SOC_MEM_ACC_TYPE(unit, mem); 3129 #if defined(BCM_TRIUMPH_SUPPORT) 3130 if (soc_feature(unit, soc_feature_esm_support)) { 3131 if ((SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ESM) || 3132 (SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ETU)) { 3133 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit, 3134 mem, 3135 index, 3136 &mem, 3137 &index)); 3138 } 3139 } 3140 #endif 3141 3142 mip = &SOC_MEM_INFO(unit, mem); 3143 3144 #if defined(BCM_TRIUMPH3_SUPPORT) 3145 if (soc_feature(unit, soc_feature_etu_support)) { 3146 if (SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ISM) { 3147 if (mip->flags & (SOC_MEM_FLAG_CAM | SOC_MEM_FLAG_EXT_CAM)) { 3148 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit, 3149 mem, 3150 index, 3151 &mem, 3152 &index)); 3153 } 3154 } 3155 /* do it again if returned mem is different */ 3156 mip = &SOC_MEM_INFO(unit, mem); 3157 } 3158 #endif 3159 if (array_index) { 3160 /* non zero array index, implying this is a memory array */ 3161 assert (mip->flags & SOC_MEM_FLAG_IS_ARRAY); /* verify this is really a memory array */ 3162 maip = SOC_MEM_ARRAY_INFOP(unit, mem); 3163 assert(maip); /* verify this is memory array information exists */ 3164 assert(array_index >= maip->first_array_index && array_index < maip->numels + maip->first_array_index); /* verify that the array index is in range */ 3165 if (array_index > maip->first_array_index) { 3166 LOG_INFO(BSL_LS_SOC_MEM, 3167 (BSL_META_U(unit, 3168 "addr: %x, mip->base: %x, block: %x, " 3169 "index = %d, mip->gran: %d, * = %x, arr_in = %u, skip = %u\n"), 3170 mip->base + (index * mip->gran) + ((array_index - maip->first_array_index) * maip->element_skip), mip->base, 3171 SOC_BLOCK2OFFSET(unit, block), index, 3172 mip->gran, (index * mip->gran), array_index, maip->element_skip)); 3173 return mip->base + (index * mip->gran) + ((array_index - maip->first_array_index) * maip->element_skip); 3174 } else { 3175 LOG_INFO(BSL_LS_SOC_MEM, 3176 (BSL_META_U(unit, 3177 "addr: %x, mip->base: %x, block: %x, " 3178 "index = %d, mip->gran: %d, * = %x\n"), 3179 mip->base+(index * mip->gran), mip->base, 3180 SOC_BLOCK2OFFSET(unit, block), index, 3181 mip->gran, (index * mip->gran))); 3182 return mip->base + (index * mip->gran); 3183 } 3184 } else { 3185 /* non memory array acces, works also with index 0 of a memory array */ 3186 LOG_INFO(BSL_LS_SOC_MEM, 3187 (BSL_META_U(unit, 3188 "addr: %x, mip->base: %x, block: %x, " 3189 "index = %d, mip->gran: %d, * = %x\n"), 3190 mip->base+(index * mip->gran), mip->base, 3191 SOC_BLOCK2OFFSET(unit, block), index, 3192 mip->gran, (index * mip->gran))); 3193 return mip->base + (index * mip->gran); 3194 } 3195 } 3196 3197 3198 #define ACC_TYPE_MASK 0xE0000 3199 /* Translate a memory address to the memory using it 3200 * If array_index is not NULL and the found memory is a memory array, 3201 * then the array index is returned in array_index . 3202 */ 3203 soc_mem_t 3204 soc_addr_to_mem(int unit, uint32 address, uint32 *mem_block) 3205 { 3206 soc_mem_t mem; 3207 uint32 offset, min_addr, max_addr, block = 0; 3208 3209 offset = address & ~0xC0f00000; /* strip block id */ 3210 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 3211 offset &= ~ACC_TYPE_MASK; /* strip memAcc*/ 3212 } 3213 #ifdef BCM_DFE_SUPPORT 3214 if(SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_A0 || 3215 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_B0 || 3216 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88754_A0 || 3217 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88755_B0) { 3218 offset = (offset & 0x000fffff) | (((offset >> 24 ) & 0x3F) << 20); 3219 } 3220 #endif 3221 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3222 if (soc_mem_is_valid(unit, mem) && 3223 ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) { 3224 3225 min_addr = max_addr = SOC_MEM_INFO(unit, mem).base; 3226 if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 3227 min_addr = max_addr = max_addr & ~ACC_TYPE_MASK; /* strip memAcc*/ 3228 } 3229 min_addr += SOC_MEM_INFO(unit, mem).index_min; 3230 max_addr += SOC_MEM_INFO(unit, mem).index_max; 3231 if (SOC_MEM_IS_ARRAY(unit, mem)) { 3232 if (offset < min_addr || offset > max_addr + 3233 (SOC_MEM_NUMELS(unit, mem) - 1 + SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * SOC_MEM_ELEM_SKIP(unit, mem)) { 3234 continue; 3235 } 3236 /* now make sure that the address is legal for the memory array */ 3237 offset = (offset - min_addr) % SOC_MEM_ELEM_SKIP(unit, mem); /* calculate the array index and check it is in range */ 3238 if (offset >= SOC_MEM_NUMELS(unit, mem)) { 3239 continue; 3240 } 3241 offset += SOC_MEM_FIRST_ARRAY_INDEX(unit, mem); 3242 } else if (offset < min_addr || offset > max_addr) { 3243 continue; 3244 } 3245 3246 if (SOC_IS_XGS3_SWITCH(unit)) { 3247 /* Match block */ 3248 block = ((address >> SOC_BLOCK_BP) & 0xf) | 3249 (((address >> SOC_BLOCK_MSB_BP) & 0x3) << 4); 3250 if (block != SOC_BLOCK2OFFSET(unit, SOC_MEM_BLOCK_ANY(unit, mem))) { 3251 continue; 3252 } 3253 } 3254 if (mem_block) { 3255 *mem_block = block; 3256 } 3257 return mem; 3258 } 3259 } 3260 return INVALIDm; 3261 } 3262 int 3263 soc_addr_is_mem(int unit, int acc_type, uint32 block, int blk, uint32 offset, soc_mem_t mem) 3264 { 3265 uint32 min_addr, max_addr; 3266 int copyno; 3267 #ifdef BCM_TOMAHAWK3_SUPPORT 3268 uint32 block_tmp = block; 3269 int rv; 3270 #endif 3271 3272 if (soc_mem_is_valid(unit, mem) && 3273 ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) { 3274 #ifdef BCM_TOMAHAWK3_SUPPORT 3275 if (SOC_IS_TOMAHAWK3(unit)) { 3276 rv = soc_th3_mmu_mem_blk_remap(mem, &block); 3277 if (rv == SOC_E_NOT_FOUND) { 3278 block = block_tmp; 3279 } 3280 } 3281 #endif 3282 3283 min_addr = max_addr = SOC_MEM_INFO(unit, mem).base; 3284 min_addr += SOC_MEM_INFO(unit, mem).index_min; 3285 max_addr += SOC_MEM_INFO(unit, mem).index_max; 3286 if (SOC_MEM_IS_ARRAY(unit, mem)) { 3287 if (offset < min_addr || offset > max_addr + 3288 (SOC_MEM_NUMELS(unit, mem) - 1) * SOC_MEM_ELEM_SKIP(unit, mem)) { 3289 return FALSE; 3290 } 3291 /* now make sure that the address is legal for the memory array */ 3292 if ( (offset - min_addr) % SOC_MEM_ELEM_SKIP(unit, mem) /* in this line (index - index_min) is computed */ 3293 > max_addr - min_addr ) { /* Is the index too big */ 3294 return FALSE; 3295 } 3296 } else if (offset < min_addr || offset > max_addr) { 3297 return FALSE; 3298 } 3299 if (SOC_IS_XGS3_SWITCH(unit)) { 3300 3301 /* Match block */ 3302 SOC_MEM_BLOCK_ITER2(unit, mem, copyno) { 3303 if (block == SOC_BLOCK2OFFSET(unit, copyno)) { 3304 break; 3305 } 3306 } 3307 if (copyno > SOC_MEM_BLOCK_MAX(unit, mem)) { 3308 return FALSE; 3309 } 3310 3311 if ((acc_type >= 0) && 3312 (acc_type != SOC_MEM_ACC_TYPE(unit, mem))) { 3313 return FALSE; 3314 } 3315 } 3316 if (SOC_IS_SAND(unit) || SOC_IS_GREYHOUND(unit) 3317 || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3318 /* check that the memory belongs to the correct block */ 3319 if (blk != SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem))) { 3320 return FALSE; 3321 } 3322 } 3323 return TRUE; 3324 } 3325 3326 return FALSE; 3327 } 3328 /* Note: acc_type = -1 is used as don't care */ 3329 soc_mem_t 3330 soc_addr_to_mem_extended(int unit, uint32 block, int acc_type, uint32 address) 3331 { 3332 soc_mem_t mem; 3333 uint32 offset; 3334 int blk = -1; 3335 offset = address; 3336 #ifdef BCM_DFE_SUPPORT 3337 if(SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_A0 || 3338 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_B0 || 3339 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88754_A0 || 3340 SOC_DRIVER(unit)->type == SOC_CHIP_BCM88755_B0) { 3341 offset = (address & 0x000fffff) | (((address >>24 ) & 0x3F) << 20); 3342 } 3343 #endif 3344 if (SOC_IS_SAND(unit) || SOC_IS_GREYHOUND(unit) || 3345 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3346 /* Find the block of the given block */ 3347 for (blk = 0; ; ++blk) { 3348 if (SOC_BLOCK_TYPE(unit, blk) < 0) { 3349 return INVALIDm; 3350 } else if (SOC_BLOCK2OFFSET(unit, blk) == block) { 3351 break; 3352 } 3353 } 3354 #ifdef BCM_JERICHO_SUPPORT 3355 if (SOC_IS_JERICHO(unit) && SOC_BLOCK_IS_BROADCAST(unit, blk)) { 3356 blk = SOC_BLOCK_BROADCAST_MEMBER(unit, blk, 0); /* For broadcast blocks we want the type of the broadcast members */ 3357 } 3358 #endif /* BCM_JERICHO_SUPPORT */ 3359 blk = SOC_BLOCK_TYPE(unit, blk); /* Get block type for later comparisons from block */ 3360 } 3361 3362 /* first look in already used mems for optimization*/ 3363 if (soc_feature(unit, soc_feature_mem_direct_acc_last_used_first)) 3364 { 3365 3366 soc_mem_t last_used_mem = drvmem_last_used_mem_direct_acc[unit]; 3367 if (soc_addr_is_mem(unit, acc_type, block, blk, offset, last_used_mem)) 3368 { 3369 return last_used_mem; 3370 } 3371 } 3372 3373 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3374 if (soc_addr_is_mem(unit, acc_type, block, blk, offset, mem)) 3375 { 3376 if (soc_feature(unit, soc_feature_mem_direct_acc_last_used_first)) 3377 { 3378 drvmem_last_used_mem_direct_acc[unit] = mem; 3379 } 3380 return mem; 3381 } 3382 } 3383 3384 return INVALIDm; 3385 } 3386 3387 /* 3388 * Function: soc_mem_addr_to_array_element_and_index 3389 * Purpose: For the given memory and a given address of its entry, return 3390 * the entry index in index, and the array index in array_index. 3391 * If the memory is not an array the returned array index is 0. 3392 * Returns: SOC_E_NONE if adress is compatible to mem, otherwise - SOC_E_UNAVAIL 3393 */ 3394 int 3395 soc_mem_addr_to_array_element_and_index(int unit, soc_mem_t mem, uint32 address, 3396 unsigned* array_index, int* index) 3397 { 3398 int array_size_base; 3399 3400 if((NULL == array_index) || (NULL == index)){ 3401 return SOC_E_PARAM; 3402 } 3403 3404 /* address includes the offest of the memory | the entry index */ 3405 if (soc_mem_is_valid(unit, mem) && 3406 ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) { 3407 if (!SOC_MEM_IS_ARRAY(unit, mem)) { 3408 if((address < (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_min)) || 3409 (address > (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_max))) { 3410 return SOC_E_UNAVAIL; 3411 } else { 3412 *array_index = 0; 3413 *index = address - SOC_MEM_INFO(unit, mem).base; 3414 return SOC_E_NONE; 3415 } 3416 } else { 3417 /* for arrays */ 3418 if ((address < SOC_MEM_INFO(unit, mem).base) || 3419 (address > (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_max + 3420 (SOC_MEM_NUMELS(unit, mem) - 1) * SOC_MEM_ELEM_SKIP(unit, mem)))) { 3421 return SOC_E_UNAVAIL; 3422 } else { 3423 array_size_base = SOC_MEM_ELEM_SKIP(unit, mem); 3424 *array_index = ((address - SOC_MEM_INFO(unit, mem).base) / array_size_base + SOC_MEM_ARRAY_INFO(unit, mem).first_array_index); 3425 *index = (address - SOC_MEM_INFO(unit, mem).base) % array_size_base; 3426 return SOC_E_NONE; 3427 } 3428 } 3429 } 3430 else { 3431 return SOC_E_UNAVAIL; 3432 } 3433 } 3434 3435 /* 3436 * Function: soc_mem_entry_bits 3437 * Purpose: Get number of bits in entry 3438 * Returns: Number of bits in the entry 3439 */ 3440 int 3441 soc_mem_entry_bits(int unit, soc_mem_t mem) 3442 { 3443 int f, end; 3444 soc_field_info_t *fieldp; 3445 soc_mem_info_t *memp; 3446 int numbits = 0; 3447 3448 if (!SOC_MEM_IS_VALID(unit, mem)) { 3449 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 3450 LOG_CLI((BSL_META_U(unit, 3451 "mem %s is invalid\n"), soc_mem_name[mem])); 3452 #endif 3453 assert(SOC_MEM_IS_VALID(unit, mem)); 3454 } 3455 3456 memp = &SOC_MEM_INFO(unit, mem); 3457 3458 for (f = 0; f < memp->nFields; f++) { 3459 fieldp = &(memp->fields[f]); 3460 end = fieldp->bp + fieldp->len; 3461 if (end > numbits) { 3462 numbits = end; 3463 } 3464 } 3465 3466 return numbits; 3467 } 3468 3469 /* 3470 * Function: 3471 * soc_mem_snoop_register 3472 * Purpose: 3473 * Registers a snooping call back for specific memory. 3474 * Call back will be called on Read or Write operations 3475 * on the memory according to specified flags 3476 * Parameters: 3477 * unit - (IN) BCM device number. 3478 * mem - (IN) Memory to register a call back for. 3479 * flags - (IN) SOC_MEM_SNOOP_XXX flags. 3480 * snoop_cv - (IN) User provided call back, NULL for unregister 3481 * user_data - (IN) user provided data to be passed to call back function 3482 * Returns: 3483 * None 3484 */ 3485 void 3486 soc_mem_snoop_register(int unit, soc_mem_t mem, uint32 flags, 3487 soc_mem_snoop_cb_t snoop_cb, void *user_data) 3488 { 3489 soc_mem_info_t *mem_info_p; 3490 3491 if (!SOC_MEM_IS_VALID(unit, mem)) { 3492 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 3493 LOG_CLI((BSL_META_U(unit, 3494 "mem %s is invalid\n"), soc_mem_name[mem])); 3495 #endif 3496 assert(SOC_MEM_IS_VALID(unit, mem)); 3497 } 3498 3499 mem_info_p = &SOC_MEM_INFO(unit, mem); 3500 3501 assert(NULL != snoop_cb); 3502 3503 mem_info_p->snoop_cb = snoop_cb; 3504 mem_info_p->snoop_user_data = user_data; 3505 mem_info_p->snoop_flags |= flags; 3506 3507 return; 3508 } 3509 3510 /* 3511 * Function: 3512 * soc_mem_snoop_unregister 3513 * Purpose: 3514 * Unregisters a snooping call back with specific flag for specific memory. 3515 * This function will not fail even if call back was not previously 3516 * registered. 3517 * Parameters: 3518 * unit - (IN) BCM device number. 3519 * mem - (IN) Memory to register a call back for. 3520 * flags - (IN) SOC_MEM_SNOOP_XXX flags. 3521 * Returns: 3522 * None 3523 */ 3524 void 3525 soc_mem_snoop_unregister(int unit, soc_mem_t mem, uint32 flags) 3526 { 3527 soc_mem_info_t *mem_info_p; 3528 3529 if (!SOC_MEM_IS_VALID(unit, mem)) { 3530 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 3531 LOG_CLI((BSL_META_U(unit, 3532 "mem %s is invalid\n"), soc_mem_name[mem])); 3533 #endif 3534 assert(SOC_MEM_IS_VALID(unit, mem)); 3535 } 3536 3537 mem_info_p = &SOC_MEM_INFO(unit, mem); 3538 3539 if (SOC_MEM_SNOOP_UNREGISTER & flags) { 3540 mem_info_p->snoop_cb = NULL; 3541 mem_info_p->snoop_user_data = NULL; 3542 mem_info_p->snoop_flags = 0; 3543 } else { 3544 mem_info_p->snoop_flags &= ~flags; 3545 if (mem_info_p->snoop_flags == 0) { 3546 mem_info_p->snoop_cb = NULL; 3547 mem_info_p->snoop_user_data = NULL; 3548 } 3549 } 3550 3551 return; 3552 } 3553 #endif /* BCM_ESW_SUPPORT || BCM_SAND_SUPPORT || defined(PORTMOD_SUPPORT)*/ 3554 3555 #ifdef BCM_ESW_SUPPORT 3556 /* Resolve DESTINATIONf value to type and value 3557 * dest_type - OUT 3558 * value - OUT 3559 */ 3560 void _soc_mem_dest_value_resolve(int unit, uint32 dest_value, uint32 *enum_type, 3561 uint32 *value) 3562 { 3563 uint32 dest_type; 3564 3565 /* Decode application enum type and destination type */ 3566 *enum_type = SOC_MEM_FIF_DEST_INVALID; 3567 *value = 0; 3568 3569 if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE0f)) != 0) { 3570 switch (dest_type) { 3571 case 3: 3572 *enum_type = SOC_MEM_FIF_DEST_NEXTHOP; 3573 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value,NEXT_HOP_INDEXf); 3574 break; 3575 case 2: 3576 *enum_type = SOC_MEM_FIF_DEST_DGPP; 3577 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DGPPf); 3578 break; 3579 case 1: 3580 *enum_type = SOC_MEM_FIF_DEST_DVP; 3581 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DVPf); 3582 break; 3583 default: 3584 break; 3585 } 3586 } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE1f)) != 0) { 3587 switch (dest_type) { 3588 case 3: 3589 *enum_type = SOC_MEM_FIF_DEST_IPMC; 3590 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, IPMC_GROUPf); 3591 break; 3592 case 2: 3593 *enum_type = SOC_MEM_FIF_DEST_L2MC; 3594 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, L2MC_GROUPf); 3595 break; 3596 case 1: 3597 *enum_type = SOC_MEM_FIF_DEST_ECMP; 3598 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, ECMP_GROUPf); 3599 break; 3600 default: 3601 break; 3602 } 3603 } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE2f)) != 0) { 3604 switch (dest_type) { 3605 case 1: 3606 *enum_type = SOC_MEM_FIF_DEST_LAG; 3607 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, LAGf); 3608 break; 3609 default: 3610 break; 3611 } 3612 } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE3f)) != 0) { 3613 switch (dest_type) { 3614 case 3: 3615 *enum_type = SOC_MEM_FIF_DEST_MYSTA; 3616 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, MY_STATION_PROFILE_IDXf); 3617 break; 3618 default: 3619 break; 3620 } 3621 } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE5f)) !=0 ) { 3622 switch (dest_type) { 3623 case 3: 3624 *enum_type = SOC_MEM_FIF_DEST_DISC_CP2CPU; 3625 *value = 0; 3626 break; 3627 case 2: 3628 *enum_type = SOC_MEM_FIF_DEST_DISC; 3629 *value = 0; 3630 break; 3631 default: 3632 break; 3633 } 3634 } 3635 3636 return ; 3637 } 3638 3639 /* Construct DESTINATIONf value with type and value 3640 * return - DESTINATIONf value 3641 */ 3642 uint32 3643 _soc_mem_dest_value_construct(int unit, uint32 dest_type, uint32 value) 3644 { 3645 soc_field_t format_type_field = INVALIDf; 3646 uint32 format_type_field_value = 0; 3647 soc_field_t format_value_field = INVALIDf; 3648 uint32 format_value_field_value = 0; 3649 uint32 dest_value = 0; 3650 3651 switch (dest_type) { 3652 case SOC_MEM_FIF_DEST_NEXTHOP: 3653 format_type_field = DEST_TYPE0f; 3654 format_type_field_value = 3; 3655 format_value_field = NEXT_HOP_INDEXf; 3656 format_value_field_value = value; 3657 break; 3658 case SOC_MEM_FIF_DEST_DGPP: 3659 format_type_field = DEST_TYPE0f; 3660 format_type_field_value = 2; 3661 format_value_field = DGPPf; 3662 format_value_field_value = value; 3663 break; 3664 case SOC_MEM_FIF_DEST_DVP: 3665 format_type_field = DEST_TYPE0f; 3666 format_type_field_value = 1; 3667 format_value_field = DVPf; 3668 format_value_field_value = value; 3669 break; 3670 case SOC_MEM_FIF_DEST_IPMC: 3671 format_type_field = DEST_TYPE1f; 3672 format_type_field_value = 3; 3673 format_value_field = IPMC_GROUPf; 3674 format_value_field_value = value; 3675 break; 3676 case SOC_MEM_FIF_DEST_L2MC: 3677 format_type_field = DEST_TYPE1f; 3678 format_type_field_value = 2; 3679 format_value_field = L2MC_GROUPf; 3680 format_value_field_value = value; 3681 break; 3682 case SOC_MEM_FIF_DEST_ECMP: 3683 format_type_field = DEST_TYPE1f; 3684 format_type_field_value = 1; 3685 format_value_field = ECMP_GROUPf; 3686 format_value_field_value = value; 3687 break; 3688 case SOC_MEM_FIF_DEST_LAG: 3689 format_type_field = DEST_TYPE2f; 3690 format_type_field_value = 1; 3691 format_value_field = LAGf; 3692 format_value_field_value = value; 3693 break; 3694 case SOC_MEM_FIF_DEST_MYSTA: 3695 format_type_field = DEST_TYPE3f; 3696 format_type_field_value = 3; 3697 format_value_field = MY_STATION_PROFILE_IDXf; 3698 format_value_field_value = value; 3699 break; 3700 case SOC_MEM_FIF_DEST_DISC_CP2CPU: 3701 format_type_field = DEST_TYPE5f; 3702 format_type_field_value = 3; 3703 break; 3704 case SOC_MEM_FIF_DEST_DISC: 3705 format_type_field = DEST_TYPE5f; 3706 format_type_field_value = 2; 3707 break; 3708 default: 3709 dest_value = 0; 3710 break; 3711 } 3712 3713 /* Convert field data into format type */ 3714 if (format_type_field != INVALIDf) { 3715 soc_format_field32_set(unit, DESTINATION_FORMATfmt, &dest_value, format_type_field, format_type_field_value); 3716 } 3717 3718 if (format_value_field != INVALIDf) { 3719 soc_format_field32_set(unit, DESTINATION_FORMATfmt, &dest_value, format_value_field, format_value_field_value); 3720 } 3721 3722 return (dest_value); 3723 } 3724 3725 /* 3726 * soc_mem_field32_dest_set 3727 * 3728 * Based on application enum type, covert configuration value 3729 * to destination format and write it to hardware memory. 3730 */ 3731 void 3732 soc_mem_field32_dest_set(int unit, soc_mem_t mem, void *entbuf, 3733 soc_field_t fld, uint32 dest_type, uint32 value) 3734 { 3735 uint32 dest_value = 0; 3736 3737 /* Convert value into destination format */ 3738 dest_value = _soc_mem_dest_value_construct(unit, dest_type, value); 3739 3740 /* Write data (in format structure) to memory buffer */ 3741 soc_mem_field32_set(unit, mem, entbuf, fld, dest_value); 3742 3743 return; 3744 } 3745 3746 /* 3747 * soc_mem_field32_dest_get 3748 * 3749 * Derive application enum type and destination value from hardware readout 3750 * based on destination format. 3751 */ 3752 uint32 3753 soc_mem_field32_dest_get(int unit, soc_mem_t mem, const void *entbuf, 3754 soc_field_t fld, uint32 *enum_type) 3755 { 3756 uint32 dest_value; 3757 uint32 value = 0; 3758 3759 /* Hardware memory readout */ 3760 dest_value = soc_mem_field32_get(unit, mem, entbuf, fld); 3761 3762 /* Decode readout from destination format */ 3763 _soc_mem_dest_value_resolve(unit, dest_value, enum_type, &value); 3764 3765 return value; 3766 } 3767 #endif /* End of BCM_ESW_SUPPORT */