symtab.c (40979B)
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 * Register mnemonic address parsing routines. 8 * See description for parse_symbolic_reference. 9 * This module is used by command line shells. 10 */ 11 12 #include <shared/bsl.h> 13 14 #include <sal/core/libc.h> 15 #include <shared/bsl.h> 16 #include <soc/debug.h> 17 #include <soc/cm.h> 18 #include <soc/register.h> 19 #include <soc/util.h> 20 #include <appl/diag/system.h> 21 #include <appl/diag/dport.h> 22 #if defined(BCM_KATANA2_SUPPORT) 23 #include <soc/katana2.h> 24 #endif 25 #if defined(BCM_GREYHOUND_SUPPORT) 26 #include <soc/greyhound.h> 27 #endif 28 #if defined(BCM_SABER2_SUPPORT) 29 #include <soc/saber2.h> 30 #endif 31 #if defined(BCM_METROLITE_SUPPORT) 32 #include <soc/metrolite.h> 33 #endif 34 35 #ifdef SOC_COUNTER_TABLE_SUPPORT 36 #include <soc/mcm/driver.h> 37 #endif 38 #if defined(BCM_PETRA_SUPPORT) 39 #include <soc/dpp/port_sw_db.h> 40 #endif 41 42 /* 43 * Symbol hash table entry with buckets represented by linked list. 44 */ 45 46 typedef struct symtab_entry_t { 47 soc_reg_t esw_reg; 48 char *name; 49 struct symtab_entry_t *next; 50 } symtab_entry_t; 51 52 static symtab_entry_t *symtab_table; 53 54 /* 55 * Statically allocated table with pointers 56 * to globally allocated registers table. 57 */ 58 59 static symtab_entry_t *hashtable[NUM_SOC_REG]; 60 61 /* 62 * Case-independent hash routine, where we store a symbol table 63 * entry (front end) in the hash table. If we 64 * hit on that entry, then we chain it at the 65 * same base memory address. 66 */ 67 68 static int 69 hash_func(char *s) 70 { 71 uint32 h = 0, c; 72 73 while ((c = *s++) != 0) 74 h = (h << 3) ^ h ^ (h >> 7) ^ (islower(c) ? sal_toupper(c) : (c)); 75 return (h % NUM_SOC_REG); 76 } 77 78 /* 79 * Initialize register symbol table. Hash all of the values in 80 * the registers file into an address table we can lookup by 81 * string mnemonic. 82 */ 83 84 void 85 _add_symbol(char *name, soc_reg_t reg, int ent, int *chained) 86 { 87 int key; 88 symtab_entry_t *table_entry; 89 90 key = hash_func(name); 91 92 /* Chain entry */ 93 table_entry = &symtab_table[ent]; 94 table_entry->name = name; 95 table_entry->esw_reg = reg; 96 97 table_entry->next = hashtable[key]; 98 if (hashtable[key]) { 99 (*chained)++; 100 } 101 hashtable[key] = table_entry; 102 } 103 104 105 /* 106 * Lookup a register in the symbol table. 107 * Returns register number from matching entry 108 * There may be both a register name and an alias that are 109 * identical (AGE_TIMER, for example). If one is a valid 110 * register for this unit and another is invalid, the 111 * valid register is returned. 112 * 113 * NOTE: hash_func is case-independent, so lookup_register is also. 114 */ 115 116 static symtab_entry_t* 117 lookup_register(int unit, char *regname) 118 { 119 symtab_entry_t *loc, *floc; 120 121 floc = NULL; 122 for (loc = hashtable[hash_func(regname)]; loc; loc = loc->next) { 123 if(!sal_strcasecmp(loc->name, regname)) { 124 if (floc == NULL) { /* save first match */ 125 floc = loc; 126 } 127 #if defined(BCM_ESW_SUPPORT) 128 if (SOC_REG_IS_VALID(unit, loc->esw_reg)) { 129 return loc; 130 } 131 #ifdef SOC_COUNTER_TABLE_SUPPORT 132 if (SOC_REG_IS_COUNTER_TABLE(unit, loc->esw_reg)) { 133 return loc; 134 } 135 #endif /* SOC_COUNTER_TABLE_SUPPORT */ 136 #endif 137 } 138 } 139 140 return (floc != NULL) ? floc : NULL; 141 } 142 143 144 void 145 init_symtab() 146 { 147 soc_reg_t reg; 148 int c, d, lin, emp, lon, len, ent; 149 symtab_entry_t *te; 150 #ifdef SOC_COUNTER_TABLE_SUPPORT 151 152 soc_driver_t *drv = &soc_driver_bcm56980_a0; 153 #endif 154 155 if (symtab_table != NULL) { 156 return; 157 } 158 159 /* count how many table entries to allocate for ESW */ 160 ent = 0; 161 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 162 for (reg = 0; reg < NUM_SOC_REG; reg++) { 163 ent++; 164 #if !defined(SOC_NO_ALIAS) 165 if (soc_reg_alias[reg] && *soc_reg_alias[reg]) { 166 ent++; 167 } 168 #endif /* !defined(SOC_NO_ALIAS) */ 169 } 170 #endif 171 #ifdef SOC_COUNTER_TABLE_SUPPORT 172 ent += drv->ctr_tbl_info->num; 173 #endif 174 175 symtab_table = sal_alloc(ent * sizeof(symtab_entry_t), "symtab_table"); 176 if (NULL == symtab_table) { 177 return; /* how to signal failure? */ 178 } 179 180 ent = 0; 181 d = 1; 182 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 183 /* Load the hashtable with each reserved word */ 184 /* ESW */ 185 for (reg = 0; reg < NUM_SOC_REG; reg++) { 186 #if !defined(SOC_NO_NAMES) 187 _add_symbol(soc_reg_name[reg], reg, ent, &d); 188 ent += 1; 189 #endif /* !SOC_NO_NAMES */ 190 #if !defined(SOC_NO_ALIAS) 191 if (soc_reg_alias[reg] && *soc_reg_alias[reg]) { 192 _add_symbol(soc_reg_alias[reg], reg, ent, &d); 193 ent += 1; 194 } 195 #endif /* !defined(SOC_NO_ALIAS) */ 196 } 197 198 #ifdef SOC_COUNTER_TABLE_SUPPORT 199 #if !defined(SOC_NO_NAMES) 200 { 201 soc_field_t fld; 202 203 for (reg = 0; reg < drv->ctr_tbl_info->num; reg++) { 204 fld = drv->ctr_tbl_info->tables[reg].ctr_field; 205 _add_symbol(soc_fieldnames[fld], 206 (fld + SOC_COUNTER_TABLE_FIELD_START), ent, &d); 207 ent += 1; 208 } 209 } 210 #endif /* !SOC_NO_NAMES */ 211 #endif /* SOC_COUNTER_TABLE_SUPPORT */ 212 213 #endif 214 215 c = ent + 1; 216 lin = d-c > c-d ? d-c : c-d; 217 emp = lon = 0; 218 219 /* count number of empties and longest chain */ 220 for (reg = 0; reg < NUM_SOC_REG; reg++) { 221 te = hashtable[reg]; 222 if (te == NULL) { 223 emp += 1; 224 continue; 225 } 226 len = 1; 227 while (te->next != NULL) { 228 len += 1; 229 te = te->next; 230 } 231 if (len > lon) { 232 lon = len; 233 } 234 } 235 236 /* 237 * this actually happens too early to print out 238 * a printf here shows: 239 * symtab: init 1028 regs, 1119 symbols, 674 linear, 445 chained 240 * 345 empty, 5 longest chain 241 */ 242 LOG_INFO(BSL_LS_APPL_SYMTAB, 243 (BSL_META("symtab: init %d regs, %d symbols, %d linear, %d chained,\n" 244 "\t\t%d empty, %d longest chain\n"), 245 NUM_SOC_REG, c, lin, d, emp, lon)); 246 247 } 248 249 #ifdef SOC_COUNTER_TABLE_SUPPORT 250 static void 251 _handle_counter_table_refs(int unit, soc_regaddrlist_t *alist, soc_reg_t reg, soc_port_t port) { 252 253 soc_regaddrinfo_t *a; 254 255 if(!SOC_REG_IS_COUNTER_TABLE(unit, reg)) { 256 return; 257 } 258 259 a = &alist->ainfo[alist->count++]; 260 a->valid = 1; 261 a->idx = 0; 262 a->reg = reg; 263 a->port = port; 264 265 } 266 #endif /* SOC_COUNTER_TABLE_SUPPORT */ 267 268 static void 269 _handle_array_refs(int unit, soc_regaddrlist_t *alist, 270 soc_reg_t reg, int block, 271 soc_cos_t cos, soc_port_t port, 272 int minidx, int maxidx) 273 { 274 #if defined(BCM_PETRA_SUPPORT) 275 int rc = 0; 276 uint32 offset = 0; 277 #endif 278 int idx; 279 soc_regaddrinfo_t *a; 280 uint32 flags = SOC_REG_INFO(unit, reg).flags; 281 282 bsl_log_add(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, unit, 283 "symtab: lookup reg %d blk %d cos %d port %d index %d:%d\n", 284 reg, block, cos, port, minidx, maxidx); 285 286 /* Ignore invalid ports, don't check if the port is really a instance id */ 287 if ((!(port & SOC_REG_ADDR_INSTANCE_MASK)) && port != REG_PORT_ANY && !SOC_PORT_VALID(unit, port) && 288 (SOC_REG_INFO(unit, reg).regtype != soc_ppportreg)) { 289 return; 290 } 291 292 for (idx = minidx; idx <= maxidx; idx++) { 293 if (flags & SOC_REG_FLAG_NO_DGNL) { 294 /* Skip diagonals. */ 295 if (idx == port) { 296 continue; 297 } 298 } 299 a = &alist->ainfo[alist->count++]; 300 a->valid = 1; 301 a->idx = idx; 302 a->reg = reg; 303 a->block = block; 304 a->port = port; 305 a->field = INVALIDf; 306 a->cos = cos; 307 a->is_custom = 0; 308 /* calculate address based on reg type */ 309 switch (SOC_REG_INFO(unit, reg).regtype) { 310 case soc_customreg: 311 #if defined(BCM_PETRA_SUPPORT) 312 rc = soc_port_sw_db_protocol_offset_get(unit, port, 0, &offset); 313 if (rc < 0) { 314 return; 315 } 316 317 a->block = ((offset < 2) ? ILKN_PMH_BLOCK(unit) : (offset < 4 ? ILKN_PML_BLOCK(unit, 0) : ILKN_PML_BLOCK(unit, 1))); 318 #endif 319 a->is_custom = 1; 320 break; 321 case soc_cosreg: 322 idx = cos; 323 /* FALLTHROUGH */ 324 case soc_cpureg: 325 case soc_mcsreg: 326 case soc_iprocreg: 327 case soc_portreg: 328 case soc_ppportreg: 329 case soc_genreg: 330 case soc_phy_reg: 331 case soc_pipereg: 332 case soc_xpereg: 333 case soc_itmreg: 334 case soc_ebreg: 335 case soc_slicereg: 336 case soc_layerreg: 337 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 338 { 339 if (!soc_feature(unit, soc_feature_new_sbus_format)) { 340 a->addr = soc_reg_addr(unit, reg, port, idx); 341 } else { 342 int blk; 343 uint8 at; 344 a->addr = soc_reg_addr_get(unit, reg, port, idx, 345 SOC_REG_ADDR_OPTION_NONE, 346 &blk, &at); 347 } 348 } 349 #endif 350 break; 351 default: 352 assert(0); 353 a->addr = 0; 354 break; 355 } 356 357 /* 358 * Check if this register is actually implemented 359 * in HW for the specified port/cos. 360 */ 361 /* coverity[OVERRUN: FALSE] */ 362 if (reg_mask_subset(unit, a, NULL) && 363 (!SOC_REG_BLOCK_IS(unit, reg, SOC_BLK_CCH))) { 364 alist->count--; 365 } 366 } 367 } 368 369 /* Check string starting at name for [ and ] */ 370 static int 371 _parse_array(char *name, char **out1, char **out2) 372 { 373 char *idx1, *idx2, *tmpchr; 374 int rv = 0; 375 376 if ((idx1 = sal_strchr(name, '[')) != 0) { 377 rv = 1; 378 *idx1++ = 0; 379 if ((tmpchr = sal_strchr(idx1, ']')) == 0) { 380 LOG_WARN(BSL_LS_APPL_SYMTAB, 381 (BSL_META("Could not parse index in %s.\n"), name)); 382 } else { 383 *tmpchr = 0; 384 } 385 if ((idx2 = sal_strchr(idx1, '-')) != 0) { 386 *idx2++ = 0; 387 } 388 } else if ((idx1 = sal_strchr(name, '(')) != 0) { 389 rv = 1; 390 *idx1++ = 0; 391 if ((tmpchr = sal_strchr(idx1, ')')) == 0) { 392 LOG_WARN(BSL_LS_APPL_SYMTAB, 393 (BSL_META("Could not parse index in %s.\n"), name)); 394 } else { 395 *tmpchr = 0; 396 } 397 if ((idx2 = sal_strchr(idx1, '-')) != 0) { 398 *idx2++ = 0; 399 } 400 } else { 401 idx2 = 0; 402 } 403 404 *out1 = idx1; 405 *out2 = idx2; 406 407 return rv; 408 } 409 410 /* 411 * Parse a symbolic register reference. 412 * 413 * Fills in soc_regaddrlist_t, which is an array of soc_regaddrinfo_t. 414 * Returns 0 on success, -1 on syntax error. 415 * 416 * Understands the following: 417 * 418 * regname -Port register, all ports 419 * regname.PBMP -Port register, selected ports 420 * 421 * regname -Generic register, all PICs or MMU 422 * regname.BLK_RANGE -Generic register, selected PICs 423 * 424 * regname -COS register, all COS values, all PICs or MMU 425 * regname.COS_RANGE -COS register, selected COS's, all PICs 426 * regname..BLK_RANGE -COS register, all COS values, selected PICs 427 * regname.COS_RANGE.BLK_RANGE -COS register, selected COS's, selected PICs 428 * 429 * In addition, [index range] may be specified. It can be specified for 430 * register, but for non-array registers, it must be 0. All array indices 431 * are 0-based. 432 * 433 * If a leading '$' is present, it is ignored. 434 * 435 * See util.c:parse_pbmp() for PBMP format 436 * See util.c:parse_num_range() for COS_RANGE format 437 * See util.c:parse_block_range() for BLK_RANGE format 438 * 439 * Register addressing 440 * soc_reg_addr(unit, port, index) 441 * - port is REG_PORT_ANY for non-pic regs 442 * - index is the cos number for COS regs 443 * 444 * Prints a warning and returns -1 if unit does not support the 445 * register. 446 */ 447 448 int 449 parse_symbolic_reference(int unit, soc_regaddrlist_t *alist, char *ref) 450 { 451 char rname[80], *range1, *range2, *idx1, *idx2, *regtype_name; 452 soc_port_t port, phy_port, dport; 453 int legal_max, legal_min, range; 454 soc_cos_t cos_min, cos_max, cos; 455 int blk_min, blk_max, blk = 0; 456 soc_block_t portblktype; 457 soc_block_types_t regblktype, bmask = NULL; 458 soc_reg_t reg; 459 pbmp_t bm; 460 soc_reg_info_t *reginfo; 461 int maxidx, minidx, idxfound = 0; 462 char pfmt[SOC_PBMP_FMT_LEN]; 463 symtab_entry_t *et; 464 int idx = 0, match = 0, max_block=0, port_num_blktype; 465 466 LOG_INFO(BSL_LS_APPL_SYMTAB, 467 (BSL_META_U(unit, 468 "parsing: %s\n"), ref)); 469 470 if (*ref == '$') { 471 ref++; 472 } 473 474 sal_strncpy(rname, ref, 79); 475 rname[79] = 0; 476 477 if ((range1 = sal_strchr(rname, '.')) != 0) { 478 *range1++ = '\0'; 479 idxfound = _parse_array(range1, &idx1, &idx2); 480 481 if ((range2 = sal_strchr(range1, '.')) != 0) { 482 *range2++ = '\0'; 483 if (*range2 == '\0') { 484 range2 = 0; 485 } 486 } 487 if (*range1 == '\0') { 488 range1 = 0; 489 } 490 } else { 491 range2 = 0; 492 } 493 494 if (!idxfound) { 495 idxfound = _parse_array(rname, &idx1, &idx2); 496 } 497 498 et = lookup_register(unit, rname); 499 if (NULL == et) { 500 return -1; 501 } 502 503 reg = et->esw_reg; 504 505 506 507 if (!SOC_REG_IS_VALID(unit, reg) && !SOC_REG_IS_COUNTER_TABLE(unit, reg)) { 508 LOG_WARN(BSL_LS_APPL_SYMTAB, 509 (BSL_META_U(unit, 510 "Register %s %d is not valid for chips using driver %s\n"), 511 et->name, reg, SOC_UNIT_NAME(unit))); 512 return -1; 513 } 514 515 #ifdef SOC_COUNTER_TABLE_SUPPORT 516 if(SOC_REG_IS_COUNTER_TABLE(unit, reg)) { 517 if (range2) { 518 return -1; 519 } 520 521 if (!range1) { 522 SOC_PBMP_CLEAR(bm); 523 SOC_PBMP_ASSIGN(bm, PBMP_CD_ALL(unit)); 524 } else if (parse_pbmp(unit, range1, &bm) < 0) { 525 return -1; 526 } 527 528 SOC_PBMP_ITER(bm, port) { 529 _handle_counter_table_refs(unit, alist, reg, port); 530 } 531 532 return (alist->count > 0)? 0: -1; 533 } 534 #endif /* SOC_COUNTER_TABLE_SUPPORT */ 535 536 reginfo = &SOC_REG_INFO(unit, reg); 537 if (!SOC_REG_IS_ENABLED(unit, reg)) { 538 #if defined(BCM_ESW_SUPPORT) 539 LOG_WARN(BSL_LS_APPL_SYMTAB, 540 (BSL_META_U(unit, 541 "Register %s is not enabled for this configuration\n"), 542 SOC_REG_NAME(unit, reg))); 543 #endif 544 return -1; 545 } 546 regblktype = reginfo->block; 547 548 #ifdef BCM_TOMAHAWK3_SUPPORT 549 if (SOC_IS_TOMAHAWK3(unit)) { 550 /* Since TH3 has the dummy blocks CDMAC defined in the regsfile, we need 551 to assign them to the CDPORT block */ 552 if (regblktype[0] == SOC_BLK_CDMAC) { 553 regblktype[0] = SOC_BLK_CDPORT; 554 } 555 } 556 #endif 557 558 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 559 /* max_block = _soc_max_blocks_per_entry_get(); */ 560 /* _soc_max_blocks_per_entry_get() + 1 is also enough but for 561 future safe purpose*/ 562 max_block = SOC_MAX_NUM_BLKS; 563 #endif 564 565 bmask = sal_alloc(sizeof(uint32) * max_block, 566 "parse_bmask"); 567 if (NULL == bmask) { 568 return -1; 569 } 570 sal_memset(bmask, 0, sizeof(uint32) * max_block); 571 572 if (diag_parse_range(idx1, idx2, &minidx, &maxidx, 573 SOC_REG_ARRAY(unit, reg) ? SOC_REG_INFO(unit, reg).first_array_index : -1, 574 SOC_REG_ARRAY(unit, reg) ? SOC_REG_NUMELS(unit,reg) + SOC_REG_INFO(unit, reg).first_array_index - 1 : -1) < 0) { 575 LOG_WARN(BSL_LS_APPL_SYMTAB, 576 (BSL_META_U(unit, 577 "Register %s: bad index specification\n"), ref)); 578 goto _return_error; 579 } 580 581 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, 582 "symtab: index %d:%d type %d regblktype [ ", 583 minidx, maxidx, reginfo->regtype); 584 while (regblktype[idx] != SOC_BLOCK_TYPE_INVALID) { 585 bsl_log_add(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 586 unit, "%s ", 587 soc_block_name_lookup_ext(regblktype[idx], unit)); 588 idx++; 589 } 590 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 591 unit, "]\n"); 592 593 alist->count = 0; 594 595 switch (reginfo->regtype) { 596 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 597 case soc_cpureg: 598 case soc_mcsreg: 599 case soc_iprocreg: 600 if (range2) { 601 goto _return_error; 602 } 603 604 /* parse block spec in range1 */ 605 if (parse_block_range(unit, regblktype, range1, 606 &blk_min, &blk_max, bmask) < 0) { 607 goto _return_error; 608 } 609 idx = 0; 610 while (bmask[idx] != 0) { 611 if (SOC_BLOCK_IN_LIST(regblktype, bmask[idx])) { 612 break; 613 } 614 idx++; 615 } 616 if ((idx > 0) && (match == 0)) { 617 goto _return_error; 618 } 619 if (blk_min < 0 || blk_max > SOC_INFO(unit).block_num) { 620 goto _return_error; 621 } 622 623 blk = CMIC_BLOCK(unit); 624 if (blk_min > blk || blk_max < blk) { 625 goto _return_error; 626 } 627 628 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, ""); 629 _handle_array_refs(unit, alist, reg, 630 blk, 631 -1, /* cos */ 632 REG_PORT_ANY, /* port */ 633 minidx, maxidx); 634 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 635 unit, ""); 636 break; 637 #endif /* ESW ONLY */ 638 case soc_ppportreg: 639 /* parse port spec in range1 */ 640 if (! range1) { 641 SOC_PBMP_ASSIGN(bm, PBMP_PP_ALL(unit)); 642 } else if (parse_pp_pbmp(unit, range1, &bm) < 0) { 643 goto _return_error; 644 } 645 LOG_VERBOSE(BSL_LS_APPL_SYMTAB, 646 (BSL_META_U(unit, 647 "symtab: ppport bitmap %s\n"), 648 SOC_PBMP_FMT(bm, pfmt))); 649 switch (regblktype[0]) { 650 case SOC_BLK_IPIPE: 651 blk = IPIPE_BLOCK(unit); 652 break; 653 case SOC_BLK_EPIPE: 654 blk = EPIPE_BLOCK(unit); 655 break; 656 default: 657 goto _return_error; 658 } 659 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, ""); 660 SOC_PBMP_ITER(bm, port) { 661 _handle_array_refs(unit, alist, reg, 662 blk, 663 -1, /* cos */ 664 port, 665 minidx, maxidx); 666 } 667 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 668 unit, ""); 669 break; 670 case soc_customreg: 671 if (range2) { 672 goto _return_error; 673 } 674 portblktype = SOC_BLK_PORT; 675 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype > 1 ? 676 SOC_DRIVER(unit)->port_num_blktype : 1 ; 677 678 /* parse port spec in range1 */ 679 if (! range1) { 680 BCM_PBMP_ASSIGN(bm, SOC_INFO(unit).custom_reg_access.custom_port_pbmp); 681 } else if (parse_pbmp(unit, range1, &bm) < 0) { 682 goto _return_error; 683 } 684 BCM_PBMP_ITER(bm, port) { /* update alist for every port in bm */ 685 _handle_array_refs(unit, alist, reg, blk, -1, port, minidx, maxidx); 686 } 687 LOG_VERBOSE(BSL_LS_APPL_SYMTAB,(BSL_META_U(unit, "symtab: port bitmap %s\n"),SOC_PBMP_FMT(bm, pfmt))); 688 break; 689 690 case soc_portreg: 691 if (range2) { 692 goto _return_error; 693 } 694 695 portblktype = SOC_BLK_PORT; 696 port_num_blktype = SOC_DRIVER(unit)->port_num_blktype > 1 ? 697 SOC_DRIVER(unit)->port_num_blktype : 1; 698 699 /* parse port spec in range1 */ 700 if (! range1) { 701 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 702 703 #ifdef BCM_DNX_SUPPORT 704 if (SOC_IS_DNX(unit)) { 705 int is_cdmac_block = 0; 706 SOC_PBMP_CLEAR(bm); 707 708 /* 709 * Convert CDMAC to CDPORT to get SOC_BLOCK_BITMAP 710 */ 711 if(regblktype[0] == SOC_BLK_CDMAC) { 712 is_cdmac_block = 1; 713 regblktype[0] = SOC_BLK_CDPORT; 714 } 715 716 SOC_BLOCKS_ITER(unit, blk, regblktype) { 717 SOC_PBMP_OR(bm, SOC_BLOCK_BITMAP(unit, blk)); 718 } 719 720 if(is_cdmac_block) { 721 regblktype[0] = SOC_BLK_CDMAC; 722 } 723 } 724 else 725 #endif 726 { 727 SOC_PBMP_CLEAR(bm); 728 729 SOC_BLOCKS_ITER(unit, blk, regblktype) { 730 SOC_PBMP_OR(bm, SOC_BLOCK_BITMAP(unit, blk)); 731 } 732 } 733 734 735 } else { 736 SOC_PBMP_ASSIGN(bm, PBMP_ALL(unit)); 737 if ((soc_feature(unit, soc_feature_linkphy_coe) && 738 SOC_INFO(unit).linkphy_enabled) || 739 (soc_feature(unit, soc_feature_subtag_coe) && 740 SOC_INFO(unit).subtag_enabled)) { 741 SOC_PBMP_CLEAR(bm); 742 SOC_PBMP_ASSIGN(bm, PBMP_PORT_ALL(unit)); 743 SOC_PBMP_PORT_ADD(bm, CMIC_PORT(unit)); 744 SOC_PBMP_PORT_ADD(bm, LB_PORT(unit)); 745 } 746 SOC_PBMP_OR(bm, PBMP_MMU(unit)); 747 } 748 #ifdef BCM_GREYHOUND_SUPPORT 749 if ((SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) 750 && (regblktype[0] == SOC_BLK_XLPORT)) { 751 int rv; 752 rv = soc_greyhound_pgw_reg_blk_index_get(unit, reg, REG_PORT_ANY, 753 &bm, NULL, NULL, 0); 754 if ((rv < 0) && (rv != SOC_E_NOT_FOUND)){ 755 goto _return_error; 756 } 757 } 758 #endif 759 } else if (parse_pbmp(unit, range1, &bm) < 0) { 760 goto _return_error; 761 } 762 LOG_VERBOSE(BSL_LS_APPL_SYMTAB, 763 (BSL_META_U(unit, 764 "symtab: port bitmap %s\n"), 765 SOC_PBMP_FMT(bm, pfmt))); 766 767 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, ""); 768 /* Coverity 769 * DPORT_SOC_PBMP_ITER checks that dport is valid. 770 */ 771 /* coverity[overrun-local] */ 772 DPORT_SOC_PBMP_ITER(unit, bm, dport, port) { 773 if (SOC_BLOCK_IN_LIST(regblktype, portblktype)) { 774 if (soc_feature(unit, soc_feature_logical_port_num)) { 775 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 776 } else { 777 phy_port = port; 778 } 779 for (idx = 0; idx < port_num_blktype; idx++) { 780 #ifdef BCM_KATANA2_SUPPORT 781 /* Override port blocks with Linkphy Blocks.. */ 782 if(SOC_IS_KATANA2(unit) && (regblktype[0] == SOC_BLK_TXLP) ) { 783 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 784 SOC_BLK_TXLP, &blk, NULL); 785 break; 786 } else if(SOC_IS_KATANA2(unit) && 787 (regblktype[0] == SOC_BLK_RXLP)) { 788 soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 789 SOC_BLK_RXLP, &blk, NULL); 790 break; 791 } 792 #endif 793 #ifdef BCM_GREYHOUND_SUPPORT 794 if ((SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) 795 && (regblktype[0] == SOC_BLK_XLPORT)) { 796 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 797 NULL, &blk, NULL, 0) > 0){ 798 break; 799 } 800 } 801 #endif 802 #ifdef BCM_METROLITE_SUPPORT 803 /* For metrolite, override port block with IECELL block */ 804 if ((SOC_IS_METROLITE(unit)) && 805 (regblktype[0] == SOC_BLK_IECELL)) { 806 soc_ml_iecell_port_reg_blk_idx_get(unit, port, 807 SOC_BLK_IECELL, &blk, NULL); 808 break; 809 } else 810 #endif 811 #if defined (BCM_SABER2_SUPPORT) 812 /* For saber2, override port block with IECELL block */ 813 if ((SOC_IS_SABER2(unit)) && 814 (regblktype[0] == SOC_BLK_IECELL)) { 815 soc_sb2_iecell_port_reg_blk_idx_get(unit, port, 816 SOC_BLK_IECELL, &blk, NULL); 817 break; 818 } 819 #endif 820 821 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, idx); 822 if (blk < 0) { 823 break; 824 } 825 if(SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CPRI){ 826 if (!(IS_CPRI_PORT(unit,port) || IS_RSVD4_PORT(unit,port))) { 827 continue; 828 } 829 } 830 if (SOC_IS_APACHE(unit) && ((phy_port == 17) || (phy_port == 53))) { 831 if ((SOC_INFO(unit).port_speed_max[port] >= 100000) && (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORT)) { 832 continue; 833 } 834 } 835 836 if (SOC_BLOCK_IN_LIST(regblktype, 837 SOC_BLOCK_TYPE(unit, blk))) { 838 break; 839 } 840 841 if (SOC_IS_DNX(unit)) { 842 if( (regblktype[0] == SOC_BLK_CDMAC) && (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CDPORT) ) { 843 /* 844 * DNX only: CDMAC case. 845 * SOC_PORT_IDX_BLOCK returns CDPORT, therefore check type of blk is CDPORT. 846 */ 847 break; 848 } 849 } 850 851 } 852 #ifdef BCM_GREYHOUND_SUPPORT 853 if ((SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) 854 && (regblktype[0] == SOC_BLK_XLPORT)) { 855 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 856 NULL, &blk, NULL, 1) > 0){ 857 continue; 858 } 859 } 860 #endif 861 if (blk < 0 || idx == port_num_blktype) { 862 goto _return_error; 863 } 864 } else { 865 int instance = -1; 866 /* This big switch statement will go away soon */ 867 { 868 switch (regblktype[0]) { 869 case SOC_BLK_IPIPE: 870 blk = IPIPE_BLOCK(unit); 871 break; 872 case SOC_BLK_IPIPE_HI: 873 blk = IPIPE_HI_BLOCK(unit); 874 /* coverity[overrun-local] */ 875 if (!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, blk), port)) { 876 continue; 877 } 878 break; 879 case SOC_BLK_EPIPE: 880 blk = EPIPE_BLOCK(unit); 881 break; 882 case SOC_BLK_EPIPE_HI: 883 blk = EPIPE_HI_BLOCK(unit); 884 if (!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, blk), port)) { 885 continue; 886 } 887 break; 888 case SOC_BLK_IGR: 889 blk = IGR_BLOCK(unit); 890 break; 891 case SOC_BLK_EGR: 892 blk = EGR_BLOCK(unit); 893 break; 894 case SOC_BLK_BSE: /* Aliased with IL */ 895 if (SOC_IS_SHADOW(unit)) { 896 if (port == 9) { 897 blk = IL0_BLOCK(unit); 898 } else if (port == 13) { 899 blk = IL1_BLOCK(unit); 900 } 901 } else { 902 blk = BSE_BLOCK(unit); 903 } 904 break; 905 case SOC_BLK_CSE: /* Aliased with MS_ISEC */ 906 if (SOC_IS_SHADOW(unit)) { 907 if (port >=1 && port <= 4) { 908 blk = MS_ISEC0_BLOCK(unit); 909 } else if (port >= 5 && port <= 8) { 910 blk = MS_ISEC1_BLOCK(unit); 911 } 912 } else { 913 blk = CSE_BLOCK(unit); 914 } 915 break; 916 case SOC_BLK_HSE: /* Aliased with MS_ESEC */ 917 if (SOC_IS_SHADOW(unit)) { 918 if (port >= 1 && port <= 4) { 919 blk = MS_ESEC0_BLOCK(unit); 920 } else if (port >= 5 && port <= 8) { 921 blk = MS_ESEC1_BLOCK(unit); 922 } 923 } else { 924 blk = HSE_BLOCK(unit); 925 } 926 break; 927 case SOC_BLK_SYS: /* Aliased with CW */ 928 if (SOC_IS_SHADOW(unit)) { 929 blk = CW_BLOCK(unit); 930 } 931 break; 932 case SOC_BLK_BSAFE: 933 blk = BSAFE_BLOCK(unit); 934 break; 935 case SOC_BLK_ESM: 936 blk = ESM_BLOCK(unit); 937 break; 938 case SOC_BLK_ARL: 939 blk = ARL_BLOCK(unit); 940 break; 941 case SOC_BLK_MMU: 942 blk = MMU_BLOCK(unit); 943 break; 944 case SOC_BLK_MCU: 945 blk = MCU_BLOCK(unit); 946 break; 947 case SOC_BLK_PGW_CL: 948 /* coverity[overrun-local] */ 949 instance = SOC_INFO(unit).port_group[port]; 950 blk = PGW_CL_BLOCK(unit, instance); 951 if (blk < 0) { 952 goto _return_error; 953 } 954 break; 955 #ifdef BCM_HURRICANE3_SUPPORT 956 case SOC_BLK_PGW_GE: 957 if (SOC_IS_HURRICANE3(unit)) { 958 blk = PGW_GE_BLOCK(unit, port); 959 if (blk < 0) { 960 goto _return_error; 961 } 962 port |= SOC_REG_ADDR_INSTANCE_MASK; 963 } 964 break; 965 #endif /* BCM_HURRICANE3_SUPPORT */ 966 default: 967 /* search for a matching block... */ 968 SOC_BLOCKS_ITER(unit, blk, regblktype) { 969 break; 970 } 971 } 972 } 973 } 974 _handle_array_refs(unit, alist, reg, 975 blk, 976 -1, /* cos */ 977 port, 978 minidx, maxidx); 979 } 980 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 981 unit, ""); 982 break; 983 case soc_cosreg: 984 /* parse cos spec in range1 */ 985 if (parse_num_range(unit, range1, &cos_min, &cos_max, 0, 986 NUM_COS(unit) - 1) < 0) { 987 goto _return_error; 988 } 989 /* parse block spec in range2 */ 990 if (parse_block_range(unit, regblktype, range2, 991 &blk_min, &blk_max, bmask) < 0) { 992 goto _return_error; 993 } 994 idx = 0; 995 while (bmask[idx] != 0) { 996 if (SOC_BLOCK_IN_LIST(regblktype, bmask[idx])) { 997 break; 998 } 999 idx++; 1000 } 1001 if ((idx > 0) && (match == 0)) { 1002 goto _return_error; 1003 } 1004 if (blk_min < 0 || blk_max > SOC_INFO(unit).block_num) { 1005 goto _return_error; 1006 } 1007 1008 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, ""); 1009 for (cos = cos_min; cos <= cos_max; cos++) { 1010 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1011 if (blk < blk_min || blk > blk_max) { 1012 continue; 1013 } 1014 port = SOC_BLOCK_PORT(unit, blk); 1015 _handle_array_refs(unit, alist, reg, 1016 blk, 1017 cos, 1018 port, 1019 -1, -1); 1020 } 1021 } 1022 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 1023 unit, ""); 1024 break; 1025 1026 case soc_genreg: 1027 if (range2) { 1028 goto _return_error; 1029 } 1030 1031 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 1032 { 1033 /* parse block spec in range1 */ 1034 if (parse_block_range(unit, regblktype, range1, 1035 &blk_min, &blk_max, bmask) < 0) { 1036 goto _return_error; 1037 } 1038 idx = 0; 1039 while (bmask[idx] != 0) { 1040 if (SOC_BLOCK_IN_LIST(regblktype, bmask[idx])) { 1041 break; 1042 } 1043 idx++; 1044 } 1045 if ((idx > 0) && (match == 0)) { 1046 goto _return_error; 1047 } 1048 if (blk_min < 0 || blk_max > SOC_INFO(unit).block_num) { 1049 goto _return_error; 1050 } 1051 1052 bsl_log_start(BSL_APPL_SYMTAB, bslSeverityNormal, unit, ""); 1053 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1054 if (blk < blk_min || blk > blk_max) { 1055 continue; 1056 } 1057 switch (regblktype[0]) { 1058 case SOC_BLK_PMQPORT: 1059 case SOC_BLK_PMQ: 1060 case SOC_BLK_PGW_CL: 1061 port = SOC_REG_ADDR_INSTANCE_MASK | SOC_BLOCK_NUMBER(unit, blk); 1062 break; 1063 default: 1064 port = SOC_BLOCK_PORT(unit, blk); 1065 break; 1066 } 1067 #ifdef BCM_GREYHOUND_SUPPORT 1068 if ((SOC_IS_HURRICANE3(unit)) && 1069 (regblktype[0] == SOC_BLK_PGW_GE)) { 1070 1071 port = SOC_REG_ADDR_INSTANCE_MASK | 1072 SOC_BLOCK_NUMBER(unit, blk); 1073 } 1074 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 1075 (regblktype[0] == SOC_BLK_PMQ)) { 1076 1077 port = SOC_REG_ADDR_INSTANCE_MASK | 1078 SOC_BLOCK_NUMBER(unit, blk); 1079 } 1080 if ((SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) 1081 && ((regblktype[0] == SOC_BLK_XLPORT) || 1082 (regblktype[0] == SOC_BLK_GXPORT))) { 1083 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 1084 NULL, NULL, NULL, 0) == SOC_E_NOT_FOUND){ 1085 /* port register not belong to pgw_gx and pgw_xl */ 1086 if (!PBMP_MEMBER(SOC_BLOCK_BITMAP(unit, blk), port)){ 1087 /* check the valid blk bitmap*/ 1088 continue; 1089 } 1090 } else if (regblktype[0] == SOC_BLK_XLPORT){ 1091 if (soc_greyhound_pgw_reg_blk_index_get(unit, reg, port, 1092 NULL, &blk, NULL, 1) > 0){ 1093 continue; 1094 } 1095 } 1096 } 1097 #endif 1098 #if defined(BCM_TOMAHAWK2_SUPPORT) 1099 if ((SOC_IS_TOMAHAWK2(unit)) && 1100 (regblktype[0] == SOC_BLK_OTPC)) { 1101 if (blk_min == blk_max) { 1102 port = SOC_REG_ADDR_INSTANCE_MASK | 1103 SOC_BLOCK_NUMBER(unit, blk); 1104 } 1105 } 1106 #endif 1107 _handle_array_refs(unit, alist, reg, 1108 blk, 1109 -1, /* cos */ 1110 port, 1111 minidx, maxidx); 1112 } 1113 bsl_log_end(BSL_APPL_SYMTAB, bslSeverityNormal, bslSinkIgnore, 1114 unit, ""); 1115 if ((SOC_IS_TOMAHAWK3(unit)) && (regblktype[0] == SOC_BLK_CDMAC)) { 1116 1117 port = REG_PORT_ANY; 1118 _handle_array_refs(unit, alist, reg, 1119 blk, 1120 -1, /* cos */ 1121 port, 1122 minidx, maxidx); 1123 } 1124 } 1125 #endif 1126 break; 1127 1128 case soc_pipereg: 1129 case soc_xpereg: 1130 case soc_itmreg: 1131 case soc_ebreg: 1132 case soc_slicereg: 1133 case soc_layerreg: 1134 legal_min = 0; 1135 legal_max = -1; 1136 regtype_name = NULL; 1137 switch (reginfo->regtype) { 1138 case soc_pipereg: 1139 legal_max = NUM_PIPE(unit) - 1; 1140 regtype_name = "pipe"; /* for debug print */ 1141 break; 1142 case soc_xpereg: 1143 legal_max = NUM_XPE(unit) - 1; 1144 regtype_name = "xpe"; /* for debug print */ 1145 break; 1146 case soc_itmreg: 1147 legal_max = NUM_ITM(unit) - 1; 1148 regtype_name = "itm"; /* for debug print */ 1149 break; 1150 case soc_ebreg: 1151 legal_max = NUM_EB(unit) - 1; 1152 regtype_name = "eb"; /* for debug print */ 1153 break; 1154 case soc_slicereg: 1155 legal_max = NUM_SLICE(unit) - 1; 1156 regtype_name = "slice"; /* for debug print */ 1157 break; 1158 case soc_layerreg: 1159 legal_max = NUM_LAYER(unit) - 1; 1160 regtype_name = "layer"; /* for debug print */ 1161 break; 1162 default: 1163 assert(0); 1164 break; 1165 } 1166 /* parse base_index number in range 1 */ 1167 if (parse_num_range(unit, range1, &cos_min, &cos_max, legal_min, 1168 legal_max) < 0) { 1169 goto _return_error; 1170 } 1171 /* parse block spec in range2 */ 1172 if (parse_block_range(unit, regblktype, range2, &blk_min, &blk_max, 1173 bmask) < 0) { 1174 goto _return_error; 1175 } 1176 if (blk_min < 0 || blk_max > SOC_INFO(unit).block_num) { 1177 goto _return_error; 1178 } 1179 idx = 0; 1180 while (bmask[idx] != 0) { 1181 if (!SOC_BLOCK_IN_LIST(regblktype, bmask[idx])) { 1182 break; 1183 } 1184 idx++; 1185 } 1186 if (bmask[idx] != 0) { 1187 goto _return_error; 1188 } 1189 LOG_VERBOSE(BSL_LS_APPL_SYMTAB, 1190 (BSL_META_U(unit, 1191 "symtab: %s %d:%d\n"), 1192 regtype_name, cos_min, cos_max)); 1193 for (range = cos_min; range <= cos_max; range++) { 1194 SOC_BLOCKS_ITER(unit, blk, regblktype) { 1195 if (blk < blk_min || blk > blk_max) { 1196 continue; 1197 } 1198 _handle_array_refs(unit, alist, reg, blk, -1, 1199 SOC_REG_ADDR_INSTANCE_MASK | range, 1200 minidx, maxidx); 1201 } 1202 } 1203 break; 1204 default: 1205 assert(0); 1206 break; 1207 } 1208 1209 if (bsl_check(bslLayerAppl, bslSourceSymtab, bslSeverityNormal, unit)) { 1210 int i; 1211 1212 bsl_log_start(BSL_APPL_SHELL, bslSeverityNormal, unit, ""); 1213 for (i = 0; i < alist->count; i++) { 1214 char buf[80]; 1215 sal_memset(buf, 0x0, 80); 1216 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) 1217 soc_reg_sprint_addr(unit, buf, &alist->ainfo[i]); 1218 #endif 1219 bsl_log_add(BSL_APPL_SHELL, bslSeverityNormal, bslSinkIgnore, 1220 unit, "symtab: %d: %s %x\n", 1221 i, buf, alist->ainfo[i].addr); 1222 } 1223 bsl_log_end(BSL_APPL_SHELL, bslSeverityNormal, bslSinkIgnore, 1224 unit, ""); 1225 } 1226 1227 if (alist->count == 0) { 1228 goto _return_error; 1229 } 1230 if (bmask) { 1231 sal_free(bmask); 1232 } 1233 return 0; 1234 1235 _return_error: 1236 sal_free(bmask); 1237 return -1; 1238 }