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

port.c (40934B)


      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 
      8 #include <soc/defs.h>
      9 
     10 #include <assert.h>
     11 
     12 #include <sal/core/libc.h>
     13 #if defined(BCM_TRIUMPH2_SUPPORT)
     14 
     15 #include <shared/util.h>
     16 #include <soc/mem.h>
     17 #include <soc/cm.h>
     18 #include <soc/drv.h>
     19 #include <soc/register.h>
     20 #include <soc/memory.h>
     21 #include <bcm/port.h>
     22 #include <bcm/error.h>
     23 #include <bcm_int/esw/triumph2.h>
     24 #include <bcm_int/esw/port.h>
     25 #include <bcm_int/esw/firebolt.h>
     26 #include <bcm_int/esw/trx.h>
     27 #include <bcm_int/esw/virtual.h>
     28 #include <bcm_int/esw/xgs3.h>
     29 #include <bcm_int/esw/trident2.h>
     30 
     31 STATIC SHR_BITDCL  *vpd_bitmap[BCM_MAX_NUM_UNITS];
     32 #define _VLAN_PROTOCOL_DATA_PROF_USED_GET(_u_, _vpd_) \
     33         SHR_BITGET(vpd_bitmap[_u_], (_vpd_))
     34 #define _VLAN_PROTOCOL_DATA_PROF_USED_SET(_u_, _vpd_) \
     35         SHR_BITSET(vpd_bitmap[_u_], (_vpd_))
     36 #define _VLAN_PROTOCOL_DATA_PROF_USED_CLR(_u_, _vpd_) \
     37         SHR_BITCLR(vpd_bitmap[_u_], (_vpd_))
     38 
     39 int 
     40 _bcm_tr2_port_vpd_bitmap_alloc(int unit) 
     41 {
     42     int num_profiles;
     43     if (vpd_bitmap[unit]) {
     44         sal_free(vpd_bitmap[unit]);
     45         vpd_bitmap[unit] = NULL;
     46     }
     47     num_profiles = soc_mem_index_count(unit, VLAN_PROTOCOL_DATAm) / 
     48                    soc_mem_index_count(unit, VLAN_PROTOCOLm);
     49     vpd_bitmap[unit] = sal_alloc(SHR_BITALLOCSIZE(num_profiles), 
     50                                  "vpd_bitmap");
     51     if (vpd_bitmap[unit] == NULL) {
     52         return BCM_E_MEMORY;
     53     }
     54     sal_memset(vpd_bitmap[unit], 0, SHR_BITALLOCSIZE(num_profiles));
     55     return BCM_E_NONE;
     56 }
     57 
     58 void
     59 _bcm_tr2_port_vpd_bitmap_free(int unit)
     60 {
     61     if (vpd_bitmap[unit]) {
     62         sal_free(vpd_bitmap[unit]);
     63     }
     64     vpd_bitmap[unit] = NULL;
     65     return;
     66 }
     67 
     68 int
     69 _bcm_port_vlan_prot_index_alloc(int unit, int *prof_ptr)
     70 {
     71     int i, num_profiles;
     72     num_profiles = soc_mem_index_count(unit, VLAN_PROTOCOL_DATAm) / 
     73                    soc_mem_index_count(unit, VLAN_PROTOCOLm);
     74     for (i = 0; i < num_profiles; i++) {
     75         if (!_VLAN_PROTOCOL_DATA_PROF_USED_GET(unit, i)) {
     76             _VLAN_PROTOCOL_DATA_PROF_USED_SET(unit, i);
     77             *prof_ptr = i * soc_mem_index_count(unit, VLAN_PROTOCOLm);
     78             break;
     79         }
     80     }
     81     if (i == num_profiles) {
     82 #ifdef BCM_KATANA2_SUPPORT
     83         
     84         if (SOC_IS_KATANA2(unit)) {
     85             *prof_ptr = i * soc_mem_index_count(unit, VLAN_PROTOCOLm);
     86             return BCM_E_NONE;
     87         }
     88 #endif
     89         return BCM_E_RESOURCE;
     90     } else {
     91         return BCM_E_NONE;
     92     }
     93 } 
     94 
     95 /*
     96  * Function:
     97  *      _bcm_port_vlan_prot_index_free
     98  * Purpose:
     99  *      Free given VLAN protocol profile index.
    100  * Parameters:
    101  *      unit       - (IN) Unit number.
    102  *      prof_ptr   - (IN) VLAN Protocol Profile index.
    103  * Returns:
    104  *      BCM_E_XXX
    105  * Notes:
    106  */
    107 int
    108 _bcm_port_vlan_prot_index_free(int unit, int prof_ptr)
    109 {
    110     int index;
    111     int num_profiles;
    112 
    113     num_profiles = soc_mem_index_count(unit, VLAN_PROTOCOL_DATAm) /
    114                    soc_mem_index_count(unit, VLAN_PROTOCOLm);
    115 
    116     index = prof_ptr / soc_mem_index_count(unit, VLAN_PROTOCOLm);
    117 
    118     if ((index < 0) || (index >= num_profiles)) {
    119             return BCM_E_INTERNAL;
    120     }
    121 
    122     _VLAN_PROTOCOL_DATA_PROF_USED_CLR(unit, index);
    123 
    124     return BCM_E_NONE;
    125 }
    126 
    127 int
    128 _bcm_tr2_port_tab_get(int unit, bcm_port_t port,
    129                       soc_field_t field, int *value)
    130 
    131 {
    132     port_tab_entry_t pent;
    133     soc_mem_t mem;
    134     int rv = BCM_E_NONE;
    135 
    136     mem = SOC_PORT_MEM_TAB(unit, port);
    137     if (!SOC_MEM_FIELD_VALID(unit, mem, field)) {
    138         return (BCM_E_UNAVAIL);
    139     }
    140     sal_memset(&pent, 0, sizeof(port_tab_entry_t));
    141     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    142     SOC_PORT_MOD_OFFSET(unit, port), &pent);
    143 
    144     if (BCM_SUCCESS(rv)) {
    145         *value = soc_PORT_TABm_field32_get(unit, &pent, field);
    146     }
    147     return rv;
    148 }
    149 
    150 
    151 /* Port table field programming - assumes PORT_LOCK is taken */
    152 int
    153 _bcm_tr2_port_tab_set(int unit, bcm_port_t port, 
    154                       soc_field_t field, int value)
    155 
    156 {
    157     port_tab_entry_t pent;
    158     soc_mem_t mem;
    159     int rv, cur_val;
    160 
    161     mem = SOC_PORT_MEM_TAB(unit, port);
    162     if (!SOC_MEM_FIELD_VALID(unit, mem, field)) {
    163         return (BCM_E_UNAVAIL);
    164     }
    165     sal_memset(&pent, 0, sizeof(port_tab_entry_t));
    166     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    167                       SOC_PORT_MOD_OFFSET(unit, port), &pent);
    168 
    169     if (BCM_SUCCESS(rv)) {
    170         cur_val = soc_PORT_TABm_field32_get(unit, &pent, field);
    171         if (value != cur_val) {
    172             soc_PORT_TABm_field32_set(unit, &pent, field, value);
    173             rv = soc_mem_write(unit, mem,
    174                                MEM_BLOCK_ALL, port, &pent);
    175         }
    176     }
    177     return rv;
    178 }
    179 
    180 /* Helper functions for bcmPortControlLanes 
    181  * Used for flex-port support
    182  */
    183 int 
    184 _bcm_tr2_port_lanes_get(int unit, bcm_port_t port, int *value)
    185 {
    186     int rv = BCM_E_NONE;
    187     uint32 rval, bitpos = 0;
    188     /*    coverity[new_values]    */
    189 
    190     if (!_bcm_esw_valid_flex_port_controlling_port(unit, port)) {
    191         return (BCM_E_PORT);
    192     }
    193 
    194     switch (port) {
    195     case 30:
    196         bitpos = 6;
    197         break;
    198     case 34:
    199         bitpos = 7;
    200         break;
    201     case 38:
    202         bitpos = 8;
    203         break;
    204     case 42:
    205         bitpos = 9;
    206         break;
    207     case 46:
    208         bitpos = 10;
    209         break;
    210     case 50:
    211         bitpos = 11;
    212         break;
    213     
    214     /* Defensive Default */
    215     /* coverity[dead_error_begin] */
    216     default:
    217         return (BCM_E_PORT);
    218     }
    219 
    220     BCM_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &rval));
    221 
    222     if (rval & (1 << bitpos)) {
    223         *value = 4;
    224     } else {
    225         *value = 1;
    226     }
    227     return rv;
    228 }
    229 
    230 static const uint16 _soc_triumph2_int_phy_addr[] = {
    231     0x00, /* Port  0 (cmic)         N/A */
    232     0x99, /* Port  1 (9SERDES)      IntBus=0 Addr=0x19 */
    233     0x81, /* Port  2 (8SERDES_0)    IntBus=0 Addr=0x01 */
    234     0x82, /* Port  3 (8SERDES_0)    IntBus=0 Addr=0x02 */
    235     0x83, /* Port  4 (8SERDES_0)    IntBus=0 Addr=0x03 */
    236     0x84, /* Port  5 (8SERDES_0)    IntBus=0 Addr=0x04 */
    237     0x85, /* Port  6 (8SERDES_0)    IntBus=0 Addr=0x05 */
    238     0x86, /* Port  7 (8SERDES_0)    IntBus=0 Addr=0x06 */
    239     0x87, /* Port  8 (8SERDES_0)    IntBus=0 Addr=0x07 */
    240     0x88, /* Port  9 (8SERDES_0)    IntBus=0 Addr=0x08 */
    241     0x89, /* Port 10 (8SERDES_1)    IntBus=0 Addr=0x09 */
    242     0x8a, /* Port 11 (8SERDES_1)    IntBus=0 Addr=0x0a */
    243     0x8b, /* Port 12 (8SERDES_1)    IntBus=0 Addr=0x0b */
    244     0x8c, /* Port 13 (8SERDES_1)    IntBus=0 Addr=0x0c */
    245     0x8d, /* Port 14 (8SERDES_1)    IntBus=0 Addr=0x0d */
    246     0x8e, /* Port 15 (8SERDES_1)    IntBus=0 Addr=0x0e */
    247     0x8f, /* Port 16 (8SERDES_1)    IntBus=0 Addr=0x0f */
    248     0x90, /* Port 17 (8SERDES_1)    IntBus=0 Addr=0x10 */
    249     0x91, /* Port 18 (9SERDES)      IntBus=0 Addr=0x11 */
    250     0x92, /* Port 19 (9SERDES)      IntBus=0 Addr=0x12 */
    251     0x93, /* Port 20 (9SERDES)      IntBus=0 Addr=0x13 */
    252     0x94, /* Port 21 (9SERDES)      IntBus=0 Addr=0x14 */
    253     0x95, /* Port 22 (9SERDES)      IntBus=0 Addr=0x15 */
    254     0x96, /* Port 23 (9SERDES)      IntBus=0 Addr=0x16 */
    255     0x97, /* Port 24 (9SERDES)      IntBus=0 Addr=0x17 */
    256     0x98, /* Port 25 (9SERDES)      IntBus=0 Addr=0x18 */
    257     0xd9, /* Port 26 (HC0)          IntBus=2 Addr=0x19 */
    258     0xda, /* Port 27 (HC1)          IntBus=2 Addr=0x1a */
    259     0xdb, /* Port 28 (HC2)          IntBus=2 Addr=0x1b */
    260     0xdc, /* Port 29 (HC3)          IntBus=2 Addr=0x1c */
    261     0xc1, /* Port 30 (HL0)          IntBus=2 Addr=0x01 */
    262     0xc2, /* Port 31 (HL0)          IntBus=2 Addr=0x02 */
    263     0xc3, /* Port 32 (HL0)          IntBus=2 Addr=0x03 */
    264     0xc4, /* Port 33 (HL0)          IntBus=2 Addr=0x04 */
    265     0xc5, /* Port 34 (HL1)          IntBus=2 Addr=0x05 */
    266     0xc6, /* Port 35 (HL1)          IntBus=2 Addr=0x06 */
    267     0xc7, /* Port 36 (HL1)          IntBus=2 Addr=0x07 */
    268     0xc8, /* Port 37 (HL1)          IntBus=2 Addr=0x08 */
    269     0xc9, /* Port 38 (HL2)          IntBus=2 Addr=0x09 */
    270     0xca, /* Port 39 (HL2)          IntBus=2 Addr=0x0a */
    271     0xcb, /* Port 40 (HL2)          IntBus=2 Addr=0x0b */
    272     0xcc, /* Port 41 (HL2)          IntBus=2 Addr=0x0c */
    273     0xcd, /* Port 42 (HL3)          IntBus=2 Addr=0x0d */
    274     0xce, /* Port 43 (HL3)          IntBus=2 Addr=0x0e */
    275     0xcf, /* Port 44 (HL3)          IntBus=2 Addr=0x0f */
    276     0xd0, /* Port 45 (HL3)          IntBus=2 Addr=0x10 */
    277     0xd1, /* Port 46 (HL4)          IntBus=2 Addr=0x11 */
    278     0xd2, /* Port 47 (HL4)          IntBus=2 Addr=0x12 */
    279     0xd3, /* Port 48 (HL4)          IntBus=2 Addr=0x13 */
    280     0xd4, /* Port 49 (HL4)          IntBus=2 Addr=0x14 */
    281     0xd5, /* Port 50 (HL5)          IntBus=2 Addr=0x15 */
    282     0xd6, /* Port 51 (HL5)          IntBus=2 Addr=0x16 */
    283     0xd7, /* Port 52 (HL5)          IntBus=2 Addr=0x17 */
    284     0xd8, /* Port 53 (HL5)          IntBus=2 Addr=0x18 */
    285 };
    286 
    287 int 
    288 _bcm_tr2_port_lanes_set(int unit, bcm_port_t port, int value)
    289 {
    290     uint16      dev_id;
    291     uint8       rev_id;
    292     int i, okay, old_value, count, rv = BCM_E_NONE;
    293     uint32 rval, val2, to_usec, mode, flags, bitpos = 0;
    294     uint64 rval64;
    295     soc_info_t *si;
    296     soc_field_t xq_rst2 = INVALIDf;
    297     uint16 phy0, phy1, phy2, phy3;
    298     bcm_port_t it_port;
    299     iarb_tdm_table_entry_t iarb_tdm;
    300     arb_tdm_table_entry_t arb_tdm;
    301     mac_driver_t *macd;
    302 
    303     si = &SOC_INFO(unit);
    304 
    305     soc_cm_get_id(unit, &dev_id, &rev_id);
    306 
    307     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
    308                                    (10 * MILLISECOND_USEC);
    309 
    310     if (!_bcm_esw_valid_flex_port_controlling_port(unit, port)) {
    311         return BCM_E_PORT;
    312     }
    313 
    314     if ((value != 1) && (value != 4)) {
    315         return BCM_E_PARAM;
    316     }
    317     BCM_IF_ERROR_RETURN(_bcm_tr2_port_lanes_get(unit, port, &old_value));
    318 
    319 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \
    320     si->ptype.num = 0; \
    321     si->ptype.min = si->ptype.max = -1; \
    322     PBMP_ITER(si->ptype.bitmap, it_port) { \
    323         si->ptype.port[si->ptype.num++] = it_port; \
    324         if (si->ptype.min < 0) { \
    325             si->ptype.min = it_port; \
    326         } \
    327         if (it_port > si->ptype.max) { \
    328             si->ptype.max = it_port; \
    329         } \
    330     }
    331 
    332     /* Step 1: Change the SOC bitmaps */
    333     if ((value == 1) && (old_value == 4)) {
    334         /* The block was originally a single high-speed port */
    335         SOC_CONTROL_LOCK(unit);
    336         if (IS_HG_PORT(unit, port)) {
    337             SOC_PBMP_PORT_REMOVE(si->st.bitmap, port);
    338             SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port);
    339             SOC_PBMP_PORT_ADD(si->ether.bitmap, port);
    340         } else {
    341             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
    342         }
    343         SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
    344         si->port_speed_max[port] = 1000;
    345         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_GE);
    346         for (i = port + 1; i < port + 4; i++) {
    347             SOC_PBMP_PORT_REMOVE(si->ge.disabled_bitmap, i);
    348             SOC_PBMP_PORT_REMOVE(si->ether.disabled_bitmap, i);
    349             SOC_PBMP_PORT_REMOVE(si->port.disabled_bitmap, i);
    350             SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, i);
    351             si->port_speed_max[i] = 1000;
    352             soc_port_cmap_set(unit, i, SOC_CTR_TYPE_GE);
    353         }
    354         RECONFIGURE_PORT_TYPE_INFO(ether);
    355         RECONFIGURE_PORT_TYPE_INFO(st);
    356         RECONFIGURE_PORT_TYPE_INFO(hg);
    357         RECONFIGURE_PORT_TYPE_INFO(xe);
    358         RECONFIGURE_PORT_TYPE_INFO(ge);
    359         SOC_CONTROL_UNLOCK(unit);
    360         BCM_IF_ERROR_RETURN(_bcm_tr2_port_tab_set(unit, port, PORT_TYPEf, 0));
    361         BCM_IF_ERROR_RETURN
    362             (soc_reg_field32_modify(unit, EGR_PORT_64r, port, PORT_TYPEf, 0));
    363     } else if ((value == 4) && (old_value == 1)) {
    364         /* The block originally had 4 GE ports */
    365         SOC_CONTROL_LOCK(unit);
    366         SOC_PBMP_PORT_ADD(si->st.bitmap, port);
    367         SOC_PBMP_PORT_ADD(si->hg.bitmap, port);
    368         SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port);
    369         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
    370 	switch (dev_id) {
    371 	case BCM56526_DEVICE_ID:
    372 	  si->port_speed_max[port] = 13000;
    373 	  break;
    374 	case BCM56636_DEVICE_ID:
    375 	case BCM56638_DEVICE_ID:
    376 	  si->port_speed_max[port] = 12000;
    377 	  break;
    378 	default:
    379 	  si->port_speed_max[port] = 10000;
    380 	}
    381         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_XE);
    382         for (i = port + 1; i < port + 4; i++) {
    383             SOC_PBMP_PORT_ADD(si->ge.disabled_bitmap, i);
    384             SOC_PBMP_PORT_ADD(si->ether.disabled_bitmap, i);
    385             SOC_PBMP_PORT_ADD(si->port.disabled_bitmap, i);
    386             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, i);
    387         }
    388         RECONFIGURE_PORT_TYPE_INFO(ether);
    389         RECONFIGURE_PORT_TYPE_INFO(st);
    390         RECONFIGURE_PORT_TYPE_INFO(hg);
    391         RECONFIGURE_PORT_TYPE_INFO(ge);
    392         SOC_CONTROL_UNLOCK(unit);
    393         BCM_IF_ERROR_RETURN(_bcm_tr2_port_tab_set(unit, port, PORT_TYPEf, 1));
    394         BCM_IF_ERROR_RETURN
    395             (soc_reg_field32_modify(unit, EGR_PORT_64r, port, PORT_TYPEf, 1));
    396     }
    397 #undef RECONFIGURE_PORT_TYPE_INFO
    398     soc_dport_map_update(unit);
    399 
    400     /* Step 2: Perform necessary block-level reset and initialization */
    401     /* Egress disable */
    402     rval = 0;
    403     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 0);
    404     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    405     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 1, rval));
    406     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 2, rval));
    407     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 3, rval));
    408 
    409     /* Hold the XQPORT hotswap reset */
    410     switch (port) {
    411     case 30:
    412         bitpos = 6;
    413         xq_rst2 = XQ0_HOTSWAP_RST_Lf;
    414         break;
    415     case 34:
    416         bitpos = 7;
    417         xq_rst2 = XQ1_HOTSWAP_RST_Lf;
    418         break;
    419     case 38:
    420         bitpos = 8;
    421         xq_rst2 = XQ2_HOTSWAP_RST_Lf;
    422         break;
    423     case 42:
    424         bitpos = 9;
    425         xq_rst2 = XQ3_HOTSWAP_RST_Lf;
    426         break;
    427     case 46:
    428         bitpos = 10;
    429         xq_rst2 = XQ4_HOTSWAP_RST_Lf;
    430         break;
    431     case 50:
    432         bitpos = 11;
    433         xq_rst2 = XQ5_HOTSWAP_RST_Lf;
    434         break;
    435     default:
    436         break;
    437     }
    438     /* coverity[result_independent_of_operands] */
    439     BCM_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REG_2r(unit, &val2));
    440     soc_reg_field_set(unit, CMIC_SOFT_RESET_REG_2r, &val2, 
    441                       xq_rst2, 0);
    442     /* coverity[result_independent_of_operands] */
    443     BCM_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REG_2r(unit, val2));
    444     sal_usleep(to_usec);
    445 
    446     /* Program the ingress and MMU TDMs */
    447     count = -1;
    448     for (i = 0; i < soc_mem_index_count(unit, ARB_TDM_TABLEm); i++) {
    449         BCM_IF_ERROR_RETURN
    450             (READ_ARB_TDM_TABLEm(unit, MEM_BLOCK_ANY, i, &arb_tdm));
    451         BCM_IF_ERROR_RETURN
    452             (READ_IARB_TDM_TABLEm(unit, MEM_BLOCK_ANY, i, &iarb_tdm));
    453         it_port = soc_ARB_TDM_TABLEm_field32_get(unit, &arb_tdm, PORT_NUMf);
    454         /* First set to disabled - 63 */
    455         if (old_value == value) {
    456             continue;
    457         } else if (old_value == 4 && value == 1) {
    458             if (port != it_port) {
    459                 continue;
    460             }
    461         } else {
    462             if ((it_port != port) && (it_port != port + 1) && 
    463                 (it_port != port + 2) && (it_port != port + 3)) {
    464                 continue;
    465             }
    466         }
    467         soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, 63);
    468         soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 63);
    469         BCM_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    470                                                   &iarb_tdm));
    471         BCM_IF_ERROR_RETURN(WRITE_ARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    472                                                  &arb_tdm));
    473         /* Then program the desired value */
    474         if (old_value == 4 && value == 1) {
    475             count++;
    476             soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, 
    477                                            port + (count % 4));
    478             soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 
    479                                             port + (count % 4));
    480         } else {
    481             soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, port);
    482             soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, port);
    483         }
    484         BCM_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    485                                                   &iarb_tdm));
    486         BCM_IF_ERROR_RETURN(WRITE_ARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    487                                                  &arb_tdm));
    488         if (soc_ARB_TDM_TABLEm_field32_get(unit, &arb_tdm, WRAP_ENf)) {
    489             break;
    490         }
    491     }
    492 
    493     /* Clear the ECRC register */
    494     for (i = port; i < port + 4; i++) {
    495         BCM_IF_ERROR_RETURN(WRITE_TOQ_EP_CREDITr(unit, i, 0));
    496     }
    497 
    498     /* Reset the EP */
    499     BCM_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &rval));
    500     rval |= (1 << (bitpos - 6));
    501     BCM_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, rval));
    502     sal_usleep(to_usec);
    503     BCM_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &rval));
    504     if (value == 4) {
    505         rval |= (1 << bitpos);
    506     } else {
    507         rval &= ~(1 << bitpos);
    508     }  
    509     /* coverity[BAD_SHIFT: FALSE] */
    510     rval &= ~(1 << (bitpos - 6));
    511     BCM_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, rval));
    512     sal_usleep(to_usec);
    513 
    514     /* Bring the XQPORT block out of reset */
    515     /* coverity[result_independent_of_operands] */
    516     BCM_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REG_2r(unit, &val2));
    517     soc_reg_field_set(unit, CMIC_SOFT_RESET_REG_2r, &val2, 
    518                       xq_rst2, 1);
    519     /* coverity[result_independent_of_operands] */
    520     BCM_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REG_2r(unit, val2));
    521     sal_usleep(to_usec);
    522 
    523     /* Bring the hyperlite out of reset */
    524     soc_xgxs_reset(unit, port);
    525     BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XQPORT_XGXS_NEWCTL_REGr, 
    526                                                port, TXD1G_FIFO_RSTBf, 0xf));
    527 
    528     /* Change the XQPORT block mode */
    529     mode = (value == 4) ? 2 : 1; /* 2 = high-speed, 1 = GE */
    530     SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval));
    531     soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, 
    532                       XQPORT_MODE_BITSf, mode);
    533     SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval));
    534     if (value == 4) {
    535         rval = 0;
    536         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, XPORT_ENf, 1);
    537         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1);
    538         SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval));
    539     }
    540 
    541     /* Egress Enable */
    542     rval = 0;
    543     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 1);
    544     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    545 
    546     rval = 0;
    547     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 
    548                       (value == 1) ? 1 : 0);
    549     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 1, rval));
    550     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 2, rval));
    551     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port + 3, rval));
    552 
    553     /* Step 3: Port probe and initialization */
    554     flags = 0;
    555     if (value == 1) {
    556         phy0 = soc_property_port_get(unit, port, spn_FLEX_PORT_PHY_ADDR, 0);
    557         if (!phy0) {
    558             phy0 = _soc_triumph2_int_phy_addr[port];
    559             flags = _SHR_PORT_PHY_INTERNAL;
    560         }
    561         SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port));
    562         SOC_IF_ERROR_RETURN(soc_phy_cfg_addr_set(unit, port, flags, phy0));
    563         BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay));
    564         if (!okay) {
    565             return BCM_E_INTERNAL;
    566         }
    567         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    568         phy1 = soc_property_port_get(unit, port + 1, spn_FLEX_PORT_PHY_ADDR, 0);
    569         if (!phy1) {
    570             phy1 = _soc_triumph2_int_phy_addr[port + 1];
    571             flags = _SHR_PORT_PHY_INTERNAL;
    572         }  
    573         SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 1));
    574         SOC_IF_ERROR_RETURN(soc_phy_cfg_addr_set(unit, port + 1, flags, phy1));
    575         BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port + 1, &okay));
    576         if (!okay) {
    577             return BCM_E_INTERNAL;
    578         }     
    579         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port + 1, TRUE));
    580         phy2 = soc_property_port_get(unit, port + 2, spn_FLEX_PORT_PHY_ADDR, 0);
    581         if (!phy2) {
    582             phy2 = _soc_triumph2_int_phy_addr[port + 2];
    583             flags = _SHR_PORT_PHY_INTERNAL;
    584         }
    585         SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 2));
    586         SOC_IF_ERROR_RETURN(soc_phy_cfg_addr_set(unit, port + 2, flags, phy2));
    587         BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port + 2, &okay));
    588         if (!okay) {
    589             return BCM_E_INTERNAL;
    590         }
    591         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port + 2, TRUE));
    592         phy3 = soc_property_port_get(unit, port + 3, spn_FLEX_PORT_PHY_ADDR, 0);
    593         if (!phy3) {
    594             phy3 = _soc_triumph2_int_phy_addr[port + 3];
    595             flags = _SHR_PORT_PHY_INTERNAL;
    596         }
    597         SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 3));
    598         SOC_IF_ERROR_RETURN(soc_phy_cfg_addr_set(unit, port + 3, flags, phy3));
    599         BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port + 3, &okay));
    600         if (!okay) {
    601             return BCM_E_INTERNAL;
    602         }
    603         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port + 3, TRUE));
    604     } else {
    605         phy0 = soc_property_port_get(unit, port, spn_FLEX_PORT_PHY_ADDR, 0);
    606         if (!phy0) {
    607             phy0 = _soc_triumph2_int_phy_addr[port];
    608             flags = _SHR_PORT_PHY_INTERNAL;
    609         } 
    610         SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port));
    611         if (old_value == 1) {
    612             SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 1));
    613             SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 2));
    614             SOC_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port + 3));
    615         }
    616         SOC_IF_ERROR_RETURN(soc_phy_cfg_addr_set(unit, port, flags, phy0));
    617         BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay));
    618         if (!okay) {
    619             return BCM_E_INTERNAL;
    620         }
    621 
    622         /* Need to reset the Bigmac to make registers accessible */
    623         SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd));
    624 
    625         SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64));
    626         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, TXRESETf, 1);
    627         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, RXRESETf, 1);
    628         SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64));
    629 
    630         SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64));
    631         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, TXRESETf, 0);
    632         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, RXRESETf, 0);
    633         SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64));
    634 
    635         SOC_IF_ERROR_RETURN(MAC_INIT(macd, unit, port));
    636 
    637         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    638     }
    639     return rv;
    640 }
    641 
    642 int _bcm_tr2_ing_pri_cng_map_default_entry_add(int unit, 
    643                                                soc_profile_mem_t *prof)
    644 {
    645     ing_pri_cng_map_entry_t pri_map[16];
    646     phb_mapping_tbl_1_entry_t phb_pri_map[16];
    647     ing_untagged_phb_entry_t phb;
    648     int index, pkt_pri, cfi, base = 0;
    649     void *entries[2];
    650 
    651     sal_memset(pri_map, 0, sizeof(ing_pri_cng_map_entry_t) * 16);
    652     sal_memset(&phb, 0, sizeof(phb));
    653 
    654     for (cfi = 0; cfi <= 1; cfi++) {
    655         for (pkt_pri = 0; pkt_pri <= 7; pkt_pri++) {
    656             index = (pkt_pri << 1) | cfi;
    657             if (SOC_IS_TRIDENT3X(unit)) {
    658                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &phb_pri_map[index], PRIf,
    659                                     pkt_pri);
    660                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &phb_pri_map[index],
    661                                     CNGf, cfi);
    662             } else {
    663                 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map[index], PRIf,
    664                                     pkt_pri);
    665                 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map[index],
    666                                     CNGf, cfi);
    667             } 
    668         }
    669     }
    670     if (SOC_IS_TRIDENT3X(unit)) {
    671         entries[0] = &phb_pri_map;
    672     } else {
    673         entries[0] = &pri_map;
    674     }
    675 
    676     /** Revisit ---- No ING_UNTAGGED_PHB found in Trident3 */
    677     entries[1] = &phb;
    678     BCM_IF_ERROR_RETURN
    679         (soc_profile_mem_add(unit, prof, entries, 16, (uint32 *)&base));
    680 
    681     if (SOC_IS_TRIDENT3X(unit)) {
    682         if (base != soc_mem_index_min(unit, PHB_MAPPING_TBL_1m)) {
    683             return BCM_E_INTERNAL;
    684         }
    685     } else {
    686         if (base != soc_mem_index_min(unit, ING_PRI_CNG_MAPm)) {
    687             return BCM_E_INTERNAL;
    688         }
    689     }
    690 
    691     return BCM_E_NONE;
    692 }
    693 
    694 /*
    695  * Function:
    696  *      _bcm_tr2_port_vlan_priority_map_get
    697  * Description:
    698  *      Get the mapping of incomming port, packet priority, and cfi bit to
    699  *      switch internal priority and color.
    700  * Parameters:
    701  *      unit         - (IN) Device number
    702  *      port         - (IN) Port number
    703  *      pkt_pri      - (IN) Packet priority
    704  *      cfi          - (IN) Packet CFI
    705  *      internal_pri - (OUT) Internal priority
    706  *      color        - (OUT) color
    707  * Return Value:
    708  *      BCM_E_XXX
    709  * Note:
    710  *      This API programs only the mapping table. 
    711  */
    712 int
    713 _bcm_tr2_port_vlan_priority_map_get(int unit, bcm_port_t port, int pkt_pri,
    714                                     int cfi, int *internal_pri, 
    715                                     bcm_color_t *color)
    716 {
    717     port_tab_entry_t pent;
    718     ing_pri_cng_map_entry_t pri_cng_entry;
    719      phb_mapping_tbl_1_entry_t phb_pri_map;
    720     int rv; 
    721     int index;
    722     int hw_color;
    723     int ptr;
    724 
    725     sal_memset(&pent, 0, sizeof(port_tab_entry_t));
    726     sal_memset(&pri_cng_entry, 0, sizeof(ing_pri_cng_map_entry_t));
    727 
    728     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
    729                       SOC_PORT_MOD_OFFSET(unit, port), &pent);
    730     BCM_IF_ERROR_RETURN(rv);
    731 
    732     ptr = soc_PORT_TABm_field32_get(unit, &pent, TRUST_DOT1P_PTRf);
    733 
    734     index = ((pkt_pri << 1) | cfi) + (ptr * _BCM_TR2_PRI_CNG_MAP_SIZE);
    735 
    736     if (SOC_IS_TRIDENT3X(unit)) {
    737         rv = soc_mem_read(unit, PHB_MAPPING_TBL_1m, MEM_BLOCK_ANY, 
    738                           index, &phb_pri_map);
    739 
    740         *internal_pri = soc_mem_field32_get(unit, PHB_MAPPING_TBL_1m, 
    741                                             (uint32 *)&phb_pri_map, PRIf);
    742         hw_color = soc_mem_field32_get(unit, PHB_MAPPING_TBL_1m, 
    743                                        (uint32 *)&phb_pri_map, CNGf);
    744     } else {
    745         rv = soc_mem_read(unit, ING_PRI_CNG_MAPm, MEM_BLOCK_ANY,
    746                           index, &pri_cng_entry);
    747 
    748         *internal_pri = soc_mem_field32_get(unit, ING_PRI_CNG_MAPm,
    749                                             (uint32 *)&pri_cng_entry, PRIf);
    750         hw_color = soc_mem_field32_get(unit, ING_PRI_CNG_MAPm,
    751                                        (uint32 *)&pri_cng_entry, CNGf);
    752     }
    753 
    754     *color = _BCM_COLOR_DECODING(unit, hw_color);
    755     return (rv);
    756 }
    757 
    758 /*
    759  * Function:
    760  *      _bcm_tr2_port_vlan_priority_map_set
    761  * Description:
    762  *      Define the mapping of incomming port, packet priority, and cfi bit to
    763  *      switch internal priority and color.
    764  * Parameters:
    765  *      unit         - (IN) Device number
    766  *      port         - (IN) Port number
    767  *      pkt_pri      - (IN) Packet priority
    768  *      cfi          - (IN) Packet CFI
    769  *      internal_pri - (IN) Internal priority
    770  *      color        - (IN) color
    771  * Return Value:
    772  *      BCM_E_XXX
    773  * Note:
    774  *      This API programs only the mapping table. 
    775  */
    776 int
    777 _bcm_tr2_port_vlan_priority_map_set(int unit, bcm_port_t port, int pkt_pri,
    778                                    int cfi, int internal_pri, bcm_color_t color)
    779 {
    780     ing_pri_cng_map_entry_t pri_cng_map[_BCM_TR2_PRI_CNG_MAP_SIZE];
    781     phb_mapping_tbl_1_entry_t phb_pri_cng_map[_BCM_TR2_PRI_CNG_MAP_SIZE];
    782     void *entries[1];
    783     port_tab_entry_t pent;
    784     int index;
    785     int rv;
    786     int new_ptr;
    787     int old_ptr;
    788     char *pri_map;
    789     int alloc_size;
    790 
    791     /* Allocate buffer for dma read. */
    792     alloc_size = _BCM_TR2_PRI_CNG_MAP_SIZE * sizeof (ing_pri_cng_map_entry_t);
    793     pri_map = soc_cm_salloc(unit, alloc_size, "TR2 pri cng map");
    794     if (NULL == pri_map) {
    795         return (BCM_E_MEMORY);
    796     }
    797     sal_memset(pri_map, 0, alloc_size);
    798     sal_memset(pri_cng_map, 0, alloc_size);
    799 
    800     /* Get man id from port table. */
    801     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
    802                       SOC_PORT_MOD_OFFSET(unit, port), &pent);
    803     if (BCM_FAILURE(rv)) {
    804         soc_cm_sfree(unit, pri_map);
    805         return (rv);
    806     }
    807     old_ptr = soc_PORT_TABm_field32_get(unit, &pent, TRUST_DOT1P_PTRf);
    808 
    809     if (SOC_IS_TRIDENT3X(unit)) {
    810         /* Get the existing profile chunk */
    811         index = old_ptr * _BCM_TR2_PRI_CNG_MAP_SIZE;
    812         rv = soc_mem_read_range(unit, PHB_MAPPING_TBL_1m, MEM_BLOCK_ANY,
    813                                 index, index + _BCM_TR2_PRI_CNG_MAP_SIZE - 1,
    814                                 pri_map);
    815         if (BCM_FAILURE(rv)) {
    816             soc_cm_sfree(unit, pri_map);
    817             return (rv);
    818          }
    819         for (index = 0; index < _BCM_TR2_PRI_CNG_MAP_SIZE; index++) {
    820             entries[0] = soc_mem_table_idx_to_pointer(unit, PHB_MAPPING_TBL_1m,
    821                                                       void *, pri_map, index);
    822             sal_memcpy(phb_pri_cng_map + index, entries[0],
    823                        sizeof(phb_mapping_tbl_1_entry_t));
    824         }
    825     } else {
    826         /* Get the existing profile chunk */
    827         index = old_ptr * _BCM_TR2_PRI_CNG_MAP_SIZE;
    828         rv = soc_mem_read_range(unit, ING_PRI_CNG_MAPm, MEM_BLOCK_ANY,
    829                                 index, index + _BCM_TR2_PRI_CNG_MAP_SIZE - 1,
    830                                 pri_map);
    831         if (BCM_FAILURE(rv)) {
    832             soc_cm_sfree(unit, pri_map);
    833             return (rv);
    834          }
    835         for (index = 0; index < _BCM_TR2_PRI_CNG_MAP_SIZE; index++) {
    836             entries[0] = soc_mem_table_idx_to_pointer(unit, ING_PRI_CNG_MAPm,
    837                                                       void *, pri_map, index);
    838             sal_memcpy(pri_cng_map + index, entries[0],
    839                        sizeof(ing_pri_cng_map_entry_t));
    840         }
    841 
    842     }
    843 
    844     /* When invoked from bcm_port_cfi_color_set, color for a particular 
    845      * cfi and port needs to be programmed for all priorities. 
    846      * To identify this special case, 
    847      * both pkt_pri and internal_pri are set to -1.
    848      */
    849     if (pkt_pri < 0 && internal_pri < 0) {
    850         for (pkt_pri = 0; pkt_pri <= 7; pkt_pri++) {
    851             index = (pkt_pri << 1) | cfi;
    852             if (SOC_IS_TRIDENT3X(unit)) {
    853                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, (uint32 *)&phb_pri_cng_map[index],
    854                         PRIf, pkt_pri);
    855                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, (uint32 *)&phb_pri_cng_map[index],
    856                         CNGf, _BCM_COLOR_ENCODING(unit, color));
    857             } else {
    858                 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index],
    859                         PRIf, pkt_pri);
    860                 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index],
    861                         CNGf, _BCM_COLOR_ENCODING(unit, color));
    862             }
    863         }
    864     } else {
    865         /* Modify what's needed */
    866         index = (pkt_pri << 1) | cfi;
    867         
    868         soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index],
    869                 PRIf, internal_pri);
    870         soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index],
    871                 CNGf, _BCM_COLOR_ENCODING(unit, color));
    872     }
    873 
    874     /* Delete the old profile chunk */
    875     if (old_ptr != 0) {
    876         index = _BCM_TR2_PRI_CNG_MAP_SIZE * old_ptr;
    877         rv = _bcm_ing_pri_cng_map_entry_delete(unit, index);
    878         if (BCM_FAILURE(rv)) {
    879             soc_cm_sfree(unit, pri_map);
    880             return (rv);
    881         }
    882     }
    883 
    884     /* Add and point to the new profile chunk */
    885     entries[0] = pri_cng_map;
    886     rv = _bcm_ing_pri_cng_map_entry_add(unit, entries,
    887                                         _BCM_TR2_PRI_CNG_MAP_SIZE, 
    888                                         (uint32 *)&new_ptr);
    889     if (BCM_FAILURE(rv)) {
    890         soc_cm_sfree(unit, pri_map);
    891         return (rv);
    892     }
    893     /*
    894      * COVERITY
    895      *
    896      * The variable new_ptr is passed by reference and will have a 
    897      * deterministic value if _bcm_ing_pri_cng_map_entry_add does
    898      * not return an error
    899      */ 
    900     /* coverity[uninit_use : FALSE] */
    901     new_ptr /= _BCM_TR2_PRI_CNG_MAP_SIZE;
    902     soc_PORT_TABm_field32_set(unit, &pent, TRUST_DOT1P_PTRf, new_ptr);
    903     rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
    904                        SOC_PORT_MOD_OFFSET(unit, port), &pent);
    905     soc_cm_sfree(unit, pri_map);
    906     return rv;
    907 }
    908 
    909 
    910 static soc_field_t _bcm_xgs3_priority_fields[] = {
    911     PRIORITY0_CNGf,
    912     PRIORITY1_CNGf,
    913     PRIORITY2_CNGf,
    914     PRIORITY3_CNGf,
    915     PRIORITY4_CNGf,
    916     PRIORITY5_CNGf,
    917     PRIORITY6_CNGf,
    918     PRIORITY7_CNGf,
    919 };
    920 
    921 /*
    922  * Function:
    923  *      _bcm_tr2_port_priority_color_set
    924  * Purpose:
    925  *      Specify the color selection for the given priority.
    926  * Parameters:
    927  *      unit -  StrataSwitch PCI device unit number (driver internal).
    928  *      port -  Port to configure
    929  *      prio -  priority (aka 802.1p CoS)
    930  *      color - color assigned to packets with indicated priority.
    931  * Returns:
    932  *      BCM_E_NONE - Success.
    933  *      BCM_E_XXX
    934  */
    935 int
    936 _bcm_tr2_port_priority_color_set(int unit, bcm_port_t port,
    937                                  int prio, bcm_color_t color)
    938 {
    939     /* In order to set color based on port and priority, both the
    940      * ING_PRI_CNG_MAP and CNG_MAP tables have to be configured.
    941      * Hardware derives color from the ING_PRI_CNG_MAP table if
    942      * incoming packet is tagged and PORT_TAB.TRUST_OUTER_DOT1P = 1.
    943      * If PORT_TAB.TRUST_OUTER_DOT1P = 0, or if packet is untagged,
    944      * harware derives color from CNG_MAP.
    945      */
    946 
    947     ing_pri_cng_map_entry_t pri_cng_map[_BCM_TR2_PRI_CNG_MAP_SIZE];
    948     cng_map_entry_t cng_map_entry;
    949     void *entries[1];
    950     port_tab_entry_t pent;
    951     int index;
    952     int rv = BCM_E_NONE;
    953     int new_ptr = 0;
    954     int old_ptr;
    955     char *pri_map;
    956     int alloc_size;
    957     uint32 val;
    958 
    959     /* Allocate buffer for dma read. */
    960     alloc_size = _BCM_TR2_PRI_CNG_MAP_SIZE * sizeof (ing_pri_cng_map_entry_t);
    961     pri_map = soc_cm_salloc(unit, alloc_size, "TR2 pri cng map");
    962     if (NULL == pri_map) {
    963         return (BCM_E_MEMORY);
    964     }
    965     sal_memset(pri_map, 0, alloc_size);
    966     sal_memset(pri_cng_map, 0, alloc_size);
    967 
    968     /* Lock the port table */
    969     soc_mem_lock(unit, PORT_TABm); 
    970 
    971     /* Get man id from port table. */
    972     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
    973                       SOC_PORT_MOD_OFFSET(unit, port), &pent);
    974     if (BCM_FAILURE(rv)) {
    975         goto _cleanup_bcm_tr2_port_priority_color_set;
    976     }
    977     old_ptr = soc_PORT_TABm_field32_get(unit, &pent, TRUST_DOT1P_PTRf);
    978 
    979     /* Get the existing profile chunk, even if old_ptr == 0, in order 
    980      * to retain the PRI field of ING_PRI_CNG_MAP.
    981      */
    982     index = old_ptr * _BCM_TR2_PRI_CNG_MAP_SIZE;
    983     rv = soc_mem_read_range(unit, ING_PRI_CNG_MAPm, MEM_BLOCK_ANY, 
    984                             index, index + _BCM_TR2_PRI_CNG_MAP_SIZE - 1,
    985                             pri_map);
    986     if (BCM_FAILURE(rv)) {
    987         goto _cleanup_bcm_tr2_port_priority_color_set;
    988     }
    989 
    990     for (index = 0; index < _BCM_TR2_PRI_CNG_MAP_SIZE; index++) {
    991         entries[0] = soc_mem_table_idx_to_pointer(unit, ING_PRI_CNG_MAPm,
    992                                                    void *, pri_map, index);
    993         sal_memcpy(pri_cng_map + index, entries[0],
    994                    sizeof(ing_pri_cng_map_entry_t));
    995     }
    996 
    997     /* Set the CNG fields in 2 consecutive entries, whose indices are given by 
    998      * (priority << 1) | cfi, where cfi = 0 or 1.
    999      */
   1000     index = prio << 1;
   1001     soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index],
   1002                         CNGf, _BCM_COLOR_ENCODING(unit, color));
   1003     soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, (uint32 *)&pri_cng_map[index+1],
   1004                         CNGf, _BCM_COLOR_ENCODING(unit, color));
   1005 
   1006     /* Add and point to the new profile chunk */
   1007     entries[0] = pri_cng_map;
   1008     rv = _bcm_ing_pri_cng_map_entry_add(unit, entries,
   1009                                                    _BCM_TR2_PRI_CNG_MAP_SIZE, 
   1010                                                    (uint32 *)&new_ptr);
   1011     if (BCM_FAILURE(rv)) {
   1012         goto _cleanup_bcm_tr2_port_priority_color_set;
   1013     }
   1014 
   1015     new_ptr /= _BCM_TR2_PRI_CNG_MAP_SIZE;
   1016     soc_PORT_TABm_field32_set(unit, &pent, TRUST_DOT1P_PTRf, new_ptr);
   1017     rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
   1018                        SOC_PORT_MOD_OFFSET(unit, port), &pent);
   1019     if (BCM_FAILURE(rv)) {
   1020         goto _cleanup_bcm_tr2_port_priority_color_set;
   1021     }
   1022 
   1023     soc_cm_sfree(unit, pri_map);
   1024     /* Release port table lock */
   1025     soc_mem_unlock(unit, PORT_TABm);
   1026 
   1027     if (old_ptr != 0) {
   1028         /* Delete the old profile chunk */
   1029         index = _BCM_TR2_PRI_CNG_MAP_SIZE * old_ptr;
   1030         BCM_IF_ERROR_RETURN(_bcm_ing_pri_cng_map_entry_delete(unit, index));
   1031     } 
   1032     
   1033     /* Configure CNG_MAP */
   1034     if (SOC_REG_IS_VALID(unit, CNG_MAPr)) {
   1035         SOC_IF_ERROR_RETURN(READ_CNG_MAPr(unit, old_ptr, &val));
   1036         soc_reg_field_set(unit, CNG_MAPr, &val,
   1037                           _bcm_xgs3_priority_fields[prio],
   1038                           _BCM_COLOR_ENCODING(unit, color));
   1039         SOC_IF_ERROR_RETURN(WRITE_CNG_MAPr(unit, new_ptr, val));
   1040         if (old_ptr != new_ptr) {
   1041             /* Clear Old CNG_MAP profile */
   1042             SOC_IF_ERROR_RETURN(WRITE_CNG_MAPr(unit, old_ptr, 0));
   1043         }
   1044     } else if (SOC_MEM_IS_VALID(unit, CNG_MAPm)) {
   1045         SOC_IF_ERROR_RETURN(READ_CNG_MAPm(unit, MEM_BLOCK_ANY,
   1046                                          old_ptr, &cng_map_entry));
   1047         soc_CNG_MAPm_field32_set(unit, &cng_map_entry,
   1048                                  _bcm_xgs3_priority_fields[prio],
   1049                                  _BCM_COLOR_ENCODING(unit, color));
   1050         SOC_IF_ERROR_RETURN(WRITE_CNG_MAPm(unit, MEM_BLOCK_ALL,
   1051                                           new_ptr, &cng_map_entry));
   1052         if (old_ptr != new_ptr) {
   1053             /* Clear Old CNG_MAP profile */
   1054             sal_memset(&cng_map_entry, 0, sizeof(cng_map_entry));
   1055             SOC_IF_ERROR_RETURN(WRITE_CNG_MAPm(unit, MEM_BLOCK_ALL,
   1056                                                old_ptr, &cng_map_entry));
   1057         }
   1058     }
   1059 
   1060     return (rv);
   1061 
   1062 _cleanup_bcm_tr2_port_priority_color_set:
   1063     /* Release port table lock */
   1064     soc_mem_unlock(unit, PORT_TABm);
   1065     soc_cm_sfree(unit, pri_map);
   1066     return (rv);
   1067 }
   1068 
   1069 #ifdef INCLUDE_L3
   1070 int
   1071 _bcm_tr2_svp_field_set(int unit, bcm_gport_t port_id, 
   1072                        soc_field_t field, int value)
   1073 {
   1074     int vp, rv = BCM_E_NONE;
   1075 
   1076     /* Get the VP index from the gport */
   1077     if (BCM_GPORT_IS_MIM_PORT(port_id)) {
   1078         vp = BCM_GPORT_MIM_PORT_ID_GET(port_id);
   1079     } else if (BCM_GPORT_IS_MPLS_PORT(port_id)) {
   1080         vp = BCM_GPORT_MPLS_PORT_ID_GET(port_id);
   1081     } else if (BCM_GPORT_IS_VXLAN_PORT(port_id)) {
   1082         vp = BCM_GPORT_VXLAN_PORT_ID_GET(port_id);
   1083     } else { 
   1084         return BCM_E_BADID;
   1085     }
   1086 
   1087     /* Be sure the entry is used and is set for MIM/MPLS */
   1088     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim) && 
   1089         !_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls) &&
   1090         !_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1091         return BCM_E_BADID;
   1092     }
   1093 
   1094     if (BCM_GPORT_IS_MIM_PORT(port_id)) {
   1095         rv = _bcm_tr2_mim_svp_field_set(unit, vp, field, value);
   1096     } else if (BCM_GPORT_IS_MPLS_PORT(port_id)) {
   1097 #if defined(BCM_MPLS_SUPPORT)
   1098         rv = _bcm_tr2_mpls_svp_field_set(unit, vp, field, value);
   1099 #endif
   1100     } else if (BCM_GPORT_IS_VXLAN_PORT(port_id)) {
   1101 #if defined(BCM_TRIDENT2_SUPPORT)
   1102         rv = _bcm_td2_vxlan_svp_field_set(unit, vp, field, value);
   1103 #endif
   1104     }
   1105     return rv;
   1106 }
   1107 
   1108 int
   1109 _bcm_tr2_svp_field_get(int unit, bcm_gport_t port_id, 
   1110                        soc_field_t field, int *value)
   1111 {
   1112     int vp, rv = BCM_E_NONE;
   1113     source_vp_entry_t svp;
   1114 
   1115     /* Get the VP index from the gport */
   1116     if (BCM_GPORT_IS_MIM_PORT(port_id)) {
   1117         vp = BCM_GPORT_MIM_PORT_ID_GET(port_id);
   1118     } else if (BCM_GPORT_IS_MPLS_PORT(port_id)) {
   1119         vp = BCM_GPORT_MPLS_PORT_ID_GET(port_id);
   1120     } else if (BCM_GPORT_IS_VXLAN_PORT(port_id)) {
   1121         vp = BCM_GPORT_VXLAN_PORT_ID_GET(port_id);
   1122     } else { 
   1123         return BCM_E_BADID;
   1124     }
   1125 
   1126     /* Be sure the entry is used and is set for MIM/MPLS */
   1127     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim) && 
   1128         !_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls) &&
   1129         !_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1130         return BCM_E_BADID;
   1131     }
   1132     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   1133 
   1134     *value = soc_SOURCE_VPm_field32_get(unit, &svp, field);
   1135     return rv;
   1136 }
   1137 
   1138 #endif /* INCLUDE_L3 */
   1139 #endif