openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

stack.c (79559B)


      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  * File:    stack.c
      8  * Purpose: This file manages MODPORT_MAP_SW table in Trident.
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #if defined(BCM_TRIDENT_SUPPORT) 
     15 
     16 #include <soc/mem.h>
     17 #include <soc/drv.h>
     18 
     19 #include <bcm/error.h>
     20 #include <bcm/types.h>
     21 #include <bcm/trunk.h>
     22 
     23 #include <bcm_int/esw_dispatch.h>
     24 #include <bcm_int/esw/stack.h>
     25 
     26 #if defined(BCM_KATANA2_SUPPORT)
     27 #include <bcm_int/esw/katana2.h>
     28 #endif
     29 
     30 #define _BCM_TD_STK_HGT_GROUP_MAX    128
     31 
     32 #define _BCM_STK_HGT_GROUP_MAX    _BCM_TD_STK_HGT_GROUP_MAX
     33 
     34 typedef struct _bcm_td_modport_map_entry_s {
     35     uint8 dest_enable[2];
     36     uint8 dest_istrunk[2];
     37     uint8 dest[2];
     38     SHR_BITDCL higig_trunk_override[_SHR_BITDCLSIZE(_BCM_STK_HGT_GROUP_MAX)];
     39     uint8 voq_cos_valid;
     40     uint8 voq_group_id;
     41 } _bcm_td_modport_map_entry_t;
     42 
     43 typedef struct _bcm_td_modport_map_profile_s {
     44     int ref_count;
     45     int num_entries;
     46     _bcm_td_modport_map_entry_t *entry_array; 
     47 } _bcm_td_modport_map_profile_t;
     48 
     49 typedef struct _bcm_td_modport_map_info_s {
     50     int auto_include_disable; /* Disables automatic inclusion of all members
     51                                  of a Higig trunk group when one of its members
     52                                  is specified as the steering destination for
     53                                  a remote module */
     54     int num_profiles;
     55     _bcm_td_modport_map_profile_t *profile_array;
     56 } _bcm_td_modport_map_info_t;
     57 
     58 STATIC _bcm_td_modport_map_info_t _bcm_td_modport_map_info[BCM_MAX_NUM_UNITS];
     59 
     60 #define MODPORT_MAP_INFO(unit) _bcm_td_modport_map_info[unit]
     61 #define MODPORT_MAP_PROFILE(unit, index) \
     62     _bcm_td_modport_map_info[unit].profile_array[index]
     63 
     64 /*
     65  * Function:
     66  *      _bcm_td_modport_map_mirror_profile_hw_copy
     67  * Purpose:
     68  *      Copy modport map profile from MODPORT_MAP_SW to MODPORT_MAP_MIRROR.
     69  * Parameters:
     70  *      unit - SOC unit #.
     71  *      index_min - Staring index.
     72  *      index_max - Ending index.
     73  *      modport_map_sw_buf - Buffer of MODPORT_MAP_SW.
     74  * Returns:
     75  *      BCM_E_XXX
     76  */
     77 STATIC int
     78 _bcm_td_modport_map_mirror_profile_hw_copy(int unit, int index_min,
     79         int index_max, uint8 *modport_map_sw_buf)
     80 {
     81     int rv = BCM_E_NONE;
     82     int num_entries;
     83     int mirror_buf_size;
     84     uint8 *mirror_buf = NULL;
     85     int i;
     86     modport_map_sw_entry_t *modport_map_sw_entry;
     87     int enable, istrunk, dest;
     88     modport_map_mirror_entry_t *mirror_entry;
     89 
     90     num_entries = index_max - index_min + 1;
     91     mirror_buf_size = num_entries * 
     92         soc_mem_entry_words(unit, MODPORT_MAP_MIRRORm) * 4;
     93     mirror_buf = soc_cm_salloc(unit, mirror_buf_size,
     94             "modport map mirror buffer");
     95     if (NULL == mirror_buf) {
     96         return BCM_E_MEMORY;
     97     }
     98     sal_memset(mirror_buf, 0, mirror_buf_size);
     99 
    100     for (i = 0; i < num_entries; i++) {
    101         modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_SWm,
    102                 modport_map_sw_entry_t *, modport_map_sw_buf, i);
    103         enable = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
    104                 ENABLE0f);
    105         istrunk = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
    106                 ISTRUNK0f);
    107         dest = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
    108                 DEST0f);
    109 
    110         mirror_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_MIRRORm,
    111                 modport_map_mirror_entry_t *, mirror_buf, i);
    112         soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry,
    113                 ENABLEf, enable);
    114         soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry,
    115                 ISTRUNKf, istrunk);
    116         soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry,
    117                 DESTf, dest);
    118     }
    119     rv = soc_mem_write_range(unit, MODPORT_MAP_MIRRORm, MEM_BLOCK_ALL,
    120             index_min, index_max, mirror_buf); 
    121     soc_cm_sfree(unit, mirror_buf);
    122 
    123 
    124 #ifdef BCM_TRIDENT2PLUS_SUPPORT
    125     if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
    126         modport_map_subport_mirror_entry_t subport_m_entry;
    127         int port;
    128 
    129         sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry));
    130         soc_mem_field32_set(unit, MODPORT_MAP_SUBPORT_M0m, &subport_m_entry, ENABLEf, 1);
    131 
    132         /* my_modid and other modid related initialization */
    133         PBMP_ALL_ITER(unit, port) {
    134             /* configure logical subport mirror numbers */    
    135             soc_mem_field32_set(unit, MODPORT_MAP_SUBPORT_M0m, &subport_m_entry, DESTf, port);
    136             SOC_IF_ERROR_RETURN                        
    137                 (WRITE_MODPORT_MAP_SUBPORT_M0m(unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    138             SOC_IF_ERROR_RETURN                        
    139                 (WRITE_MODPORT_MAP_SUBPORT_M1m(unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    140             SOC_IF_ERROR_RETURN                        
    141                 (WRITE_MODPORT_MAP_SUBPORT_M2m(unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    142             SOC_IF_ERROR_RETURN                        
    143                 (WRITE_MODPORT_MAP_SUBPORT_M3m(unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    144                                                     
    145         }
    146     }
    147 #endif
    148     return rv;
    149 }
    150 
    151 /*
    152  * Function:
    153  *      _bcm_td_modport_map_profile_hw_write
    154  * Purpose:
    155  *      Write modport map profile to hardware.
    156  * Parameters:
    157  *      unit - SOC unit #.
    158  *      profile_index - Profile number.
    159  *      profile - Modport map profile.
    160  * Returns:
    161  *      BCM_E_XXX
    162  */
    163 STATIC int
    164 _bcm_td_modport_map_profile_hw_write(int unit, int profile_index,
    165         _bcm_td_modport_map_profile_t *profile)
    166 {
    167     int rv = BCM_E_NONE;
    168     int profile_buf_size;
    169     uint8 *profile_buf = NULL;
    170     int i, j;
    171     modport_map_sw_entry_t *modport_map_entry;
    172     _bcm_td_modport_map_entry_t profile_entry;
    173     soc_field_t enable_field[2]  = {ENABLE0f, ENABLE1f};
    174     soc_field_t istrunk_field[2] = {ISTRUNK0f, ISTRUNK1f};
    175     soc_field_t dest_field[2]    = {DEST0f, DEST1f};
    176     bcm_gport_t gport;
    177     bcm_trunk_t tid;
    178     bcm_trunk_chip_info_t chip_info;
    179     int hg_trunk_group;
    180     int index_min, index_max;
    181     int dest[2] = {0};
    182 #if defined(BCM_SABER2_SUPPORT)
    183 	int mask1 = 0, bitlen1 = 0 , mask2 = 0, bitlen2= 0;
    184 #endif
    185     profile_buf_size = profile->num_entries *
    186         soc_mem_entry_words(unit, MODPORT_MAP_SWm) * 4;
    187     profile_buf = soc_cm_salloc(unit, profile_buf_size, "modport map buffer");
    188     if (NULL == profile_buf) {
    189         return BCM_E_MEMORY;
    190     }
    191     sal_memset(profile_buf, 0, profile_buf_size);
    192 
    193     for (i = 0; i < profile->num_entries; i++) {
    194         modport_map_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_SWm,
    195                 modport_map_sw_entry_t *, profile_buf, i);
    196         profile_entry = profile->entry_array[i];
    197 
    198         if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_COS_VALIDf)) {
    199             soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    200                     VOQ_COS_VALIDf, profile_entry.voq_cos_valid);
    201         }
    202         if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_GRP_IDf)) {
    203             soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    204                     VOQ_GRP_IDf, profile_entry.voq_group_id);
    205         }
    206 
    207         for (j = 0; j < 2; j++) {
    208             if (profile_entry.dest_enable[j] == 0) {
    209                 continue;
    210             }
    211             soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    212                     enable_field[j], profile_entry.dest_enable[j]);
    213 
    214             if (profile_entry.dest_istrunk[j]) {
    215                 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    216                         istrunk_field[j], 1);
    217                 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    218                         dest_field[j], profile_entry.dest[j]);
    219             } else {
    220 #if defined(BCM_KATANA2_SUPPORT)
    221                 if (soc_feature(unit, soc_feature_linkphy_coe) ||
    222                     soc_feature(unit, soc_feature_subtag_coe)) {
    223 
    224                     /* For SB2, DEST0 11:0
    225                        ISTRUNK0 = 0:
    226                         11:7: Egress Physical Port
    227                          6:0: Egress PP_PORT
    228                        ISTRUNK0 = 1:
    229                         2:0: Egress HiGig Trunk Group ID */
    230 #ifdef BCM_SABER2_SUPPORT
    231                     if (SOC_IS_SABER2(unit)) {
    232                         bitlen1  = soc_mem_field_length(unit, MODPORT_MAP_SWm, PHYSICAL_PORT1f);
    233                         mask1 = (1 << bitlen1) - 1;
    234                         bitlen2  = soc_mem_field_length(unit, MODPORT_MAP_SWm, PP_PORT1f);
    235                         mask2 = ( 1 << bitlen2) - 1;
    236                         dest[j] = ((profile_entry.dest[j] & mask1) << bitlen2) |
    237                             (profile_entry.dest[j] & mask2);
    238                     } else
    239 #endif
    240                     if (SOC_IS_KATANA2(unit)){
    241 
    242                     /* DEST0 13:0
    243                        ISTRUNK0 = 0:
    244                         13:8: Egress Physical Port
    245                          7:0: Egress PP_PORT
    246                        ISTRUNK0 = 1:
    247                         3:0: Egress HiGig Trunk Group ID */
    248                     /* For KT2 physical port to pp_port is 1:1 mapped */
    249                          dest[j] = ((profile_entry.dest[j] & 0x3f) << 8) |
    250                               (profile_entry.dest[j] & 0xff);
    251                     } else {
    252                         LOG_ERROR(BSL_LS_BCM_COMMON,
    253                                 (BSL_META_U(unit,
    254                                             "TODO: DEST0 to be programmed in required format\n")));
    255                         dest[j] = profile_entry.dest[j];
    256                     } 
    257                 } else
    258 #endif
    259                 {
    260                     dest[j] = profile_entry.dest[j];
    261                 }
    262                 if (MODPORT_MAP_INFO(unit).auto_include_disable) {
    263                     soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    264                             istrunk_field[j], 0);
    265                     soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    266                             dest_field[j], dest[j]);
    267                 } else {
    268                     SOC_GPORT_LOCAL_SET(gport, profile_entry.dest[j]);
    269                     rv = bcm_esw_trunk_find(unit, 0, gport, &tid);
    270                     if (rv == BCM_E_NOT_FOUND) {
    271                         /* dest is not a member of a Higig trunk group */
    272                         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    273                                 istrunk_field[j], 0);
    274                         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    275                                 dest_field[j], dest[j]);
    276                     } else if (BCM_FAILURE(rv)) {
    277                         goto cleanup;
    278                     } else {
    279                         /* dest is a member of a Higig trunk group */
    280                         rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
    281                         if (BCM_FAILURE(rv)) {
    282                             goto cleanup;
    283                         }
    284                         if (tid < chip_info.trunk_fabric_id_min) {
    285                             rv = BCM_E_PARAM;
    286                             goto cleanup;
    287                         }
    288                         hg_trunk_group = tid - chip_info.trunk_fabric_id_min;
    289 
    290                         if (SHR_BITGET(
    291                             profile_entry.higig_trunk_override, 
    292                             hg_trunk_group)) {
    293                             soc_MODPORT_MAP_SWm_field32_set(unit,
    294                                     modport_map_entry,
    295                                     istrunk_field[j], 0);
    296                             soc_MODPORT_MAP_SWm_field32_set(unit,
    297                                     modport_map_entry,
    298                                     dest_field[j], dest[j]);
    299                         } else {
    300                             soc_MODPORT_MAP_SWm_field32_set(unit,
    301                                     modport_map_entry,
    302                                     istrunk_field[j], 1);
    303                             soc_MODPORT_MAP_SWm_field32_set(unit,
    304                                     modport_map_entry,
    305                                     dest_field[j], hg_trunk_group);
    306                         }
    307                     }
    308                 }
    309             }
    310         }
    311 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
    312         /* Set the HW entries to 0 if the link status is down */
    313         if (soc_feature(unit, soc_feature_epc_linkflap_recover) &&
    314             profile_entry.dest_enable[0] == 1 &&
    315             profile_entry.dest_enable[1] == 1) {
    316             int k;
    317             for (k = 0; k < 2; k++) {
    318                 int link = -1;
    319                 bcm_esw_port_link_status_get(unit, profile_entry.dest[k], &link);
    320                 if (link == 0 && !profile_entry.dest_istrunk[k]) {
    321                     soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    322                                                     enable_field[k], 0);
    323                     soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry,
    324                                                     dest_field[k], 0);
    325                 }
    326             }
    327         }
    328 #endif /*defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)*/
    329     }
    330 
    331     index_min = profile_index * profile->num_entries;
    332     index_max = index_min + profile->num_entries - 1;
    333     rv = soc_mem_write_range(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL,
    334             index_min, index_max, profile_buf); 
    335     if (BCM_FAILURE(rv)) {
    336         goto cleanup;
    337     }
    338     rv = _bcm_td_modport_map_mirror_profile_hw_copy(unit, index_min, index_max,
    339             profile_buf); 
    340     if (BCM_FAILURE(rv)) {
    341         goto cleanup;
    342     }
    343 
    344 cleanup:
    345     if (NULL != profile_buf) {
    346         soc_cm_sfree(unit, profile_buf);
    347     }
    348 
    349     return rv;
    350 }
    351 
    352 /*
    353  * Function:
    354  *      _bcm_td_modport_map_profile_add
    355  * Purpose:
    356  *      Add a modport map profile.
    357  * Parameters:
    358  *      unit - SOC unit #.
    359  *      profile - Modport map profile.
    360  *      profile_index - (OUT) Profile number.
    361  * Returns:
    362  *      BCM_E_XXX
    363  */
    364 STATIC int
    365 _bcm_td_modport_map_profile_add(int unit,
    366         _bcm_td_modport_map_profile_t *profile,
    367         int *profile_index) 
    368 {
    369     int i;
    370 
    371     /* Check if the given profile matches any existing profile */
    372 
    373     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    374         if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) {
    375             continue;
    376         }
    377         if (MODPORT_MAP_PROFILE(unit, i).num_entries != profile->num_entries) {
    378             return BCM_E_INTERNAL;
    379         }
    380         if (0 == sal_memcmp(MODPORT_MAP_PROFILE(unit, i).entry_array,
    381                     profile->entry_array,
    382                     profile->num_entries * sizeof(_bcm_td_modport_map_entry_t))) {
    383             MODPORT_MAP_PROFILE(unit, i).ref_count++;
    384             *profile_index = i;
    385             return BCM_E_NONE;
    386         }
    387     }
    388 
    389     /* The given profile does not match any existing profile */
    390 
    391     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    392         if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) {
    393             MODPORT_MAP_PROFILE(unit, i).num_entries = profile->num_entries;
    394             sal_memcpy(MODPORT_MAP_PROFILE(unit, i).entry_array,
    395                     profile->entry_array,
    396                     profile->num_entries * sizeof(_bcm_td_modport_map_entry_t));
    397             MODPORT_MAP_PROFILE(unit, i).ref_count++;
    398             *profile_index = i;
    399             BCM_IF_ERROR_RETURN
    400                 (_bcm_td_modport_map_profile_hw_write(unit, i, profile));
    401             return BCM_E_NONE;
    402         }
    403     }
    404 
    405     /* No available profile */
    406     return BCM_E_RESOURCE;
    407 }
    408 
    409 /*
    410  * Function:
    411  *      _bcm_td_modport_map_profile_delete
    412  * Purpose:
    413  *      Delete a modport map profile.
    414  * Parameters:
    415  *      unit - SOC unit #.
    416  *      profile_index - Profile number.
    417  * Returns:
    418  *      BCM_E_XXX
    419  */
    420 STATIC int
    421 _bcm_td_modport_map_profile_delete(int unit, int profile_index) 
    422 {
    423     if (MODPORT_MAP_PROFILE(unit, profile_index).ref_count == 0) {
    424         return BCM_E_INTERNAL;
    425     }
    426 
    427     MODPORT_MAP_PROFILE(unit, profile_index).ref_count--;
    428 
    429     if (MODPORT_MAP_PROFILE(unit, profile_index).ref_count == 0) {
    430         sal_memset(MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 0,
    431                 sizeof(_bcm_td_modport_map_entry_t) *
    432                 MODPORT_MAP_PROFILE(unit, profile_index).num_entries);
    433         BCM_IF_ERROR_RETURN(_bcm_td_modport_map_profile_hw_write(unit,
    434                     profile_index,
    435                     &MODPORT_MAP_PROFILE(unit, profile_index)));
    436     }
    437 
    438     return BCM_E_NONE;
    439 }
    440 
    441 /*
    442  * Function:
    443  *      _bcm_td_modport_map_free_resources
    444  * Purpose:
    445  *      Free resources of modport map profiles.
    446  * Parameters:
    447  *      unit - SOC unit #.
    448  * Returns:
    449  *      None
    450  */
    451 STATIC void
    452 _bcm_td_modport_map_free_resources(int unit)
    453 {
    454     int i;
    455 
    456     if (MODPORT_MAP_INFO(unit).profile_array) {
    457         for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    458             if (MODPORT_MAP_PROFILE(unit, i).entry_array) {
    459                 sal_free(MODPORT_MAP_PROFILE(unit, i).entry_array);
    460                 MODPORT_MAP_PROFILE(unit, i).entry_array = NULL;
    461             }
    462         }
    463         sal_free(MODPORT_MAP_INFO(unit).profile_array);
    464         MODPORT_MAP_INFO(unit).profile_array = NULL;
    465     }
    466 }
    467 
    468 /*
    469  * Function:
    470  *      bcm_td_modport_map_init
    471  * Purpose:
    472  *      Initialize modport map profiles.
    473  * Parameters:
    474  *      unit - SOC unit #.
    475  * Returns:
    476  *      BCM_E_xxx
    477  */
    478 int
    479 bcm_td_modport_map_init(int unit)
    480 {
    481     int rv = BCM_E_NONE;
    482     int i;
    483     _bcm_td_modport_map_profile_t profile;
    484     int profile_index;
    485     int port_count;
    486     bcm_port_t port;
    487     bcm_pbmp_t all_pbmp;
    488 
    489     BCM_PBMP_CLEAR(all_pbmp);
    490     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
    491 #if defined(BCM_KATANA2_SUPPORT)
    492     if (soc_feature(unit, soc_feature_linkphy_coe) ||
    493         soc_feature(unit, soc_feature_subtag_coe)) {
    494         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
    495     }
    496     if (SOC_IS_KATANA2(unit)) {
    497         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp));
    498     }
    499 #endif
    500 
    501     sal_memset(&MODPORT_MAP_INFO(unit), 0,
    502             sizeof(_bcm_td_modport_map_info_t));
    503 
    504     /* By default, all members of a Higig trunk group is automatically
    505      * included if one of its members is specified as the steering
    506      * destination for a remote module.
    507      */
    508     MODPORT_MAP_INFO(unit).auto_include_disable = 0;
    509 
    510     MODPORT_MAP_INFO(unit).num_profiles =
    511         soc_mem_index_count(unit, MODPORT_MAP_SWm) / (SOC_MODID_MAX(unit) + 1);
    512 
    513     if (NULL == MODPORT_MAP_INFO(unit).profile_array) {
    514         MODPORT_MAP_INFO(unit).profile_array =
    515             sal_alloc(sizeof(_bcm_td_modport_map_profile_t) *
    516                     MODPORT_MAP_INFO(unit).num_profiles, "modport map profiles");
    517         if (NULL == MODPORT_MAP_INFO(unit).profile_array) {
    518             _bcm_td_modport_map_free_resources(unit);
    519             return BCM_E_MEMORY;
    520         }
    521     }
    522     sal_memset(MODPORT_MAP_INFO(unit).profile_array, 0,
    523             sizeof(_bcm_td_modport_map_profile_t) *
    524             MODPORT_MAP_INFO(unit).num_profiles);
    525 
    526     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    527         MODPORT_MAP_PROFILE(unit, i).num_entries = SOC_MODID_MAX(unit) + 1;
    528         if (NULL == MODPORT_MAP_PROFILE(unit, i).entry_array) {
    529             MODPORT_MAP_PROFILE(unit, i).entry_array =
    530                 sal_alloc(sizeof(_bcm_td_modport_map_entry_t) *
    531                         MODPORT_MAP_PROFILE(unit, i).num_entries, "modport map entries");
    532             if (NULL == MODPORT_MAP_PROFILE(unit, i).entry_array) {
    533                 _bcm_td_modport_map_free_resources(unit);
    534                 return BCM_E_MEMORY;
    535             }
    536         }
    537         sal_memset(MODPORT_MAP_PROFILE(unit, i).entry_array, 0,
    538                 sizeof(_bcm_td_modport_map_entry_t) *
    539                 MODPORT_MAP_PROFILE(unit, i).num_entries);
    540     }
    541 
    542     if (!SOC_WARM_BOOT(unit)) {  
    543         /* Create a profile of all zeroes and have all ports point to it */
    544 
    545         profile.num_entries = SOC_MODID_MAX(unit) + 1;
    546         profile.entry_array = sal_alloc(sizeof(_bcm_td_modport_map_entry_t) *
    547                 profile.num_entries, "profile entry array");
    548         if (NULL == profile.entry_array) {
    549             return BCM_E_MEMORY;
    550         }
    551         sal_memset(profile.entry_array, 0, sizeof(_bcm_td_modport_map_entry_t) *
    552                 profile.num_entries);
    553         rv = _bcm_td_modport_map_profile_add(unit, &profile, &profile_index); 
    554         sal_free(profile.entry_array);
    555         if (BCM_FAILURE(rv)) {
    556             return rv;
    557         }
    558 
    559         port_count = 0;
    560         PBMP_ITER(all_pbmp, port) {
    561             BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, profile_index));
    562             port_count++;
    563         }
    564         MODPORT_MAP_PROFILE(unit, profile_index).ref_count = port_count;
    565     }
    566 
    567     return rv;
    568 }
    569 
    570 /*
    571  * Function:
    572  *      bcm_td_modport_map_detach
    573  * Purpose:
    574  *      Detach modport map profiles.
    575  * Parameters:
    576  *      unit - SOC unit #.
    577  * Returns:
    578  *      BCM_E_xxx
    579  */
    580 int
    581 bcm_td_modport_map_detach(int unit)
    582 {
    583     _bcm_td_modport_map_free_resources(unit);
    584     return BCM_E_NONE;
    585 }
    586 
    587 int 
    588 bcm_td_modport_map_hw_write_entry(int unit, int index, 
    589                 int select_index, bcm_port_t dest_port, int set)
    590 {
    591     int rv = BCM_E_NONE;
    592     uint8 *profile_buf = NULL;
    593     int profile_buf_size;
    594     modport_map_sw_entry_t *modport_map_sw_entry;
    595     int enable[2];
    596     int dest[2];
    597     soc_field_t enable_field[2]  = {ENABLE0f, ENABLE1f};
    598     soc_field_t dest_field[2]    = {DEST0f, DEST1f};
    599     int i, num_dest_supported;
    600 
    601     num_dest_supported = 2;
    602     sal_memset(enable, 0, sizeof(int) * 2);
    603     sal_memset(dest, 0, sizeof(int) * 2);
    604 
    605     /* 1 Entry x 1 Word x 4 (bytes) */
    606     profile_buf_size = 1 * 4 * soc_mem_entry_words(unit, MODPORT_MAP_SWm);
    607     profile_buf = soc_cm_salloc(unit, profile_buf_size,
    608                     "modport map entry buffer");
    609     if (NULL == profile_buf) {
    610         return BCM_E_MEMORY;
    611     }
    612 
    613     rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY,
    614                             index, profile_buf);
    615     if (BCM_FAILURE(rv)) {
    616         soc_cm_sfree(unit, profile_buf);
    617         return BCM_E_RESOURCE;
    618     }
    619     modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit,
    620         MODPORT_MAP_SWm, modport_map_sw_entry_t *, profile_buf, 0);
    621 
    622     for (i = 0; i < num_dest_supported; i++) {
    623         if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, enable_field[i])) {
    624             enable[i] = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
    625                     enable_field[i]);
    626         }
    627         if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, dest_field[i])) {
    628             dest[i] = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
    629                     dest_field[i]);
    630         }
    631     }
    632     if ((set == 1)) {
    633         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry,
    634                 enable_field[select_index], set);
    635         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry,
    636                 dest_field[select_index], dest_port);
    637     } else if (enable[select_index] && (dest[select_index] == dest_port)) {
    638         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry,
    639                 enable_field[select_index], 0);
    640         soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry,
    641                 dest_field[select_index], 0);
    642     } else {
    643         soc_cm_sfree(unit, profile_buf);
    644         return BCM_E_INTERNAL;
    645     }
    646     rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY,
    647                             index, profile_buf);
    648     if (BCM_FAILURE(rv)) {
    649         soc_cm_sfree(unit, profile_buf);
    650         return BCM_E_RESOURCE;
    651     }
    652     rv = _bcm_td_modport_map_mirror_profile_hw_copy(unit, index, index,
    653                         profile_buf);
    654     if (BCM_FAILURE(rv)) {
    655         soc_cm_sfree(unit, profile_buf);
    656         return BCM_E_RESOURCE;
    657     }
    658     soc_cm_sfree(unit, profile_buf);
    659     return BCM_E_NONE;
    660 }
    661 
    662 /*
    663  * Function:
    664  *      _bcm_td_stk_is_port_hgtid_member
    665  * Purpose:
    666  *      Helper function to find if the hgtid
    667  *      (got from MODPORT_MAP_SW.DEST for trunk case)
    668  *      has the port as its member.
    669  *      Also returns the corresponding trunk id if the port
    670  *      is member of HGTID.
    671  * Parameters:
    672  *      unit    - (IN) SOC unit #
    673  *      hgtid   - (IN) Higig Trunk id (index of HG_TRUNK_BITMAP)
    674  *      port    - (IN) Member port
    675  *      trunkid - (OUT) trunk id of the given port
    676  * Returns:
    677  *      True  - Port is a member of hgtid
    678  *      False - Port is not a member of hgtid
    679  */
    680 STATIC int
    681 _bcm_td_stk_is_port_hgtid_member(int unit, int hgtid,
    682                         bcm_port_t port, int *trunkid)
    683 {
    684     int tid, rv, mymodid;
    685     bcm_trunk_chip_info_t chip_info;
    686     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
    687     if (chip_info.trunk_fabric_id_min == -1) {
    688         return 0;
    689     }
    690     rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
    691     if (BCM_FAILURE(rv)) {
    692         return 0;
    693     }
    694     rv = bcm_esw_trunk_find(unit, mymodid, port, &tid);
    695     if (BCM_FAILURE(rv)) {
    696         return 0;
    697     }
    698     tid -= chip_info.trunk_fabric_id_min;
    699     if (hgtid == tid) {
    700         *trunkid = tid + chip_info.trunk_fabric_id_min;
    701         return 1;
    702     }
    703     return 0;
    704 }
    705 
    706 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
    707 STATIC int
    708 _bcm_td_sdk_is_port_set_in_epc_link_bmap(int unit, bcm_port_t port,
    709                                          int *set)
    710 {
    711    epc_link_bmap_entry_t  epc_link_bmap_entry;
    712    soc_pbmp_t             link_pbmp;
    713 
    714    SOC_PBMP_CLEAR(link_pbmp);
    715 
    716    BCM_IF_ERROR_RETURN(READ_EPC_LINK_BMAPm(
    717                 unit, MEM_BLOCK_ANY, 0, &epc_link_bmap_entry));
    718    soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm,
    719             &epc_link_bmap_entry, PORT_BITMAPf,&link_pbmp);
    720    if (SOC_PBMP_MEMBER(link_pbmp, port)) {
    721        /* port is there in EPC_LINK_BMAP */
    722        *set = 1;
    723    } else {
    724        *set = 0;
    725    }
    726    return BCM_E_NONE;
    727 }
    728 /*
    729  * Function:
    730  *      _bcm_td_stk_modport_map_is_member_link_handler
    731  * Purpose:
    732  *      Called from bcm_esw_trunk_set and bcm_esw_trunk_member_add
    733  *      to check if this member shall be added.
    734  * Parameters:
    735  *      unit      - (IN) SOC unit #
    736  *      gport     - (IN) gport for member port
    737  *      trunk_id  - (IN) trunk identifier
    738  *      test_only - (IN) if set to 1 no need to update cache.
    739  *      status    - (OUT)set to 1 if port needs to be added to trunk.
    740  *                       else set to 0.
    741  * Returns:
    742  *      BCM_E_XXXX
    743  */
    744 int
    745 _bcm_td_stk_modport_map_member_link_handler(int unit,
    746                                             bcm_gport_t gport,
    747                                             bcm_trunk_t trunk_id,
    748                                             int test_only,
    749                                             int *status)
    750 {
    751     int                           i, j, k;
    752     int                           enable[2];
    753     int                           dest[2];
    754     int                           istrunk[2];
    755     int                           num_dest_supported;
    756     int                           set = 1;
    757     int                           rv = BCM_E_NONE;
    758     bcm_port_t                    port;
    759     _bcm_td_modport_map_profile_t *profile;
    760 
    761     if (!status) {
    762         return BCM_E_PARAM;
    763     }
    764 
    765     num_dest_supported = 2;
    766     rv =  bcm_esw_port_local_get(unit, gport, &port);
    767     if (rv != BCM_E_NONE) {
    768         *status = 1;
    769         return BCM_E_NONE;
    770     }
    771 
    772     /* if port is not local hg port return */
    773     if (!IS_ST_PORT(unit, port)) {
    774         *status = 1;
    775         return BCM_E_NONE;
    776     }
    777 
    778     rv = _bcm_td_sdk_is_port_set_in_epc_link_bmap(unit, port, &set);
    779     if (rv != BCM_E_NONE) {
    780         *status = 1;
    781         return BCM_E_NONE;
    782     }
    783     if (set) {
    784         *status = 1;
    785         return BCM_E_NONE;
    786     }
    787     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    788          if (MODPORT_MAP_PROFILE(unit, i).ref_count != 0) {
    789              profile = &MODPORT_MAP_PROFILE(unit, i);
    790              for (j = 0; j < profile->num_entries; j++) {
    791                  for (k = 0; k < num_dest_supported; k++) {
    792                        enable[k] = profile->entry_array[j].dest_enable[k];
    793                        dest[k] = profile->entry_array[j].dest[k];
    794                       istrunk[k] = profile->entry_array[j].dest_istrunk[k];
    795                   }
    796                   for (k = 0; k < num_dest_supported; k++) {
    797                        int port_is_cached = 0;
    798                       bcm_trunk_t dummy_tid;
    799                        if (enable[k] && istrunk[k] &&
    800                            enable[(k+1)%num_dest_supported]) {
    801                            if (_bcm_td_stk_is_port_hgtid_member(
    802                                unit, dest[k], port, &dummy_tid)) {
    803                                int mymodid;
    804                                rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
    805                                if (BCM_FAILURE(rv)) {
    806                                    return rv;
    807                                }
    808                            }
    809                            if ((trunk_id == -1) &&
    810                                (_BCM_PORT_TRUNK_LINKFLAP_GET(unit, port) !=
    811                                BCM_TRUNK_INVALID)) {
    812                                port_is_cached = 1;
    813                                trunk_id =
    814                                _BCM_PORT_TRUNK_LINKFLAP_GET(unit, port);
    815                            }
    816                            if (trunk_id != -1) {
    817                                if (!port_is_cached) {
    818                                    if (!test_only) {
    819                                         _BCM_PORT_TRUNK_LINKFLAP_SET(
    820                                                       unit, port, trunk_id);
    821                                    }
    822                                    *status = 0;
    823                                } else {
    824                                    *status = 1;
    825                                }
    826                            }
    827                        }
    828                   }
    829              }
    830          }
    831     }
    832     return BCM_E_NONE;
    833 }
    834 
    835 /*
    836  * Function:
    837  *      _bcm_td_stk_modport_map_linkscan_handler
    838  * Purpose:
    839  *      Called from linkscan handler when port toggles.
    840  *      Enables and Disables the port in MODPORT_MAP_SW.
    841  * Parameters:
    842  *      unit  - (IN) SOC unit #
    843  *      info  - (IN) port info
    844  * Returns:
    845  *      None
    846  */
    847 int 
    848 _bcm_td_stk_modport_map_linkscan_handler(int unit, 
    849                 bcm_port_t port, bcm_port_info_t *info)
    850 {
    851     int i, j, k;
    852     int enable[2];
    853     int dest[2];
    854     int istrunk[2];
    855     int num_dest_supported;
    856     _bcm_td_modport_map_profile_t *profile;
    857     int index, set;
    858     int rv = BCM_E_NONE;
    859 
    860     if (!info) {
    861         return BCM_E_PARAM;
    862     }
    863 
    864     num_dest_supported = 2;
    865     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
    866         if (MODPORT_MAP_PROFILE(unit, i).ref_count != 0) {
    867             profile = &MODPORT_MAP_PROFILE(unit, i);
    868             for (j = 0; j < profile->num_entries; j++) {
    869                 for (k = 0; k < num_dest_supported; k++) {
    870                     enable[k] = profile->entry_array[j].dest_enable[k];
    871                     dest[k] = profile->entry_array[j].dest[k];
    872                     istrunk[k] = profile->entry_array[j].dest_istrunk[k];
    873                 }
    874                 /* For cases where the profile points to a trunk
    875                  * and the port in question is a member of the trunk,
    876                  * the port is removed from the trunk group when it is shut.
    877                  * This state is saved so that upon port enable, the port is added
    878                  * back to the trunk group.
    879                  */
    880                 for (k = 0; k < num_dest_supported; k++) {
    881                     int port_is_cached = 0;
    882                     bcm_trunk_t trunk_id = -1;
    883                     /* Remove the port from trunk, only if both DEST are enabled */
    884                     if (enable[k] && istrunk[k] && enable[(k+1)%num_dest_supported]) {
    885                         if (_bcm_td_stk_is_port_hgtid_member(unit, dest[k], port, &trunk_id)) {
    886                             int mymodid;
    887                             rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
    888                             if (BCM_FAILURE(rv)) {
    889                                 return rv;
    890                             }
    891                         }
    892                         if ((trunk_id == -1) &&
    893                             (_BCM_PORT_TRUNK_LINKFLAP_GET(unit, port) != BCM_TRUNK_INVALID)) {
    894                             port_is_cached = 1;
    895                             trunk_id = _BCM_PORT_TRUNK_LINKFLAP_GET(unit, port);
    896                         }
    897                         if (trunk_id != -1) {
    898                             bcm_trunk_member_t p_trunk_member;
    899                             bcm_trunk_member_t_init(&p_trunk_member);
    900                             BCM_GPORT_LOCAL_SET(p_trunk_member.gport, port);
    901                             if ((!port_is_cached) &&
    902                                 (info->linkstatus == BCM_PORT_LINK_STATUS_DOWN)) {
    903                                 rv = bcm_esw_trunk_member_delete(unit, trunk_id, &p_trunk_member);
    904                                 if (BCM_FAILURE(rv)) {
    905                                     return rv;
    906                                 }
    907                                 _BCM_PORT_TRUNK_LINKFLAP_SET(unit, port, trunk_id);
    908                             } else if ((port_is_cached) &&
    909                                        (info->linkstatus == BCM_PORT_LINK_STATUS_UP)) {
    910                                 /* Check if EPC_PORT_BMAP is updated */
    911                                 BCM_IF_ERROR_RETURN(_bcm_td_sdk_is_port_set_in_epc_link_bmap(
    912                                                                               unit, port, &set));
    913                                 if (set) {
    914                                     rv = bcm_esw_trunk_member_add(unit, trunk_id, &p_trunk_member);
    915                                     if (BCM_FAILURE(rv)) {
    916                                         return rv;
    917                                     }
    918                                     _BCM_PORT_TRUNK_LINKFLAP_CLEAR(unit, port);
    919                                 }
    920 
    921                             }
    922                             continue;
    923                         }
    924                     }
    925                 }
    926                 /* Max Number of destination for a modid is currently 2 */
    927                 if (!istrunk[0] && !istrunk[1] && enable[0] && enable[1]) {
    928                     int select;
    929                     if (dest[0] == port) {
    930                         select = 0;
    931                     } else if (dest[1] == port) {
    932                         select = 1;
    933                     } else {
    934                         continue;
    935                     }
    936                     index = (i * profile->num_entries) + j;
    937                     if (info->linkstatus == BCM_PORT_LINK_STATUS_DOWN) {
    938                         rv = bcm_td_modport_map_hw_write_entry(unit, index, 
    939                                                             select, port, 0);
    940                     } else  if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) {
    941                         rv = bcm_td_modport_map_hw_write_entry(unit, index, 
    942                                                             select, port, 1);
    943                     }
    944                     if (BCM_FAILURE(rv)){
    945                         return rv;
    946                     }
    947                 }
    948             }
    949         }
    950     }
    951     return BCM_E_NONE;
    952 }
    953 #endif
    954 
    955 /*
    956  * Function:
    957  *      bcm_td_stk_port_modport_op
    958  * Purpose:
    959  *      Set, add, or delete modport mappings.
    960  * Parameters:
    961  *      unit - SOC unit #.
    962  *      op - Set, add, or delete.
    963  *      ing_port - Ingress port.
    964  *      dest_modid - Destination module ID.
    965  *      dest_port - Array of destination Higig ports.
    966  *      dest_port_count - Size of dest_port array.
    967  * Returns:
    968  *      BCM_E_xxx
    969  */
    970 int
    971 bcm_td_stk_port_modport_op(int unit, int op, bcm_port_t ing_port,
    972                            bcm_module_t dest_modid, bcm_port_t *dest_port,
    973                            int dest_port_count)
    974 {
    975     int rv = BCM_E_NONE;
    976     int num_dest_supported;
    977     int modid_count, modid_min, modid_max;
    978     int hgtid[SOC_MAX_NUM_PORTS];
    979     int i, k, j;
    980     bcm_trunk_t tid;
    981     bcm_trunk_chip_info_t chip_info;
    982     uint32 rval;
    983     int profile_index, new_profile_index;
    984     _bcm_td_modport_map_profile_t profile;
    985     int entry_array_size;
    986     int enable[2];
    987     int istrunk[2];
    988     int dest[2];
    989     int match;
    990 
    991 #ifdef BCM_TOMAHAWK3_SUPPORT
    992     if (SOC_IS_TOMAHAWK3(unit)) {
    993         return BCM_E_UNAVAIL;
    994     }
    995 #endif
    996 
    997     if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) {
    998         return BCM_E_PARAM;
    999     }
   1000 
   1001     if (BCM_GPORT_IS_SET(ing_port)) {
   1002         BCM_IF_ERROR_RETURN(
   1003                 bcm_esw_port_local_get(unit, ing_port, &ing_port));
   1004     }
   1005     if (!SOC_PORT_VALID(unit, ing_port)) {
   1006         return BCM_E_PORT;
   1007     }
   1008 
   1009     modid_count = SOC_MODID_MAX(unit) + 1;
   1010     if (dest_modid == -1) {
   1011         modid_min = 0;
   1012         modid_max = modid_count - 1;
   1013     } else {
   1014         if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   1015             return BCM_E_PARAM;
   1016         }
   1017         modid_min = modid_max = dest_modid;
   1018     }
   1019 
   1020     num_dest_supported = 2;
   1021     if (dest_port_count > num_dest_supported) {
   1022         return BCM_E_RESOURCE;
   1023     }
   1024 
   1025     sal_memset(hgtid, 0, sizeof(hgtid));
   1026     for (i = 0; i < dest_port_count; i++) {
   1027         if (BCM_GPORT_IS_TRUNK(dest_port[i])) {
   1028             tid = SOC_GPORT_TRUNK_GET(dest_port[i]);
   1029             BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   1030             if (chip_info.trunk_fabric_id_min >= 0 &&
   1031                     tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */
   1032                 hgtid[i] = tid - chip_info.trunk_fabric_id_min;
   1033             } else {
   1034                 return BCM_E_PARAM;
   1035             }
   1036         } else {
   1037             if (!SOC_PORT_VALID(unit, dest_port[i])) {
   1038                 return BCM_E_PORT;
   1039             }
   1040         }
   1041     }
   1042 
   1043     soc_mem_lock(unit, MODPORT_MAP_SWm);
   1044 
   1045     /* Get ingress port's current profile index */
   1046     rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   1047     if (BCM_FAILURE(rv)) {
   1048         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1049         return rv;
   1050     }
   1051     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   1052                 MODPORT_MAP_INDEX_UPPERf);
   1053 
   1054     /* Get current profile */
   1055     profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries;
   1056     entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t);
   1057     profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array");
   1058     if (NULL == profile.entry_array) {
   1059         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1060         return BCM_E_MEMORY;
   1061     }
   1062     sal_memcpy(profile.entry_array,
   1063             MODPORT_MAP_PROFILE(unit, profile_index).entry_array,
   1064             entry_array_size);
   1065 
   1066     /* Modify profile */
   1067     for (i = modid_min; i <= modid_max; i++) {
   1068         for (k = 0; k < num_dest_supported; k++) {
   1069             enable[k] = profile.entry_array[i].dest_enable[k]; 
   1070             istrunk[k] = profile.entry_array[i].dest_istrunk[k]; 
   1071             dest[k] = profile.entry_array[i].dest[k]; 
   1072         }
   1073 
   1074         switch (op) {
   1075             case _BCM_STK_PORT_MODPORT_OP_SET:
   1076                 for (k = 0; k < dest_port_count; k++) {
   1077                     enable[k] = 1;
   1078                     if (BCM_GPORT_IS_TRUNK(dest_port[k])) {
   1079                         istrunk[k] = 1;
   1080                         dest[k] = hgtid[k];
   1081                     } else {
   1082                         istrunk[k] = 0;
   1083                         dest[k] = dest_port[k];
   1084                     }
   1085                 }
   1086                 for (k = dest_port_count; k < num_dest_supported; k++) {
   1087                     enable[k] = 0;
   1088                     istrunk[k] = 0;
   1089                     dest[k] = 0;
   1090                 }
   1091                 break;
   1092 
   1093             case _BCM_STK_PORT_MODPORT_OP_ADD:
   1094                 for (k = 0; k < dest_port_count; k++) {
   1095                     /* Find the first free destination */
   1096                     for (j = 0; j < num_dest_supported; j++) {
   1097                         if (enable[j] == 0) {
   1098                             break;
   1099                         }
   1100                     }
   1101                     if (j == num_dest_supported) {
   1102                         /* A free destination cannot be found */
   1103                         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1104                         sal_free(profile.entry_array);
   1105                         return BCM_E_RESOURCE;
   1106                     }
   1107                     enable[j] = 1;
   1108                     if (BCM_GPORT_IS_TRUNK(dest_port[k])) {
   1109                         istrunk[j] = 1;
   1110                         dest[j] = hgtid[k];
   1111                     } else {
   1112                         istrunk[j] = 0;
   1113                         dest[j] = dest_port[k];
   1114                     }
   1115                 }
   1116                 break;
   1117 
   1118             case _BCM_STK_PORT_MODPORT_OP_DELETE:
   1119                 for (k = 0; k < dest_port_count; k++) {
   1120                     /* Find the matching destination */
   1121                     match = 0;
   1122                     for (j = 0; j < num_dest_supported; j++) {
   1123                         if (enable[j] == 1) {
   1124                             if (BCM_GPORT_IS_TRUNK(dest_port[k])) {
   1125                                 if (istrunk[j] == 1 &&
   1126                                         dest[j] == hgtid[k]) {
   1127                                     match = 1;
   1128                                 }
   1129                             } else {
   1130                                 if (istrunk[j] == 0 &&
   1131                                         dest[j] == dest_port[k]) {
   1132                                     match = 1;
   1133                                 } 
   1134                             }
   1135                             if (match) {
   1136                                 enable[j] = 0;
   1137                                 istrunk[j] = 0;
   1138                                 dest[j] = 0;
   1139                                 break;
   1140                             }
   1141                         }
   1142                     }
   1143                     if (!match) {
   1144                         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1145                         sal_free(profile.entry_array);
   1146                         return BCM_E_NOT_FOUND;
   1147                     }
   1148                 }
   1149                 break;
   1150 
   1151             default:
   1152                 soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1153                 sal_free(profile.entry_array);
   1154                 return BCM_E_INTERNAL;
   1155         }
   1156 
   1157         for (k = 0; k < num_dest_supported; k++) {
   1158             profile.entry_array[i].dest_enable[k] = enable[k];
   1159             profile.entry_array[i].dest_istrunk[k] = istrunk[k];
   1160             profile.entry_array[i].dest[k] = dest[k];
   1161         }
   1162     }
   1163 
   1164     /* Add modified profile */
   1165     rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index);
   1166     if (BCM_FAILURE(rv)) {
   1167         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1168         sal_free(profile.entry_array);
   1169         return rv;
   1170     }
   1171 
   1172     /* Update ingress port's profile index */
   1173     soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   1174                 MODPORT_MAP_INDEX_UPPERf, new_profile_index);
   1175     rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval);
   1176     if (BCM_FAILURE(rv)) {
   1177         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1178         sal_free(profile.entry_array);
   1179         return rv;
   1180     }
   1181 
   1182     /* Remove old profile */
   1183     rv = _bcm_td_modport_map_profile_delete(unit, profile_index);
   1184     soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1185     sal_free(profile.entry_array);
   1186     return rv;
   1187 }
   1188 
   1189 /*
   1190  * Function:
   1191  *      bcm_td_stk_port_modport_get
   1192  * Purpose:
   1193  *      Get modport mappings.
   1194  * Parameters:
   1195  *      unit - SOC unit #.
   1196  *      ing_port - Ingress port.
   1197  *      dest_modid - Destination module ID.
   1198  *      dest_port_max - Size of dest_port_array.
   1199  *      dest_port_array - (OUT) Array of destination Higig ports.
   1200  *      dest_port_count - (OUT) Number of ports returned in dest_port array.
   1201  * Returns:
   1202  *      BCM_E_xxx
   1203  */
   1204 int
   1205 bcm_td_stk_port_modport_get(int unit, bcm_port_t ing_port,
   1206                           bcm_module_t dest_modid, int dest_port_max,
   1207                           bcm_port_t *dest_port_array,
   1208                           int *dest_port_count)
   1209 {
   1210     uint32 rval;
   1211     int profile_index;
   1212     _bcm_td_modport_map_profile_t profile;
   1213     int count;
   1214     int num_dest_supported;
   1215     int i;
   1216     int enable, istrunk, dest;
   1217     bcm_trunk_chip_info_t chip_info;
   1218     bcm_trunk_t tid;
   1219 
   1220     if (BCM_GPORT_IS_SET(ing_port)) {
   1221         BCM_IF_ERROR_RETURN(
   1222                 bcm_esw_port_local_get(unit, ing_port, &ing_port));
   1223     }
   1224     if (!SOC_PORT_VALID(unit, ing_port)) {
   1225         return BCM_E_PORT;
   1226     }
   1227 
   1228     if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   1229         return BCM_E_PARAM;
   1230     }
   1231 
   1232     if (dest_port_max < 0 || dest_port_array == NULL ||
   1233             dest_port_count == NULL) {
   1234         return BCM_E_PARAM;
   1235     }
   1236 
   1237     BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval));
   1238     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   1239             MODPORT_MAP_INDEX_UPPERf);
   1240     profile = MODPORT_MAP_PROFILE(unit, profile_index);
   1241 
   1242     count= 0;
   1243     num_dest_supported = 2;
   1244     for (i = 0; i < num_dest_supported; i++) {
   1245         enable = profile.entry_array[dest_modid].dest_enable[i]; 
   1246         istrunk = profile.entry_array[dest_modid].dest_istrunk[i]; 
   1247         dest = profile.entry_array[dest_modid].dest[i]; 
   1248 
   1249         if (enable) {
   1250             if (dest_port_max > count) {
   1251             	if (istrunk) {
   1252                     BCM_IF_ERROR_RETURN
   1253                        (bcm_esw_trunk_chip_info_get(unit, &chip_info));
   1254                     tid = dest + chip_info.trunk_fabric_id_min;
   1255                     BCM_GPORT_TRUNK_SET(dest_port_array[count], tid);
   1256                 } else {
   1257                     dest_port_array[count] = dest;
   1258                 }
   1259             }
   1260             if ((dest_port_max != 0) &&
   1261                 (dest_port_max == count)) {
   1262                 break;
   1263             }
   1264             count++;
   1265         }
   1266     }
   1267     *dest_port_count = count;
   1268 
   1269     return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND;
   1270 }
   1271 
   1272 /*
   1273  * Function:
   1274  *      bcm_td_stk_modport_voq_op
   1275  * Purpose:
   1276  *      Set/get VoQ info.
   1277  * Parameters:
   1278  *      unit - SOC unit #.
   1279  *      ing_port - Ingress port.
   1280  *      dest_modid - Destination module ID.
   1281  *      grp_id - (IN/OUT) VoQ group ID.
   1282  *      op - Set/get.
   1283  * Returns:
   1284  *      BCM_E_xxx
   1285  */
   1286 int
   1287 bcm_td_stk_modport_voq_op(int unit, bcm_port_t ing_port,
   1288         bcm_module_t dest_modid, int *grp_id, int op)
   1289 {
   1290     int rv = BCM_E_NONE;
   1291     int modid_count, modid_min, modid_max;
   1292     uint32 rval;
   1293     int profile_index, new_profile_index;
   1294     _bcm_td_modport_map_profile_t profile;
   1295     int entry_array_size;
   1296     int voq_cos_valid, voq_group_id;
   1297     int i;
   1298 
   1299     if (BCM_GPORT_IS_SET(ing_port)) {
   1300         BCM_IF_ERROR_RETURN(
   1301                 bcm_esw_port_local_get(unit, ing_port, &ing_port));
   1302     }
   1303     if (!SOC_PORT_VALID(unit, ing_port)) {
   1304         return BCM_E_PORT;
   1305     }
   1306 
   1307     modid_count = SOC_MODID_MAX(unit) + 1;
   1308     if (dest_modid == -1 && op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET) {
   1309         modid_min = 0;
   1310         modid_max = modid_count - 1;
   1311     } else {
   1312         if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   1313             return BCM_E_PARAM;
   1314         }
   1315         modid_min = modid_max = dest_modid;
   1316     }
   1317 
   1318     if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_COUNT) {
   1319         return BCM_E_PARAM;
   1320     }
   1321 
   1322     soc_mem_lock(unit, MODPORT_MAP_SWm);
   1323 
   1324     /* Get ingress port's current profile index */
   1325     rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   1326     if (BCM_FAILURE(rv)) {
   1327         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1328         return rv;
   1329     }
   1330     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   1331             MODPORT_MAP_INDEX_UPPERf);
   1332 
   1333     /* Get current profile */
   1334     profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries;
   1335     entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t);
   1336     profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array");
   1337     if (NULL == profile.entry_array) {
   1338         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1339         return BCM_E_MEMORY;
   1340     }
   1341     sal_memcpy(profile.entry_array,
   1342             MODPORT_MAP_PROFILE(unit, profile_index).entry_array,
   1343             entry_array_size);
   1344 
   1345     if (op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET) {
   1346         voq_cos_valid = (*grp_id >= 0) ? 1: 0;
   1347         voq_group_id = (*grp_id >= 0) ? *grp_id : 0;
   1348 
   1349         /* Modify profile */
   1350         for (i = modid_min; i <= modid_max; i++) {
   1351             profile.entry_array[i].voq_cos_valid = voq_cos_valid;
   1352             profile.entry_array[i].voq_group_id = voq_group_id;
   1353         }
   1354 
   1355         /* Add modified profile */
   1356         rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index);
   1357         if (BCM_FAILURE(rv)) {
   1358             soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1359             sal_free(profile.entry_array);
   1360             return rv;
   1361         }
   1362 
   1363         /* Update ingress port's profile index */
   1364         soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   1365                 MODPORT_MAP_INDEX_UPPERf, new_profile_index);
   1366         rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval);
   1367         if (BCM_FAILURE(rv)) {
   1368             soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1369             sal_free(profile.entry_array);
   1370             return rv;
   1371         }
   1372 
   1373         /* Remove old profile */
   1374         rv = _bcm_td_modport_map_profile_delete(unit, profile_index);
   1375         if (BCM_FAILURE(rv)) {
   1376             soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1377             sal_free(profile.entry_array);
   1378             return rv;
   1379         }
   1380     } else if (op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_GET) {
   1381         voq_cos_valid = profile.entry_array[dest_modid].voq_cos_valid;
   1382         voq_group_id = profile.entry_array[dest_modid].voq_group_id;
   1383         *grp_id = (voq_cos_valid) ? voq_group_id: -1;
   1384     }
   1385 
   1386     soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1387     sal_free(profile.entry_array);
   1388     return rv;
   1389 }
   1390 
   1391 /*
   1392  * Function:
   1393  *      bcm_td_stk_modport_map_update
   1394  * Purpose:
   1395  *      Update modport map profiles due to changes in Higig trunk membership.
   1396  * Parameters:
   1397  *      unit - SOC unit #.
   1398  * Returns:
   1399  *      BCM_E_xxx
   1400  */
   1401 int
   1402 bcm_td_stk_modport_map_update(int unit)
   1403 {
   1404     int i;
   1405 
   1406     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   1407         if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) {
   1408             continue;
   1409         }
   1410         BCM_IF_ERROR_RETURN(_bcm_td_modport_map_profile_hw_write(unit, i,
   1411                     &MODPORT_MAP_PROFILE(unit, i)));
   1412     }
   1413 
   1414     return BCM_E_NONE;
   1415 }
   1416 
   1417 /*
   1418  * Function:
   1419  *      bcm_td_stk_trunk_override_ucast_set
   1420  * Purpose:
   1421  *      Set/clear HiGig Trunk Override in modport map profile.
   1422  * Parameters:
   1423  *      unit - SOC unit
   1424  *      ing_port - Ingress Port
   1425  *      hgtid - Higig Trunk ID
   1426  *      modid - Module ID  
   1427  *      enable - HighGig Trunk Override set/clear flag.
   1428  * Returns:
   1429  *      BCM_E_XXX
   1430  */
   1431 int
   1432 bcm_td_stk_trunk_override_ucast_set(int unit, bcm_port_t ing_port,
   1433                                bcm_trunk_t hgtid, int modid, int enable)
   1434 {
   1435     int rv = BCM_E_NONE;
   1436     uint32 rval;
   1437     int profile_index, new_profile_index;
   1438     _bcm_td_modport_map_profile_t profile;
   1439     int entry_array_size;
   1440 
   1441     if (BCM_GPORT_IS_SET(ing_port)) {
   1442         BCM_IF_ERROR_RETURN(
   1443                 bcm_esw_port_local_get(unit, ing_port, &ing_port));
   1444     }
   1445     if (!SOC_PORT_VALID(unit, ing_port)) {
   1446         return BCM_E_PORT;
   1447     }
   1448 
   1449     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   1450         return BCM_E_PARAM;
   1451     }
   1452 
   1453     soc_mem_lock(unit, MODPORT_MAP_SWm);
   1454 
   1455     /* Get ingress port's current profile index */
   1456     rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   1457     if (BCM_FAILURE(rv)) {
   1458         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1459         return rv;
   1460     }
   1461     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   1462             MODPORT_MAP_INDEX_UPPERf);
   1463 
   1464     /* Get current profile */
   1465     profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries;
   1466     entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t);
   1467     profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array");
   1468     if (NULL == profile.entry_array) {
   1469         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1470         return BCM_E_MEMORY;
   1471     }
   1472     sal_memcpy(profile.entry_array,
   1473             MODPORT_MAP_PROFILE(unit, profile_index).entry_array,
   1474             entry_array_size);
   1475 
   1476     /* Modify profile */
   1477     if (enable) {
   1478         SHR_BITSET(profile.entry_array[modid].higig_trunk_override, hgtid);
   1479     } else {
   1480         SHR_BITCLR(profile.entry_array[modid].higig_trunk_override, hgtid);
   1481     }
   1482 
   1483     /* Add modified profile */
   1484     rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index);
   1485     if (BCM_FAILURE(rv)) {
   1486         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1487         sal_free(profile.entry_array);
   1488         return rv;
   1489     }
   1490 
   1491     /* Update ingress port's profile index */
   1492     soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   1493             MODPORT_MAP_INDEX_UPPERf, new_profile_index);
   1494     rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval);
   1495     if (BCM_FAILURE(rv)) {
   1496         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1497         sal_free(profile.entry_array);
   1498         return rv;
   1499     }
   1500 
   1501     /* Remove old profile */
   1502     rv = _bcm_td_modport_map_profile_delete(unit, profile_index);
   1503     soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1504     sal_free(profile.entry_array);
   1505     return rv;
   1506 }
   1507 
   1508 /*
   1509  * Function:
   1510  *      bcm_td_stk_trunk_override_ucast_get
   1511  * Purpose:
   1512  *      Get HiGig Trunk Override from modport map profile.
   1513  * Parameters:
   1514  *      unit - SOC unit
   1515  *      ing_port - Ingress Port
   1516  *      hgtid - Trunk ID
   1517  *      modid - Module ID  
   1518  *      enable - HighGig Trunk Override flag.
   1519  * Returns:
   1520  *      BCM_E_XXX
   1521  */
   1522 int
   1523 bcm_td_stk_trunk_override_ucast_get(int unit, bcm_port_t ing_port, 
   1524                                  bcm_trunk_t hgtid, int modid, int *enable) 
   1525 {
   1526     int rv = BCM_E_NONE;
   1527     uint32 rval;
   1528     int profile_index;
   1529     _bcm_td_modport_map_profile_t profile;
   1530     int entry_array_size;
   1531 
   1532     if (BCM_GPORT_IS_SET(ing_port)) {
   1533         BCM_IF_ERROR_RETURN(
   1534                 bcm_esw_port_local_get(unit, ing_port, &ing_port));
   1535     }
   1536     if (!SOC_PORT_VALID(unit, ing_port)) {
   1537         return BCM_E_PORT;
   1538     }
   1539 
   1540     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   1541         return BCM_E_PARAM;
   1542     }
   1543 
   1544     soc_mem_lock(unit, MODPORT_MAP_SWm);
   1545 
   1546     /* Get ingress port's current profile index */
   1547     rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   1548     if (BCM_FAILURE(rv)) {
   1549         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1550         return rv;
   1551     }
   1552     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   1553             MODPORT_MAP_INDEX_UPPERf);
   1554 
   1555     /* Get current profile */
   1556     profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries;
   1557     entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t);
   1558     profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array");
   1559     if (NULL == profile.entry_array) {
   1560         soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1561         return BCM_E_MEMORY;
   1562     }
   1563     sal_memcpy(profile.entry_array,
   1564             MODPORT_MAP_PROFILE(unit, profile_index).entry_array,
   1565             entry_array_size);
   1566 
   1567     /* Modify profile */
   1568     *enable = SHR_BITGET(profile.entry_array[modid].higig_trunk_override, 
   1569                         hgtid) ? 1 : 0;
   1570 
   1571     soc_mem_unlock(unit, MODPORT_MAP_SWm);
   1572     sal_free(profile.entry_array);
   1573     return rv;
   1574 }
   1575 
   1576 /*
   1577  * Function:
   1578  *      bcm_td_modport_map_mode_set
   1579  * Purpose:
   1580  *      Set modport map mode.
   1581  * Parameters:
   1582  *      unit - (IN) SOC unit number.
   1583  *      type - (IN) Configuration parameter type.
   1584  *      arg  - (IN) Configuration paramter value.
   1585  * Returns:
   1586  *      BCM_E_xxx
   1587  */
   1588 int
   1589 bcm_td_modport_map_mode_set(int unit, bcm_switch_control_t type, int arg)
   1590 {
   1591     switch (type) {
   1592         case bcmSwitchFabricTrunkAutoIncludeDisable:
   1593             MODPORT_MAP_INFO(unit).auto_include_disable = arg;
   1594             break;
   1595 
   1596         default:
   1597             return BCM_E_PARAM;
   1598     }
   1599 
   1600     return BCM_E_NONE;
   1601 }
   1602 
   1603 /*
   1604  * Function:
   1605  *      bcm_td_modport_map_mode_get
   1606  * Purpose:
   1607  *      Get modport map mode.
   1608  * Parameters:
   1609  *      unit - (IN) SOC unit number.
   1610  *      type - (IN) Configuration parameter type.
   1611  *      arg  - (OUT) Configuration paramter value.
   1612  * Returns:
   1613  *      BCM_E_xxx
   1614  */
   1615 int
   1616 bcm_td_modport_map_mode_get(int unit, bcm_switch_control_t type, int *arg)
   1617 {
   1618     switch (type) {
   1619         case bcmSwitchFabricTrunkAutoIncludeDisable:
   1620             *arg = MODPORT_MAP_INFO(unit).auto_include_disable;
   1621             break;
   1622 
   1623         default:
   1624             return BCM_E_PARAM;
   1625     }
   1626 
   1627     return BCM_E_NONE;
   1628 }
   1629 
   1630 /*
   1631  * Function:
   1632  *      bcm_td_stk_modport_map_port_attach
   1633  * Purpose:
   1634  *      Initialize modport map profiles ptr on new port that added
   1635  *      during flexport operation.
   1636  * Parameters:
   1637  *      unit    - (IN) Unit number.
   1638  *      port    - (IN) Logical port.
   1639  * Returns:
   1640  *      SOC_E_XXX
   1641  */
   1642 int
   1643 bcm_td_stk_modport_map_port_attach(int unit, bcm_port_t port)
   1644 {
   1645     _bcm_td_modport_map_profile_t profile;
   1646     int profile_index;
   1647     int rv;
   1648 
   1649     /* Get the profile_index of default profile */
   1650     profile.num_entries = SOC_MODID_MAX(unit) + 1;
   1651     profile.entry_array = sal_alloc(sizeof(_bcm_td_modport_map_entry_t) *
   1652         profile.num_entries, "profile entry array");
   1653     if (NULL == profile.entry_array) {
   1654         return BCM_E_MEMORY;
   1655     }
   1656     sal_memset(profile.entry_array, 0, sizeof(_bcm_td_modport_map_entry_t) *
   1657             profile.num_entries);
   1658     rv = _bcm_td_modport_map_profile_add(unit, &profile, &profile_index); 
   1659     sal_free(profile.entry_array);
   1660     if (BCM_FAILURE(rv)) {
   1661        return rv;
   1662     }
   1663 
   1664     /* Set the profile ptr to the port */
   1665     BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, profile_index));
   1666     MODPORT_MAP_PROFILE(unit, profile_index).ref_count++;
   1667 
   1668     return BCM_E_NONE;
   1669 }
   1670 
   1671 /*
   1672  * Function:
   1673  *      bcm_td_stk_modport_map_port_detach
   1674  * Purpose:
   1675  *      Detach port from modport map profiles.
   1676  * Parameters:
   1677  *      unit    - (IN) Unit number.
   1678  *      port    - (IN) Logical port.
   1679  * Returns:
   1680  *      SOC_E_XXX
   1681  */
   1682 int
   1683 bcm_td_stk_modport_map_port_detach(int unit, bcm_port_t port)
   1684 {
   1685     int profile_index;
   1686     uint32 val;
   1687 
   1688     SOC_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, port, &val));
   1689     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val,
   1690                                       MODPORT_MAP_INDEX_UPPERf);
   1691 
   1692     MODPORT_MAP_PROFILE(unit, profile_index).ref_count--;
   1693 
   1694     /* Clear the profile ptr */
   1695     BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, 0));
   1696 
   1697     return BCM_E_NONE;
   1698 }
   1699 
   1700 #ifdef BCM_WARM_BOOT_SUPPORT
   1701 /*
   1702  * Function:
   1703  *     bcm_td_modport_map_scache_size_get
   1704  * Purpose:
   1705  *     Get scache size needed to store modport map profile state.
   1706  * Parameters:
   1707  *     unit - Device unit number
   1708  *     size - (OUT) Scache size needed.
   1709  * Returns:
   1710  *     None
   1711  */
   1712 int
   1713 bcm_td_modport_map_scache_size_get(int unit, int *size)
   1714 {
   1715 
   1716 #if defined(BCM_KATANA2_SUPPORT)
   1717     if (SOC_IS_KATANA2(unit)) {
   1718         /* For each MODPORT_MAP_SWm entry, 8 bytes of internal
   1719          * state need to be stored:
   1720          * - First 2 bytes: bit 14 = dest_istrunk[0], bits 13-0 = dest[0].
   1721          * - Next 2 bytes: bit 14 = dest_istrunk[1], bits 13-0 = dest[1].
   1722          * - Next 4 bytes: 32-bit higig_trunk_override.
   1723          */
   1724         *size = (2 * sizeof(uint16) + sizeof(SHR_BITDCL)) 
   1725                                 * soc_mem_index_count(unit, MODPORT_MAP_SWm);
   1726     } else
   1727 #endif /* BCM_KATANA2_SUPPORT */
   1728     {
   1729         /* For each MODPORT_MAP_SWm entry, 6 bytes of internal
   1730          * state need to be stored:
   1731          * - First byte: bit 7 = dest_istrunk[0], bits 6-0 = dest[0].
   1732          * - Second byte: bit 7 = dest_istrunk[1], bits 6-0 = dest[1].
   1733          * - Next 4 bytes: 32-bit higig_trunk_override.
   1734          */
   1735         *size = (2 * sizeof(uint8) + sizeof(SHR_BITDCL)) 
   1736                                 * soc_mem_index_count(unit, MODPORT_MAP_SWm);
   1737     }
   1738     return BCM_E_NONE;
   1739 }
   1740 
   1741 /*
   1742  * Function:
   1743  *     bcm_td_modport_map_sync
   1744  * Purpose:
   1745  *     Store modport map profile state to scache.
   1746  * Parameters:
   1747  *     unit - Device unit number
   1748  *     scache_ptr - Scache pointer.
   1749  * Returns:
   1750  *     None
   1751  */
   1752 int
   1753 bcm_td_modport_map_sync(int unit, uint8 **scache_ptr)
   1754 {
   1755     int i, j, k;
   1756     _bcm_td_modport_map_profile_t profile;
   1757     int istrunk, dest;
   1758     SHR_BITDCL higig_trunk_override;
   1759     uint8 dest_byte;
   1760 #if defined(BCM_KATANA2_SUPPORT)
   1761     uint16 kt2_dest_byte;
   1762     int isenable;
   1763 #endif
   1764 
   1765     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   1766         profile = MODPORT_MAP_PROFILE(unit, i);
   1767         for (j = 0; j < profile.num_entries; j++) {
   1768             for (k = 0; k < 2; k++) {
   1769                 istrunk = profile.entry_array[j].dest_istrunk[k]; 
   1770                 dest = profile.entry_array[j].dest[k];
   1771 #if defined(BCM_KATANA2_SUPPORT)
   1772                 if (SOC_IS_KATANA2(unit)) {
   1773                     /* DEST0 13:0
   1774                      * if ISTRUNK0 == 0 then
   1775                      *  13:8: Egress Physical Port; 7:0: Egress PP_PORT
   1776                      * else if ISTRUNK0 == 1 then
   1777                      *  3:0: Egress HiGig Trunk Group ID.
   1778                      * note: KT2 physical port to pp_port is 1:1 mapped.
   1779                      */
   1780                     isenable = profile.entry_array[j].dest_enable[k];
   1781                     kt2_dest_byte = ((isenable & 0x1) << 15) |
   1782                                     ((istrunk & 0x1) << 14) |
   1783                                     ((dest & 0x3f) << 8) | (dest & 0xff);
   1784                     sal_memcpy(*scache_ptr, &kt2_dest_byte,
   1785                                sizeof(kt2_dest_byte));
   1786                     *scache_ptr += sizeof(kt2_dest_byte);
   1787                 } else
   1788 #endif /* BCM_KATANA2_SUPPORT */
   1789                 {
   1790                     dest_byte = ((istrunk & 0x1) << 7) | (dest & 0x7f);
   1791                     sal_memcpy(*scache_ptr, &dest_byte, sizeof(dest_byte));
   1792                     *scache_ptr += sizeof(dest_byte);
   1793                 }
   1794             }
   1795 
   1796             higig_trunk_override = profile.entry_array[j].higig_trunk_override[0];
   1797             sal_memcpy(*scache_ptr, &higig_trunk_override,
   1798                     sizeof(higig_trunk_override));
   1799             *scache_ptr += sizeof(higig_trunk_override);
   1800         }
   1801     }
   1802 
   1803     return BCM_E_NONE;
   1804 }
   1805 
   1806 /*
   1807  * Function:
   1808  *     bcm_td_modport_map_reinit
   1809  * Purpose:
   1810  *     Retrieve modport map profile state from hardware and scache.
   1811  * Parameters:
   1812  *     unit - Device unit number
   1813  *     scache_ptr - Scache pointer.
   1814  * Returns:
   1815  *     None
   1816  */
   1817 int
   1818 bcm_td_modport_map_reinit(int unit, uint8 **scache_ptr)
   1819 {
   1820     int rv = BCM_E_NONE;
   1821     bcm_port_t ing_port;
   1822     uint32 val;
   1823     int profile_index;
   1824     int i, j, k;
   1825     _bcm_td_modport_map_profile_t profile;
   1826     int profile_buf_size;
   1827     uint8 *profile_buf = NULL;
   1828     int index_min, index_max;
   1829     modport_map_sw_entry_t *modport_map_sw_entry;
   1830     soc_field_t enable_field[2]  = {ENABLE0f, ENABLE1f};
   1831     soc_field_t istrunk_field[2] = {ISTRUNK0f, ISTRUNK1f};
   1832     soc_field_t dest_field[2]    = {DEST0f, DEST1f};
   1833 #if defined(BCM_KATANA2_SUPPORT)
   1834     uint16 kt2_dest_byte;
   1835 #endif
   1836     uint8 dest_byte;
   1837 
   1838     bcm_gport_t gport;
   1839     bcm_trunk_t tid;
   1840     bcm_trunk_chip_info_t chip_info;
   1841     int hg_tid;
   1842     bcm_pbmp_t all_pbmp;
   1843 
   1844     BCM_PBMP_CLEAR(all_pbmp);
   1845     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   1846 #if defined(BCM_KATANA2_SUPPORT)
   1847     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1848         soc_feature(unit, soc_feature_subtag_coe)) {
   1849         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   1850     }
   1851     if (SOC_IS_KATANA2(unit)) {
   1852         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp));
   1853     }
   1854 #endif
   1855 
   1856 
   1857     /* Recover each profile's reference count */
   1858     PBMP_ITER(all_pbmp, ing_port) {
   1859         SOC_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &val));
   1860         profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val,
   1861                                       MODPORT_MAP_INDEX_UPPERf);
   1862         MODPORT_MAP_PROFILE(unit, profile_index).ref_count++;
   1863     }
   1864 
   1865     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   1866         profile = MODPORT_MAP_PROFILE(unit, i);
   1867         if (profile.ref_count == 0) {
   1868             /* Skip the scache region containing the state of this profile */
   1869             if (*scache_ptr != NULL) {
   1870 #if defined(BCM_KATANA2_SUPPORT)
   1871                 if (SOC_IS_KATANA2(unit)) {
   1872                     *scache_ptr += profile.num_entries *
   1873                         (2 * sizeof(kt2_dest_byte) + sizeof(SHR_BITDCL)); 
   1874                 } else
   1875 #endif
   1876                 {
   1877                     *scache_ptr += profile.num_entries *
   1878                         (2 * sizeof(dest_byte) + sizeof(SHR_BITDCL)); 
   1879                 }
   1880             }
   1881             continue;
   1882         }
   1883 
   1884         /* Read profile from MODPOR_MAP_SWm */
   1885 
   1886         profile_buf_size = profile.num_entries *
   1887             soc_mem_entry_words(unit, MODPORT_MAP_SWm) * 4;
   1888         profile_buf = soc_cm_salloc(unit, profile_buf_size,
   1889                 "modport map buffer"); 
   1890         if (NULL == profile_buf) {
   1891             return BCM_E_MEMORY;
   1892         }
   1893 
   1894         index_min = i * profile.num_entries;
   1895         index_max = index_min + profile.num_entries - 1;
   1896         rv = soc_mem_read_range(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY,
   1897                 index_min, index_max, profile_buf);
   1898         if (SOC_FAILURE(rv)) {
   1899             soc_cm_sfree(unit, profile_buf);
   1900             return rv;
   1901         }
   1902 
   1903         /* Recover profile state */
   1904 
   1905         for (j = 0; j < profile.num_entries; j++) {
   1906             modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit,
   1907                     MODPORT_MAP_SWm, modport_map_sw_entry_t *, profile_buf, j);
   1908 
   1909             for (k = 0; k < 2; k++) {
   1910                 profile.entry_array[j].dest_enable[k] =
   1911                     soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
   1912                             enable_field[k]);
   1913                 if (*scache_ptr != NULL) {
   1914 #if defined(BCM_KATANA2_SUPPORT)
   1915                     if (SOC_IS_KATANA2(unit)) {
   1916                         sal_memcpy(&kt2_dest_byte, *scache_ptr,
   1917                                    sizeof(kt2_dest_byte));
   1918                         *scache_ptr += sizeof(kt2_dest_byte);
   1919 
   1920                         profile.entry_array[j].dest_istrunk[k] =
   1921                             (kt2_dest_byte >> 14) & 0x1; 
   1922                         profile.entry_array[j].dest[k] = kt2_dest_byte & 0xff;
   1923                     } else
   1924 #endif /* BCM_KATANA2_SUPPORT */
   1925                     {
   1926                         sal_memcpy(&dest_byte, *scache_ptr, sizeof(dest_byte));
   1927                         *scache_ptr += sizeof(dest_byte);
   1928                         profile.entry_array[j].dest_istrunk[k] =
   1929                             (dest_byte >> 7) & 0x1; 
   1930                         profile.entry_array[j].dest[k] = dest_byte & 0x7f;
   1931                     }
   1932                 } else {
   1933                     profile.entry_array[j].dest_istrunk[k] =
   1934                         soc_MODPORT_MAP_SWm_field32_get(unit,
   1935                             modport_map_sw_entry, istrunk_field[k]);
   1936 #if defined(BCM_KATANA2_SUPPORT)
   1937                     if (SOC_IS_KATANA2(unit)) {
   1938                         profile.entry_array[j].dest[k] =
   1939                             (soc_MODPORT_MAP_SWm_field32_get(unit,
   1940                                 modport_map_sw_entry, dest_field[k])) & 0xff;
   1941                     } else
   1942 #endif /* BCM_KATANA2_SUPPORT */
   1943                     {
   1944                         profile.entry_array[j].dest[k] =
   1945                             soc_MODPORT_MAP_SWm_field32_get(unit,
   1946                                 modport_map_sw_entry, dest_field[k]);
   1947                     }
   1948 
   1949                     /* Infer Higig trunk override info */
   1950                     if (profile.entry_array[j].dest_enable[k] &&
   1951                             !profile.entry_array[j].dest_istrunk[k]) {
   1952                         SOC_GPORT_LOCAL_SET(gport, profile.entry_array[j].dest[k]);
   1953                         rv = bcm_esw_trunk_find(unit, 0, gport, &tid);
   1954                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1955                             soc_cm_sfree(unit, profile_buf);
   1956                             return rv;
   1957                         }
   1958                         if (BCM_SUCCESS(rv)) {
   1959                             /* Port belongs to a Higig trunk group. */
   1960                             rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
   1961                             if (BCM_FAILURE(rv)) {
   1962                                 soc_cm_sfree(unit, profile_buf);
   1963                                 return rv;
   1964                             }
   1965                             if (tid >= chip_info.trunk_fabric_id_min &&
   1966                                     tid <= chip_info.trunk_fabric_id_max) {
   1967                                 hg_tid = tid - chip_info.trunk_fabric_id_min;
   1968                                 SHR_BITSET(
   1969                                     profile.entry_array[j].higig_trunk_override,
   1970                                     hg_tid);
   1971                             } else {
   1972                                 soc_cm_sfree(unit, profile_buf);
   1973                                 return BCM_E_INTERNAL;
   1974                             }
   1975                         } 
   1976                     }
   1977                 }
   1978             }
   1979 
   1980             if (*scache_ptr != NULL) {
   1981                 sal_memcpy(profile.entry_array[j].higig_trunk_override, 
   1982                                             *scache_ptr, sizeof(SHR_BITDCL));
   1983                 *scache_ptr += sizeof(SHR_BITDCL);
   1984             }
   1985 
   1986             if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_COS_VALIDf)) {
   1987                 profile.entry_array[j].voq_cos_valid =
   1988                     soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
   1989                             VOQ_COS_VALIDf);
   1990             }
   1991             if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_GRP_IDf)) {
   1992                 profile.entry_array[j].voq_group_id =
   1993                     soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry,
   1994                             VOQ_GRP_IDf);
   1995             }
   1996         }
   1997 
   1998         soc_cm_sfree(unit, profile_buf);
   1999     }
   2000 
   2001     return BCM_E_NONE;
   2002 }
   2003 
   2004 /*
   2005  * Function:
   2006  *     bcm_td_modport_map_enable_scache_size_get
   2007  * Purpose:
   2008  *     Get scache size needed to store modport map profile enable field.
   2009  * Parameters:
   2010  *     unit - Device unit number
   2011  *     size - (OUT) Scache size needed.
   2012  * Returns:
   2013  *     None
   2014  */
   2015 int
   2016 bcm_td_modport_map_enable_scache_size_get(int unit, int *size)
   2017 {
   2018 
   2019     /* For each MODPORT_MAP_SWm entry, 1 bytes of internal
   2020      * state need to be stored:
   2021      * One byte - bit 1 = enable[1], bit 0 = enable[0].
   2022      */
   2023     *size = (1 * sizeof(uint8)) *
   2024             soc_mem_index_count(unit, MODPORT_MAP_SWm);
   2025     return BCM_E_NONE;
   2026 }
   2027 
   2028 /*
   2029  * Function:
   2030  *     bcm_td_modport_map_enable_sync
   2031  * Purpose:
   2032  *     Store modport map profile enable field to scache.
   2033  * Parameters:
   2034  *     unit - Device unit number
   2035  *     scache_ptr - Scache pointer.
   2036  * Returns:
   2037  *     None
   2038  */
   2039 int
   2040 bcm_td_modport_map_enable_sync(int unit, uint8 **scache_ptr)
   2041 {
   2042     int i, j;
   2043     _bcm_td_modport_map_profile_t profile;
   2044     uint8 enable_byte;
   2045 
   2046     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2047         profile = MODPORT_MAP_PROFILE(unit, i);
   2048         for (j = 0; j < profile.num_entries; j++) {
   2049             enable_byte = ((profile.entry_array[j].dest_enable[1] & 0x1) << 1) |
   2050                             (profile.entry_array[j].dest_enable[0] & 0x1);
   2051             sal_memcpy(*scache_ptr, &enable_byte, sizeof(enable_byte));
   2052             *scache_ptr += sizeof(enable_byte);
   2053         }
   2054     }
   2055 
   2056     return BCM_E_NONE;
   2057 }
   2058 
   2059 /*
   2060  * Function:
   2061  *     bcm_td_modport_map_enable_reinit
   2062  * Purpose:
   2063  *     Retrieve modport map enable field from hardware and scache.
   2064  * Parameters:
   2065  *     unit - Device unit number
   2066  *     scache_ptr - Scache pointer.
   2067  * Returns:
   2068  *     None
   2069  */
   2070 int
   2071 bcm_td_modport_map_enable_reinit(int unit, uint8 **scache_ptr)
   2072 {
   2073     int i, j;
   2074     _bcm_td_modport_map_profile_t profile;
   2075     uint8 enable_byte;
   2076 
   2077     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2078         profile = MODPORT_MAP_PROFILE(unit, i);
   2079         for (j = 0; j < profile.num_entries; j++) {
   2080             sal_memcpy(&enable_byte, *scache_ptr, sizeof(enable_byte));
   2081             *scache_ptr += sizeof(enable_byte);
   2082             profile.entry_array[j].dest_enable[0] = (enable_byte & 0x1);
   2083             profile.entry_array[j].dest_enable[1] = ((enable_byte >> 1) & 0x1);
   2084         }
   2085     }
   2086 
   2087     return BCM_E_NONE;
   2088 }
   2089 
   2090 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   2091 /*
   2092  * Function:
   2093  *     bcm_td_linkflap_trunk_map_scache_size_get
   2094  * Purpose:
   2095  *     Get scache size needed to store port to trunk mapping
   2096  * Parameters:
   2097  *     unit - Device unit number
   2098  *     size - (OUT) Scache size needed.
   2099  * Returns:
   2100  *     None
   2101  */
   2102 int
   2103 bcm_td_linkflap_trunk_map_scache_size_get(int unit, int *size)
   2104 {
   2105     *size = (sizeof(int)) * SOC_MAX_NUM_PORTS;
   2106     return BCM_E_NONE;
   2107 }
   2108 
   2109 /*
   2110  * Function:
   2111  *     bcm_td_linkflap_trunk_map_sync
   2112  * Purpose:
   2113  *     Store linkflap port to trunk mapping.
   2114  * Parameters:
   2115  *     unit - Device unit number
   2116  *     scache_ptr - Scache pointer.
   2117  * Returns:
   2118  *     None
   2119  */
   2120 int
   2121 bcm_td_linkflap_trunk_map_sync(int unit, uint8 **scache_ptr)
   2122 {
   2123     bcm_port_t p;
   2124     int trunk;
   2125     PBMP_PORT_ITER(unit, p) {
   2126         trunk = _BCM_PORT_TRUNK_LINKFLAP_GET(unit, p);
   2127         sal_memcpy(*scache_ptr, &trunk, sizeof(int));
   2128         *scache_ptr += sizeof(int);
   2129     }
   2130     return BCM_E_NONE;
   2131 }
   2132 
   2133 /*
   2134  * Function:
   2135  *     bcm_td_linkflap_trunk_map_reinit
   2136  * Purpose:
   2137  *     Retrieve linkflap port to trunk mapping
   2138  * Parameters:
   2139  *     unit - Device unit number
   2140  *     scache_ptr - Scache pointer.
   2141  * Returns:
   2142  *     None
   2143  */
   2144 int
   2145 bcm_td_linkflap_trunk_map_reinit(int unit, uint8 **scache_ptr)
   2146 {
   2147     bcm_port_t p;
   2148     int trunk;
   2149     PBMP_PORT_ITER(unit, p) {
   2150         sal_memcpy(&trunk, *scache_ptr, sizeof(int));
   2151         *scache_ptr += sizeof(int);
   2152         _BCM_PORT_TRUNK_LINKFLAP_SET(unit, p, trunk);
   2153     }
   2154     return BCM_E_NONE;
   2155 }
   2156 #endif
   2157 
   2158 /*
   2159  * Function:
   2160  *     bcm_td_stk_trunk_override_hi_scache_size_get
   2161  * Purpose:
   2162  *     Get scache size needed to store modport map profile state.
   2163  * Parameters:
   2164  *     unit - Device unit number
   2165  *     size - (OUT) Scache size needed.
   2166  * Returns:
   2167  *     None
   2168  */
   2169 int
   2170 bcm_td_stk_trunk_override_hi_scache_size_get(int unit, int *size)
   2171 {
   2172     uint32 higig_trunk_override_hi_size;
   2173 
   2174     higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX)
   2175                                     - sizeof(SHR_BITDCL);
   2176     *size = higig_trunk_override_hi_size * 
   2177                                     soc_mem_index_count(unit, MODPORT_MAP_SWm);
   2178 
   2179     return BCM_E_NONE;
   2180 }
   2181 
   2182 /*
   2183  * Function:
   2184  *     bcm_td_stk_trunk_override_hi_sync
   2185  * Purpose:
   2186  *     Store stk trunk override high bitmap to scache.
   2187  * Parameters:
   2188  *     unit - Device unit number
   2189  *     scache_ptr - Scache pointer.
   2190  * Returns:
   2191  *     None
   2192  */
   2193 int
   2194 bcm_td_stk_trunk_override_hi_sync(int unit, uint8 **scache_ptr)
   2195 {
   2196     int i, j;
   2197     uint32 higig_trunk_override_hi_size;
   2198     _bcm_td_modport_map_profile_t profile;
   2199     SHR_BITDCL *higig_trunk_override_hi;
   2200 
   2201     higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX)
   2202                                     - sizeof(SHR_BITDCL);
   2203     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2204         profile = MODPORT_MAP_PROFILE(unit, i);
   2205         for (j = 0; j < profile.num_entries; j++) {
   2206             higig_trunk_override_hi = 
   2207                                 &profile.entry_array[j].higig_trunk_override[1];
   2208             sal_memcpy(*scache_ptr, 
   2209                         higig_trunk_override_hi, higig_trunk_override_hi_size);
   2210             *scache_ptr += higig_trunk_override_hi_size;
   2211         }
   2212     }
   2213 
   2214     return BCM_E_NONE;
   2215 }
   2216 
   2217 /*
   2218  * Function:
   2219  *     bcm_td_stk_trunk_override_hi_reinit
   2220  * Purpose:
   2221  *     Retrieve stk trunk override high bitmap scache.
   2222  * Parameters:
   2223  *     unit - Device unit number
   2224  *     scache_ptr - Scache pointer.
   2225  * Returns:
   2226  *     None
   2227  */
   2228 int
   2229 bcm_td_stk_trunk_override_hi_reinit(int unit, uint8 **scache_ptr)
   2230 {
   2231     int i, j;
   2232     uint32 higig_trunk_override_hi_size;
   2233     _bcm_td_modport_map_profile_t profile;
   2234 
   2235     higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX)
   2236                                     - sizeof(SHR_BITDCL);
   2237     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2238         profile = MODPORT_MAP_PROFILE(unit, i);
   2239         if (profile.ref_count == 0) {
   2240             *scache_ptr += profile.num_entries * higig_trunk_override_hi_size; 
   2241             continue;
   2242         }
   2243 
   2244         for (j = 0; j < profile.num_entries; j++) {
   2245             sal_memcpy(&profile.entry_array[j].higig_trunk_override[1], 
   2246                                 *scache_ptr, higig_trunk_override_hi_size);
   2247             *scache_ptr += higig_trunk_override_hi_size;
   2248         }
   2249     }
   2250 
   2251     return BCM_E_NONE;
   2252 }
   2253 
   2254 
   2255 #endif /* BCM_WARM_BOOT_SUPPORT */
   2256 
   2257 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   2258 /*
   2259  * Function:
   2260  *     bcm_td_modport_map_sw_dump
   2261  * Purpose:
   2262  *     Displays modport map software structure information.
   2263  * Parameters:
   2264  *     unit - Device unit number
   2265  * Returns:
   2266  *     None
   2267  */
   2268 void
   2269 bcm_td_modport_map_sw_dump(int unit)
   2270 {
   2271     int num_entries;
   2272     int i, j, word;
   2273     int entry_index;
   2274     _bcm_td_modport_map_profile_t profile;
   2275     int enable, istrunk, dest;
   2276 
   2277     LOG_CLI((BSL_META_U(unit,
   2278                         "  Stack Modport Higig Trunk Auto Include Disable = %d\n"),
   2279              MODPORT_MAP_INFO(unit).auto_include_disable));
   2280 
   2281     LOG_CLI((BSL_META_U(unit,
   2282                         "  Stack Modport Profile\n")));
   2283 
   2284     num_entries = 0;
   2285     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2286         num_entries += MODPORT_MAP_PROFILE(unit, i).num_entries;
   2287     }
   2288     LOG_CLI((BSL_META_U(unit,
   2289                         "      Number of entries: %d\n"), num_entries));
   2290 
   2291     LOG_CLI((BSL_META_U(unit,
   2292                         "      Index RefCount EntriesPerSet - HIGIG PORT or TRUNK\n")));
   2293     entry_index = 0;
   2294     for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) {
   2295         profile = MODPORT_MAP_PROFILE(unit, i);
   2296         if (profile.ref_count == 0) {
   2297             entry_index += profile.num_entries;
   2298             continue;
   2299         }
   2300 
   2301         for (j = 0; j < profile.num_entries; j++) {
   2302             LOG_CLI((BSL_META_U(unit,
   2303                                 "     %5d %8d %13d    "),
   2304                      entry_index++, profile.ref_count, profile.num_entries));
   2305 
   2306             enable = profile.entry_array[j].dest_enable[0]; 
   2307             istrunk = profile.entry_array[j].dest_istrunk[0]; 
   2308             dest = profile.entry_array[j].dest[0]; 
   2309             LOG_CLI((BSL_META_U(unit,
   2310                                 "enable0=%d, istrunk0=%d, dest0=%d, "),
   2311                      enable, istrunk, dest));
   2312 
   2313             enable = profile.entry_array[j].dest_enable[1]; 
   2314             istrunk = profile.entry_array[j].dest_istrunk[1]; 
   2315             dest = profile.entry_array[j].dest[1]; 
   2316             LOG_CLI((BSL_META_U(unit,
   2317                                 "enable1=%d, istrunk1=%d, dest1=%d, "),
   2318                      enable, istrunk, dest));
   2319 
   2320             LOG_CLI((BSL_META_U(unit,
   2321                                 "higig_trunk_override=0x")));
   2322             for (word = _SHR_BITDCLSIZE(_BCM_STK_HGT_GROUP_MAX) - 1;
   2323                 word >= 0; word--) {
   2324                     LOG_CLI((BSL_META_U(unit,
   2325                                         "%08x%s"),
   2326                              profile.entry_array[j].higig_trunk_override[word],
   2327                              word ? "_" : "\n"));
   2328             }
   2329         }
   2330     }
   2331 }
   2332 
   2333 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   2334 
   2335 #endif /* BCM_TRIDENT_SUPPORT */