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

cmicsim.c (149518B)


      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  * The part of PCID that simulates the cmic
      8  *
      9  * Requires:
     10  *
     11  * Provides:
     12  *     soc_internal_pcic_init
     13  *     soc_internal_read
     14  *     soc_internal_write
     15  *     soc_internal_reset
     16  *     soc_internal_vlan_tab_init
     17  *     soc_internal_memory_fetch
     18  *     soc_internal_memory_store
     19  *     soc_internal_manual_hash
     20  *     soc_internal_vlan_tab_init
     21  *     soc_internal_manual_hash
     22  *     soc_internal_send_int
     23  *     soc_internal_table_dma
     24  *     soc_internal_schan_ctrl_write
     25  */
     26 
     27 #include <shared/bsl.h>
     28 
     29 #include <unistd.h>
     30 #include <stdlib.h>
     31 
     32 #include <sys/types.h>
     33 #include <sys/time.h>
     34 #include <soc/mem.h>
     35 #include <soc/hash.h>
     36 
     37 #include <soc/cmic.h>
     38 #ifdef BCM_CMICM_SUPPORT
     39 #include <soc/cmicm.h>
     40 #endif
     41 #include <soc/drv.h>
     42 #include <soc/debug.h>
     43 #include <sal/appl/io.h>
     44 #include <bde/pli/verinet.h>
     45 
     46 #include "pcid.h"
     47 #include "mem.h"
     48 #include "cmicsim.h"
     49 #include "dma.h"
     50 #ifdef BCM_ISM_SUPPORT
     51 #include "ism.h"
     52 #endif
     53 
     54 /*
     55  * PCI Config Space Simulation
     56  */
     57 
     58 void
     59 soc_internal_pcic_init(pcid_info_t *pcid_info, uint16 pci_dev_id,
     60                        uint16 pci_ven_id, uint8 pci_rev_id, uint32 pci_mbar0)
     61 {
     62     /* PCI ID's translated at higher level */
     63 
     64     /* Device ID (16b), Vendor ID (16b) */
     65     PCIC(pcid_info, 0x00) = (pci_dev_id << 16) | pci_ven_id;
     66 
     67     /* Status (16b), Command (16b) */
     68     PCIC(pcid_info, 0x04) = 0x04800046;
     69 
     70     /* Class Code (24b), Rev ID (8b) */
     71     PCIC(pcid_info, 0x08) = 0x02800000 | pci_rev_id;
     72 
     73     /* BIST, Hdr Type, Lat Timer, Cache Line Size */
     74     PCIC(pcid_info, 0x0c) = 0x00002008;
     75 
     76     /* BAR0 */
     77     PCIC(pcid_info, 0x10) = pci_mbar0;
     78 
     79     /* BAR1 */
     80     PCIC(pcid_info, 0x14) = 0x00000000;
     81 
     82     /* BAR2 */
     83     PCIC(pcid_info, 0x18) = 0x00000000;
     84 
     85     /* BAR3 */
     86     PCIC(pcid_info, 0x1c) = 0x00000000;
     87 
     88     /* BAR4 */
     89     PCIC(pcid_info, 0x20) = 0x00000000;
     90 
     91     /* BAR5 */
     92     PCIC(pcid_info, 0x24) = 0x00000000;
     93 
     94     /* Cardbus CIS Pointer */
     95     PCIC(pcid_info, 0x28) = 0x00000000;
     96 
     97     /* Subsystem ID (16b), Subsystem Vendor ID (16b) */
     98     PCIC(pcid_info, 0x2c) = 0x00000000;
     99 
    100     /* Expansion ROM base addr */
    101     PCIC(pcid_info, 0x30) = 0x00000000;
    102 
    103     /* Reserved (24b), Capabilities Ptr (8b) */
    104     PCIC(pcid_info, 0x34) = 0x00000000;
    105 
    106     /* Reserved */
    107     PCIC(pcid_info, 0x38) = 0x00000000;
    108 
    109     /* Max_Lat, Min_Gnt, Int Pin, Int Line */
    110     PCIC(pcid_info, 0x3c) = 0x0000010b;
    111 
    112     /* Retry_Timeout, TRDY_Timeout */
    113     PCIC(pcid_info, 0x40) = 0x00008080;
    114 
    115     /* Retry_Timeout, TRDY_Timeout */
    116     PCIC(pcid_info, 0x44) = 0x00000000;
    117 }
    118 
    119 int
    120 soc_internal_write_reg(pcid_info_t *pcid_info, uint32 address, uint32 *data)
    121 {
    122     soc_regaddrinfo_t ainfo;
    123     int rv;
    124 
    125     soc_regaddrinfo_get(pcid_info->unit, &ainfo, address);
    126 
    127     if (!ainfo.valid || ainfo.reg < 0) {
    128         LOG_WARN(BSL_LS_SOC_COMMON,
    129                  (BSL_META("Attempt to write to unknown S-channel address 0x%x\n"),
    130                   address));
    131     } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
    132         SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags &
    133                SOC_REG_FLAG_RO) {
    134         LOG_WARN(BSL_LS_SOC_COMMON,
    135                  (BSL_META("Attempt to write to read-only S-channel address 0x%x\n"),
    136                   address));
    137     }
    138 
    139 #if defined(BCM_FIREBOLT_SUPPORT)
    140     /*
    141     ** Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block
    142     */
    143     if (SOC_IS_FB_FX_HX(pcid_info->unit)) {
    144         int blk;
    145         int unit = pcid_info->unit;
    146         blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20;
    147         if (((address & 0x00f80000) == blk)
    148             && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12)))    {
    149             if ((ainfo.reg == ICOS_SELr) ||
    150                 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASKr) ||
    151                 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASKr) ||
    152                 (ainfo.reg == IBCAST_BLOCK_MASKr) ||
    153                 (ainfo.reg == IEMIRROR_CONTROLr) ||
    154                 (ainfo.reg == IMIRROR_CONTROLr) ||
    155 #if defined(BCM_RAPTOR_SUPPORT) 
    156                 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASK_HIr) ||
    157                 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASK_HIr) ||
    158                 (ainfo.reg == IBCAST_BLOCK_MASK_HIr) ||
    159                 (ainfo.reg == IEMIRROR_CONTROL_HIr) ||
    160 #endif /* BCM_RAPTOR_SUPPORT */
    161                 0) {
    162                 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20;
    163                 address = (address & ~(0x00f00000)) | blk;
    164             }
    165         }
    166         blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20;
    167         if (((address & 0x00f80000) == blk)
    168             && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12)))    {
    169             blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20;
    170             address = (address & ~(0x00f00000)) | blk;
    171         }
    172     }
    173 #endif    /* BCM_FIREBOLT_SUPPORT */
    174 
    175 #if defined(BCM_RAVEN_SUPPORT)
    176     if (SOC_IS_RAVEN(pcid_info->unit)) {
    177         if (ainfo.reg == COMMAND_CONFIGr) {
    178             uint32 old_data[2];
    179             if (soc_internal_read_reg(pcid_info, address, old_data) >= 0) {
    180                 if (soc_reg_field_get(pcid_info->unit, COMMAND_CONFIGr,
    181                                  data[0], SW_RESETf) == 0) {
    182                     /*
    183                      * Warn if any field is modified without UNIMAC in reset.
    184                      */
    185                     uint32  cc_rst;
    186                     cc_rst = data[0] ^ old_data[0];
    187                     soc_reg_field_set(pcid_info->unit, COMMAND_CONFIGr,
    188                                          &cc_rst, SW_RESETf, 0);
    189                     if (cc_rst) {
    190                         LOG_WARN(BSL_LS_SOC_COMMON,
    191                                  (BSL_META("UNIMAC: Attempt to Modify COMMAND_CONFIG without MAC in reset old = 0x%08X new = 0x%08X\n"), old_data[0], data[0]));
    192                     }
    193                 }
    194             }
    195         }
    196     }
    197 #endif    /* BCM_RAVEN_SUPPORT */
    198 
    199 #ifdef BCM_TRIDENT_SUPPORT
    200     if (soc_feature(pcid_info->unit, soc_feature_logical_port_num)) {
    201         soc_info_t *si;
    202         int phy_port;
    203         int blk;
    204 
    205         si = &SOC_INFO(pcid_info->unit);
    206         switch (ainfo.reg) {
    207         case EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr:
    208             phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, data[0],
    209                                          PHYSICAL_PORT_NUMBERf);
    210             if (phy_port != 0x7f) {
    211                 si->port_p2l_mapping[phy_port] = ainfo.port;
    212                 si->port_l2p_mapping[ainfo.port] = phy_port;
    213                 blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port);
    214                 si->port_type[ainfo.port] =
    215                     SOC_BLOCK_INFO(pcid_info->unit, blk).type;
    216                 if (ainfo.port > si->port.max) {
    217                     si->port.max = ainfo.port;
    218                 }
    219             }
    220             break;
    221         case MMU_TO_PHY_PORT_MAPPINGr:
    222             phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, data[0],
    223                                          PHY_PORTf);
    224             if (phy_port != 0x7f) {
    225                 si->port_p2m_mapping[phy_port] = ainfo.idx & 0x7f;
    226                 si->port_m2p_mapping[ainfo.idx & 0x7f] = phy_port;
    227             }
    228             break;
    229         default:
    230             break;
    231         }
    232     }
    233 #endif /* BCM_TRIDENT_SUPPORT */
    234 
    235     rv = soc_datum_reg_write(pcid_info, ainfo, 0, address, data);
    236 
    237     return rv;
    238 }
    239 
    240 int
    241 soc_internal_read_reg(pcid_info_t *pcid_info, uint32 address, uint32 *data)
    242 {
    243     soc_regaddrinfo_t ainfo;
    244     int rv;
    245 
    246     soc_regaddrinfo_get(pcid_info->unit, &ainfo, address);
    247 
    248     if (!ainfo.valid || ainfo.reg < 0) {
    249         LOG_ERROR(BSL_LS_SOC_COMMON,
    250                   (BSL_META("Attempt to read from unknown S-channel address 0x%x\n"),
    251                    address));
    252     } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
    253         SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & SOC_REG_FLAG_WO) {
    254         LOG_WARN(BSL_LS_SOC_COMMON,
    255                  (BSL_META("Attempt to read from write-only S-channel address 0x%x\n"),
    256                   address));
    257     }
    258 
    259 #if defined(BCM_FIREBOLT_SUPPORT)
    260     /*
    261     ** Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block
    262     ** Well not really. Some of the registers are Higig only.
    263     */
    264     if (SOC_IS_FB_FX_HX(pcid_info->unit)) {
    265         int blk;
    266         int unit = pcid_info->unit;
    267         blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20;
    268         if (((address & 0x00f80000) == blk)
    269             && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12)))    {
    270             if ((ainfo.reg == ICOS_SELr) ||
    271                 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASKr) ||
    272                 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASKr) ||
    273                 (ainfo.reg == IBCAST_BLOCK_MASKr) ||
    274                 (ainfo.reg == IEMIRROR_CONTROLr) ||
    275                 (ainfo.reg == IMIRROR_CONTROLr) ||
    276 #if defined(BCM_RAPTOR_SUPPORT)
    277                 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASK_HIr) ||
    278                 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASK_HIr) ||
    279                 (ainfo.reg == IBCAST_BLOCK_MASK_HIr) ||
    280                 (ainfo.reg == IEMIRROR_CONTROL_HIr) ||
    281 #endif /* BCM_RAPTOR_SUPPORT */
    282                 0) {
    283                 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20;
    284                 address = (address & ~(0x00f00000)) | blk;
    285                 soc_regaddrinfo_get(pcid_info->unit, &ainfo, address);
    286             }
    287         }
    288         blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20;
    289         if (((address & 0x00f80000) == blk)
    290             && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12)))    {
    291             blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20;
    292             address = (address & ~(0x00f00000)) | blk;
    293             soc_regaddrinfo_get(pcid_info->unit, &ainfo, address);
    294         }
    295     }
    296 #endif  /* BCM_FIREBOLT_SUPPORT */
    297 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \
    298 || defined(BCM_RAPTOR_SUPPORT)
    299     /*
    300     ** Patch over array registers with different reset values
    301     */
    302     if (SOC_IS_FIREBOLT2(pcid_info->unit) || SOC_IS_TRX(pcid_info->unit) ||
    303         SOC_IS_RAVEN(pcid_info->unit) || SOC_IS_HAWKEYE(pcid_info->unit)) {
    304         if (ainfo.reg == EGR_OUTER_TPIDr) {
    305             switch (address & 0x3) {
    306             case 0:
    307                 ainfo.reg = EGR_OUTER_TPID_0r;
    308                 break;
    309             case 1:
    310                 ainfo.reg = EGR_OUTER_TPID_1r;
    311                 break;
    312             case 2:
    313                 ainfo.reg = EGR_OUTER_TPID_2r;
    314                 break;
    315             case 3:
    316                 ainfo.reg = EGR_OUTER_TPID_3r;
    317                 break;
    318             /* coverity[dead_error_begin] */
    319             default:
    320                 break;
    321             }
    322             ainfo.idx = -1;
    323         }
    324         if (ainfo.reg == ING_OUTER_TPIDr) {
    325             switch (address & 0x3) {
    326             case 0:
    327                 ainfo.reg = ING_OUTER_TPID_0r;
    328                 break;
    329             case 1:
    330                 ainfo.reg = ING_OUTER_TPID_1r;
    331                 break;
    332             case 2:
    333                 ainfo.reg = ING_OUTER_TPID_2r;
    334                 break;
    335             case 3:
    336                 ainfo.reg = ING_OUTER_TPID_3r;
    337                 break;
    338             /* coverity[dead_error_begin] */
    339             default:
    340                 break;
    341             }
    342             ainfo.idx = -1;
    343         }
    344     }
    345 #if defined(BCM_TRIUMPH_SUPPORT)
    346     if (SOC_IS_TR_VL(pcid_info->unit)) {
    347         if (ainfo.reg == ING_MPLS_TPIDr) {
    348             switch (address & 0x3) {
    349             case 0:
    350                 ainfo.reg = ING_MPLS_TPID_0r;
    351                 break;
    352             case 1:
    353                 ainfo.reg = ING_MPLS_TPID_1r;
    354                 break;
    355             case 2:
    356                 ainfo.reg = ING_MPLS_TPID_2r;
    357                 break;
    358             case 3:
    359                 ainfo.reg = ING_MPLS_TPID_3r;
    360                 break;
    361              /* coverity[dead_error_begin] */
    362             default:
    363                 break;
    364             }
    365             ainfo.idx = -1;
    366         }
    367     }
    368 #endif /* BCM_TRIUMPH_SUPPORT */
    369 #endif  /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT
    370            || BCM_RAPTOR_SUPPORT */
    371     rv = soc_datum_reg_read(pcid_info, ainfo, 0, address, data);
    372 
    373     if (SOC_E_NONE == rv) {
    374         /* Chip specific register value patches */
    375 #if defined(BCM_FIREBOLT_SUPPORT)
    376         if (SOC_IS_TRX(pcid_info->unit)) {
    377             /*
    378              * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1
    379              * returns DONE=1
    380              */
    381             if (SOC_IS_TD_TT(pcid_info->unit)) {
    382                 if (address == 0x180003) {  /* ING_HW_RESET_CONTROL_2 */
    383                     data[0] |= (1 << 18);
    384                 }
    385                 if (address == 0x280001) {  /* EGR_HW_RESET_CONTROL_1 */
    386                     data[0] |= (1 << 18);
    387                 }
    388             } else if (SOC_IS_TRIUMPH2(pcid_info->unit) ||
    389                        SOC_IS_APOLLO(pcid_info->unit)) {
    390                 if (address == 0x080003) {  /* ING_HW_RESET_CONTROL_2 */
    391                     data[0] |= (1 << 18);
    392                 }
    393                 if (address == 0x180001) {  /* EGR_HW_RESET_CONTROL_1 */
    394                     data[0] |= (1 << 18);
    395                 }
    396             } else {
    397                 if (address == 0xa80003) {  /* ING_HW_RESET_CONTROL_2 */
    398                     data[0] |= (1 << 18);
    399                 }
    400                 if (address == 0xb80001) {  /* EGR_HW_RESET_CONTROL_1 */
    401                     data[0] |= (1 << 18);
    402                 }
    403             }
    404         }
    405         else if (SOC_IS_FB_FX_HX(pcid_info->unit)) {
    406             /*
    407              * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1
    408              * returns DONE=1
    409              */
    410             if (address == 0x780002) {      /* ING_HW_RESET_CONTROL_2 */
    411                     data[0] |= (1 << 18);
    412             }
    413             if (address == 0x980001) {      /* EGR_HW_RESET_CONTROL_1 */
    414                     data[0] |= (1 << 18);
    415             }
    416         }
    417         else if (SOC_IS_HBX(pcid_info->unit)) {
    418             /*
    419              * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1
    420              * returns DONE=1
    421              */
    422             if (address == 0x180203) {      /* ING_HW_RESET_CONTROL_2_X */
    423                     data[0] |= (1 << 18);
    424             }
    425             if (address == 0x180403) {      /* ING_HW_RESET_CONTROL_2_Y */
    426                     data[0] |= (1 << 18);
    427             }
    428             if (address == 0x180603) {      /* ING_HW_RESET_CONTROL_2 */
    429                     data[0] |= (1 << 18);
    430             }
    431             if (address == 0x480601) {      /* EGR_HW_RESET_CONTROL_1 */
    432                     data[0] |= (1 << 18);
    433             }
    434         }
    435 #endif  /* BCM_FIREBOLT_SUPPORT */
    436         return 0;
    437     } else if (SOC_E_NOT_FOUND == rv) {
    438 
    439     /*
    440          * The register is not in the hash table, so it has not been written
    441          * before.  Provide a default value.
    442          */
    443         if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
    444             (ainfo.valid && ainfo.reg >= 0)) {
    445             /*This macro handle both 64 and above_64 regs*/
    446             SOC_REG_ABOVE_64_RST_VAL_GET(pcid_info->unit, ainfo.reg, data);
    447         } else {
    448             data[0] = 0xffffffff;
    449             data[1] = 0xffffffff;
    450         }
    451 
    452         rv = SOC_E_NONE;
    453 
    454 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT)
    455         if (SOC_IS_FX_HX(pcid_info->unit)) {
    456             if (address == 0xb80210) {  /* BSAFE_GLB_DEV_STATUS */
    457                 data[0] |= (1 << 7);    /* PROD_CFG_VLD */
    458             }
    459             if (address == 0xb8020c) {  /* BSAFE_GLB_PROD_CFG */
    460                 data[0] |= (pcid_info->opt_gbp_wid << 8); /* LMD_ENABLE */
    461             }
    462         }
    463 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT */
    464 #ifdef  BCM_HERCULES_SUPPORT
    465         if (SOC_IS_HERCULES15(pcid_info->unit) &&
    466             (address & 0xff0fffff) == 0x00000202) {
    467             /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */
    468             data[0] |= 0x00000008;
    469         }
    470 #endif  /* BCM_HERCULES_SUPPORT */
    471 
    472 #if defined(BCM_FIREBOLT_SUPPORT)
    473         if (SOC_IS_FB(pcid_info->unit) ||
    474             SOC_IS_HELIX(pcid_info->unit) ||
    475             SOC_IS_FELIX(pcid_info->unit)) {
    476             if (address == 0x00200002 ||        /* MAC_XGXS_STAT.XE0 */
    477                 address == 0x00300002 ||        /* MAC_XGXS_STAT.XE1 */
    478                 address == 0x00400002 ||        /* MAC_XGXS_STAT.XE2 */
    479                 address == 0x00500002) {        /* MAX_XGXS_STAT_XE3 */
    480                 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */
    481                 data[0] |= 0x00000008;
    482             }
    483         }
    484 #endif  /* BCM_FIREBOLT_SUPPORT */
    485 #if defined(BCM_BRADLEY_SUPPORT)
    486         if (SOC_IS_HBX(pcid_info->unit)) {
    487             if ((address & 0xfff00fff) == 0x000002) { /* MAX_XGXS_STAT */
    488                 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */
    489                 data[0] |= 0x00000020;
    490             }
    491         }
    492 #endif  /* BCM_BRADLEY_SUPPORT */
    493 #if defined(BCM_TRIUMPH_SUPPORT)
    494         if (SOC_IS_TR_VL(pcid_info->unit)) {
    495             if (address == 0x00200002 || /* MAC_XGXS_STAT.XE0 */
    496                 address == 0x00300002 || /* MAC_XGXS_STAT.XE1 */
    497                 address == 0x00400002 || /* MAC_XGXS_STAT.XE2 */
    498                 address == 0x00500002 || /* MAC_XGXS_STAT.XE3 */
    499                 address == 0x00600002 || /* MAC_XGXS_STAT.XE4 */
    500                 address == 0x00700002 || /* MAC_XGXS_STAT.XE5 */
    501                 address == 0x00800002 || /* MAC_XGXS_STAT.XE6 */
    502                 address == 0x00900002) { /* MAX_XGXS_STAT.XE7 */
    503                 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */
    504                 data[0] |= 0x00000020;
    505             }
    506         }
    507 #endif  /* BCM_TRIUMPH_SUPPORT */
    508 #if defined(BCM_TRIUMPH2_SUPPORT)
    509         if (SOC_IS_TRIUMPH2(pcid_info->unit) || SOC_IS_APOLLO(pcid_info->unit) ||
    510             SOC_IS_VALKYRIE2(pcid_info->unit)) {
    511             if (address == 0x800002 || /* MAC_XGXS_STAT.XP0 */
    512                 address == 0x900002 || /* MAC_XGXS_STAT.XP1 */
    513                 address == 0xa00002 || /* MAC_XGXS_STAT.XP2 */
    514                 address == 0xb00002 || /* MAC_XGXS_STAT.XP3 */
    515                 address == 0x40000002 || /* MAC_XGXS_STAT.XQ0 */
    516                 address == 0x40100002 || /* MAC_XGXS_STAT.XQ1 */
    517                 address == 0x40200002 || /* MAC_XGXS_STAT.XQ2 */
    518                 address == 0x40300002 || /* MAC_XGXS_STAT.XQ3 */
    519                 address == 0x40400002 || /* MAC_XGXS_STAT.XQ4 */
    520                 address == 0x40500002) { /* MAX_XGXS_STAT.XQ5 */
    521                 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */
    522                 data[0] |= 0x00000020;
    523             }
    524         }
    525 #endif  /* BCM_TRIUMPH2_SUPPORT */
    526     } else {
    527         LOG_ERROR(BSL_LS_SOC_COMMON,
    528                   (BSL_META("RPC error: soc_internalreg_read failed %d. \n"), rv));
    529     }
    530 
    531     return rv;
    532 }
    533 
    534 int
    535 soc_internal_write_bytes(pcid_info_t *pcid_info, uint32 address, uint8 *data, 
    536                          int len)
    537 {
    538     uint32  temp[SOC_MAX_MEM_WORDS];
    539 
    540     if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) {
    541         return 1;
    542     }
    543 
    544     /* writing bytes is supported only for bcmsim */
    545     if ((pcid_info->regmem_cb) && 
    546         (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, 
    547                               (uint32 *)data, (len * 8)) == 0)) {
    548         return 0;
    549     }
    550 
    551     /* if no registered call-back, default to write_mem */
    552     sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32)));
    553     sal_memcpy(temp, data, len);
    554     return soc_internal_write_mem(pcid_info, address, temp);
    555 
    556 }
    557 
    558 int
    559 soc_internal_write_mem(pcid_info_t *pcid_info, uint32 address, uint32 *data)
    560 {
    561     soc_mem_t       mem;
    562     int rv;
    563 
    564     if ((pcid_info->regmem_cb) 
    565         && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, data, 
    566                                  ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) {
    567         return 0;
    568     }
    569 
    570     if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) {
    571 #ifdef    BCM_FIREBOLT_SUPPORT
    572         if (SOC_IS_FBX(pcid_info->unit)) {
    573             if (SOC_IS_FB_FX_HX(pcid_info->unit)) {
    574                 /*
    575                  * Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block
    576                  */
    577                 int blk;
    578                 int unit = pcid_info->unit;
    579                 int cpu_port = CMIC_PORT(unit);
    580                 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20;
    581                 if (((address & 0x00f00000) == blk)
    582                     && ((address & 0x0000001f) != cpu_port )
    583                     && (mem != IFP_PORT_FIELD_SELm))    {
    584                     blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20;
    585                     address = (address & ~(0x00f00000)) | blk;
    586                 }
    587                 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20;
    588                 if (((address & 0x00f00000) == blk)
    589                     && ((address & 0x0000001f) != cpu_port))    {
    590                     blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20;
    591                     address = (address & ~(0x00f00000)) | blk;
    592                 }
    593             }
    594 
    595             switch(mem) {
    596                 case L3_ENTRY_IPV4_UNICASTm:
    597                 case L3_ENTRY_IPV4_MULTICASTm:
    598                 case L3_ENTRY_IPV6_UNICASTm:
    599                 case L3_ENTRY_IPV6_MULTICASTm:
    600                     if(SOC_IS_HAWKEYE(pcid_info->unit)){
    601                         break;
    602                     }
    603                     return (soc_internal_l3x2_write(pcid_info, mem,
    604                                                     address, data));
    605                 default: break;
    606             }
    607         }
    608 #endif /* BCM_FIREBOLT_SUPPORT */
    609 #if defined(BCM_TRX_SUPPORT)
    610         if (SOC_IS_TRX(pcid_info->unit)) {
    611             if (mem == VLAN_MACm) {
    612                 /* In real HW, VLAN_MAC table is overlaid on VLAN_XLATE table */
    613                 return (soc_internal_vlan_xlate_entry_write(pcid_info, address,
    614                                        (vlan_xlate_entry_t *) data));
    615             }
    616         }
    617 #endif
    618 
    619         if  (soc_mem_is_aggr(pcid_info->unit, mem)) {
    620             return soc_internal_write_aggrmem(pcid_info, address, data);
    621         }
    622     }
    623 
    624     rv = soc_datum_mem_write(pcid_info, 0, address, data);
    625     return rv;
    626 }
    627 
    628 int
    629 soc_internal_read_bytes(pcid_info_t *pcid_info, uint32 address, uint8 *data,
    630                         int len)
    631 {
    632     uint32  temp[SOC_MAX_MEM_WORDS];
    633     int     rv;
    634 
    635     if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) {
    636         return 1;
    637     }
    638 
    639     /* reading bytes is supported only for bcmsim */
    640     if ((pcid_info->regmem_cb) && 
    641         (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, 
    642                               (uint32 *) data, (len * 8)) == 0)) {
    643         return 0;
    644     }
    645 
    646     /* if no registered call-back, default to read_mem */
    647     sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32)));
    648     rv = soc_internal_read_mem(pcid_info, address, temp);
    649     if (!rv) {
    650         sal_memcpy(data, temp, len);
    651     }
    652     return rv;
    653 }
    654 int
    655 soc_internal_read_mem(pcid_info_t *pcid_info, uint32 address, uint32 *data)
    656 {
    657     int             i, rv;
    658     soc_mem_t       mem;
    659 
    660     if ((pcid_info->regmem_cb) 
    661         && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, data, 
    662                                  ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) {
    663         return 0;
    664     }
    665 
    666     if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) {
    667 #ifdef    BCM_FIREBOLT_SUPPORT
    668         if (SOC_IS_FBX(pcid_info->unit)) {
    669             if (SOC_IS_FB_FX_HX(pcid_info->unit)) {
    670                 /*
    671                  * Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block
    672                  */
    673                 int blk;
    674                 int unit = pcid_info->unit;
    675                 int cpu_port = CMIC_PORT(unit);
    676                 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20;
    677                 if (((address & 0x00f00000) == blk)
    678                     && ((address & 0x0000001f) != cpu_port )
    679                     && (mem != IFP_PORT_FIELD_SELm))    {
    680                     blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20;
    681                     address = (address & ~(0x00f00000)) | blk;
    682                 }
    683                 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20;
    684                 if (((address & 0x00f00000) == blk)
    685                     && ((address & 0x0000001f) != cpu_port))    {
    686                     blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20;
    687                     address = (address & ~(0x00f00000)) | blk;
    688                 }
    689             }
    690 
    691             switch(mem) {
    692                 case L3_ENTRY_IPV4_UNICASTm:
    693                 case L3_ENTRY_IPV4_MULTICASTm:
    694                 case L3_ENTRY_IPV6_UNICASTm:
    695                 case L3_ENTRY_IPV6_MULTICASTm:
    696                     if(SOC_IS_HAWKEYE(pcid_info->unit)){
    697                         break;
    698                     }
    699                     return (soc_internal_l3x2_read(pcid_info, mem,
    700                                                    address, data));
    701                 default: break;
    702             }
    703         }
    704 #endif /* BCM_FIREBOLT_SUPPORT */
    705 #if defined(BCM_TRX_SUPPORT)
    706         if (SOC_IS_TRX(pcid_info->unit)) {
    707             if (mem == VLAN_MACm) {
    708                 /* In real HW, VLAN_MAC table is overlaid on VLAN_XLATE table */
    709                 return (soc_internal_vlan_xlate_entry_read(pcid_info, address,
    710                                        (vlan_xlate_entry_t *) data));
    711             }
    712         }
    713 #endif
    714         if  (soc_mem_is_aggr(pcid_info->unit, mem)) {
    715             return soc_internal_read_aggrmem(pcid_info, address, data);
    716         }
    717     }
    718 
    719     rv = soc_datum_mem_read(pcid_info, 0, address, data);
    720 
    721     if (SOC_E_NOT_FOUND == rv) {
    722         /* Return null entry value if recognize, otherwise 0xf's */
    723         if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) {
    724             if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) {
    725                 memcpy(data,               /* Memory */
    726                        soc_mem_entry_null(pcid_info->unit, mem),
    727                        4 * soc_mem_entry_words(pcid_info->unit, mem));
    728             } else {
    729                 memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem));
    730             }
    731         } else {                   /* Other */
    732             for (i = 0; i < SOC_MAX_MEM_WORDS; i++) {
    733                 data[i] = 0xffffffff;
    734             }
    735         }
    736     }
    737 
    738     return SOC_E_NONE;
    739 }
    740 
    741 /*
    742  * Re-sort fields of aggregate mems based on bit position
    743  */
    744 void
    745 _soc_internal_fields_sort(soc_field_info_t *src, uint32 count, soc_field_info_t *dst)
    746 {
    747     uint32 i, j;
    748     soc_field_info_t tmp;
    749     
    750     sal_memcpy(dst, src, count * sizeof(soc_field_info_t));
    751     for (i = 0; i < count; i++) {
    752         for (j = 0; j < count - i - 1; j++) {
    753             if (dst[j].bp < dst[j+1].bp) {
    754                 sal_memcpy(&tmp, &dst[j], 
    755                            sizeof(soc_field_info_t));
    756                 sal_memcpy(&dst[j], &dst[j+1],
    757                            sizeof(soc_field_info_t));
    758                 sal_memcpy(&dst[j+1], &tmp,
    759                            sizeof(soc_field_info_t));
    760             }
    761         }
    762     }    
    763 }
    764 
    765 /*
    766 ** This is a generic function to handle aggregate memories. Memories
    767 ** made up of unequal depth and field mismatch between unified view
    768 ** and individual component memories require special handling.
    769 ** For example L2 table has HIT bits which are packet into 1/8 size table
    770 */
    771 int
    772 soc_internal_read_aggrmem(pcid_info_t *pcid_info, uint32 addr, uint32 *data)
    773 {
    774     int         unit = pcid_info->unit;
    775     uint32      ent[SOC_MAX_MEM_WORDS];
    776     uint32      fv[SOC_MAX_MEM_WORDS];
    777     soc_mem_t   *m = NULL;
    778     int         index, i;
    779     int         offset;
    780     int         adj_offset = 0;
    781     int         f;
    782     int         nfield;
    783     int         pck_factor;
    784     soc_mem_t   mem;
    785     soc_mem_info_t *amemp;
    786     soc_mem_info_t *memp;
    787     soc_field_info_t *fieldp;
    788     soc_field_info_t *asflds; /* array for aggregate mem sorted fields */
    789     soc_field_info_t *sflds; /* array for partial mem sorted fields */
    790 
    791     mem = soc_addr_to_mem(pcid_info->unit, addr, NULL);
    792 
    793     if (mem == INVALIDm)
    794     {
    795         return SOC_E_PARAM;
    796     }
    797 
    798     offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0xfffff;
    799     index = 0;
    800     memset(data, 0, 4 * soc_mem_entry_words(unit, mem));
    801     do {
    802         m = SOC_MEM_AGGR(unit, index);
    803         if (m[0] == mem) {
    804             /* Fetch the individual components */
    805             nfield = 1;
    806             for(i = 1; m[i] != INVALIDm; i++) {
    807                 /*
    808                 ** Multiple entries compacted into one entry like HIT
    809                 ** requires special handling.
    810                 */
    811                 amemp = &SOC_MEM_INFO(unit, mem);
    812                 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) {
    813                     continue;
    814                 }
    815                 pck_factor = (soc_mem_index_max(unit, mem) /
    816                               soc_mem_index_max(unit, m[i]));
    817                 assert(pck_factor != 0);
    818                 adj_offset = offset / pck_factor;
    819                 soc_internal_read_mem(pcid_info,
    820                         soc_mem_addr(unit, m[i], 0,
    821                                 SOC_MEM_BLOCK_ANY(unit, m[i]),
    822                                 adj_offset), ent);
    823 
    824                 /* Iterate thru' the fields in this View */
    825                 memp = &SOC_MEM_INFO(unit, m[i]);
    826                 if (pck_factor == 1) {
    827                     for (f = memp->nFields - 1; f >= 0; f--) {
    828                         fieldp = &memp->fields[f];
    829                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
    830                         if (soc_mem_field_valid(unit, mem, fieldp->field) &&
    831                             soc_mem_field_valid(unit, m[i], fieldp->field)) {
    832                             soc_mem_field_set(unit, mem, data, fieldp->field,
    833                                               fv);
    834                         }
    835                         nfield++;
    836                     }
    837                 } else if (memp->nFields == pck_factor) {
    838                         asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 
    839                                            "aggregate fields");
    840                         if (!asflds) {
    841                             return SOC_E_INTERNAL;
    842                         }
    843                         sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 
    844                                            "mem fields");
    845                         if (!sflds) {
    846                             sal_free(asflds);
    847                             return SOC_E_INTERNAL;
    848                         }
    849                         _soc_internal_fields_sort(amemp->fields, amemp->nFields,
    850                                                   asflds);
    851                         _soc_internal_fields_sort(memp->fields, memp->nFields,
    852                                                   sflds);
    853                         fieldp = &sflds[memp->nFields -
    854                                     (offset % pck_factor) - 1];
    855                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
    856                         fieldp = &asflds[(amemp->nFields - nfield)];
    857                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
    858                         nfield++;
    859                         sal_free(asflds); sal_free(sflds);
    860                 } else if (memp->nFields == (pck_factor * 2)) {
    861                         asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 
    862                                            "aggregate fields");
    863                         if (!asflds) {
    864                             return SOC_E_INTERNAL;
    865                         }
    866                         sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 
    867                                            "mem fields");
    868                         if (!sflds) {
    869                             sal_free(asflds);
    870                             return SOC_E_INTERNAL;
    871                         }
    872                         _soc_internal_fields_sort(amemp->fields, amemp->nFields,
    873                                                   asflds);
    874                         _soc_internal_fields_sort(memp->fields, memp->nFields,
    875                                                   sflds);
    876                         fieldp = &sflds[memp->nFields -
    877                                     (offset % pck_factor) - 1];
    878                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
    879                         fieldp = &asflds[(amemp->nFields - nfield)];
    880                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
    881                         nfield++;
    882 
    883                         fieldp = &sflds[memp->nFields - pck_factor - 
    884                                     (offset % pck_factor) - 1];
    885                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
    886                         fieldp = &asflds[(amemp->nFields - nfield)];
    887                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
    888                         nfield++;
    889                         sal_free(asflds); sal_free(sflds);
    890                 } else {
    891                     LOG_ERROR(BSL_LS_SOC_COMMON,
    892                               (BSL_META_U(unit,
    893                                           "soc_internal_read_aggrmem:mem=%d"
    894                                           "Unable to handle Aggregate Mem component %d\n"),
    895                                mem, m[i]));
    896                 }
    897             }
    898             return(0);
    899         }
    900         index++;
    901     } while (m[0] != INVALIDm);
    902 
    903     /* Not found in the table of aggregate memories */
    904     LOG_ERROR(BSL_LS_SOC_COMMON,
    905               (BSL_META_U(unit,
    906                           "soc_internal_read_aggrmem:mem=%d missing in Aggregate Mem List\n"),
    907                mem));
    908     if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) {
    909         memcpy(data,               /* Memory */
    910                soc_mem_entry_null(pcid_info->unit, mem),
    911                4 * soc_mem_entry_words(pcid_info->unit, mem));
    912     } else {
    913         memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem));
    914     }           
    915     return(0);
    916 }
    917 
    918 int
    919 soc_internal_write_aggrmem(pcid_info_t *pcid_info, uint32 addr, uint32 *data)
    920 {
    921     int         unit = pcid_info->unit;
    922     uint32      ent[SOC_MAX_MEM_WORDS];
    923     uint32      fv[SOC_MAX_MEM_WORDS];
    924     soc_mem_t   *m = NULL;
    925     int         index, i;
    926     int         offset;
    927     int         adj_offset = 0;
    928     int         f;
    929     int         nfield;
    930     int         pck_factor;
    931     soc_mem_t   mem;
    932     soc_mem_info_t *amemp;
    933     soc_mem_info_t *memp;
    934     soc_field_info_t *fieldp;
    935     soc_field_info_t *asflds; /* array for aggregate mem sorted fields */
    936     soc_field_info_t *sflds; /* array for partial mem sorted fields */
    937 
    938     mem = soc_addr_to_mem(pcid_info->unit, addr, NULL);
    939 
    940     if (mem == INVALIDm)
    941     {
    942         return SOC_E_PARAM;
    943     }
    944 
    945     memset(ent, 0, 4 * soc_mem_entry_words(unit, mem));
    946     offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0xfffff;
    947     index = 0;
    948     do {
    949         m = SOC_MEM_AGGR(unit, index);
    950         if (m[0] == mem) {
    951             /* Fetch the individual components */
    952             nfield = 1;
    953             for(i = 1; m[i] != INVALIDm; i++) {
    954                 /*
    955                 ** Multiple entries compacted into one entry like HIT
    956                 ** requires special handling.
    957                 */
    958                 amemp = &SOC_MEM_INFO(unit, mem);
    959                 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) {
    960                     continue;
    961                 }
    962                 pck_factor = (soc_mem_index_max(unit, mem) /
    963                               soc_mem_index_max(unit, m[i]));
    964                 assert(pck_factor != 0);
    965                 adj_offset = offset / pck_factor;
    966                 memp = &SOC_MEM_INFO(unit, m[i]);
    967                 
    968                 /* Iterate thru' the fields in this View */
    969                 if (pck_factor == 1) {
    970                     for (f = memp->nFields - 1; f >= 0; f--) {
    971                         fieldp = &memp->fields[f];
    972                         if (soc_mem_field_valid(unit, mem, fieldp->field) &&
    973                             soc_mem_field_valid(unit, m[i], fieldp->field)) {
    974                             soc_mem_field_get(unit, mem, data, fieldp->field,
    975                                               fv);
    976                             soc_mem_field_set(unit, m[i], ent, fieldp->field,
    977                                               fv);
    978                         }
    979                         nfield++;
    980                     }
    981                 } else if (memp->nFields == pck_factor) {
    982                         asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 
    983                                            "aggregate fields");
    984                         if (!asflds) {
    985                             return SOC_E_INTERNAL;
    986                         }
    987                         sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 
    988                                            "mem fields");
    989                         if (!sflds) {
    990                             sal_free(asflds);
    991                             return SOC_E_INTERNAL;
    992                         }
    993                         _soc_internal_fields_sort(amemp->fields, amemp->nFields,
    994                                                   asflds);
    995                         _soc_internal_fields_sort(memp->fields, memp->nFields,
    996                                                   sflds);
    997                         fieldp = &asflds[(amemp->nFields - nfield)];
    998                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
    999                         fieldp = &sflds[memp->nFields -
   1000                                     (offset % pck_factor) - 1];
   1001                         soc_internal_read_mem(pcid_info,
   1002                                 soc_mem_addr(unit, m[i], 0,
   1003                                         SOC_MEM_BLOCK_ANY(unit, m[i]),
   1004                                         adj_offset), ent);
   1005                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   1006                         nfield++;
   1007                         sal_free(asflds); sal_free(sflds);
   1008                 } else if (memp->nFields == (pck_factor * 2)) {
   1009                         asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 
   1010                                            "aggregate fields");
   1011                         if (!asflds) {
   1012                             return SOC_E_INTERNAL;
   1013                         }
   1014                         sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 
   1015                                            "mem fields");
   1016                         if (!sflds) {
   1017                             sal_free(asflds);
   1018                             return SOC_E_INTERNAL;
   1019                         }
   1020                         _soc_internal_fields_sort(amemp->fields, amemp->nFields,
   1021                                                   asflds);
   1022                         _soc_internal_fields_sort(memp->fields, memp->nFields,
   1023                                                   sflds);
   1024                         fieldp = &asflds[(amemp->nFields - nfield)];
   1025                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
   1026                         fieldp = &sflds[memp->nFields -
   1027                                     (offset % pck_factor) - 1];
   1028                         soc_internal_read_mem(pcid_info,
   1029                                 soc_mem_addr(unit, m[i], 0,
   1030                                         SOC_MEM_BLOCK_ANY(unit, m[i]),
   1031                                         adj_offset), ent);
   1032                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   1033                         nfield++;
   1034 
   1035                         fieldp = &asflds[(amemp->nFields - nfield)];
   1036                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
   1037                         fieldp = &sflds[memp->nFields - pck_factor -
   1038                                     (offset % pck_factor) - 1];
   1039                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   1040                         nfield++;
   1041                         sal_free(asflds); sal_free(sflds);
   1042                 } else {
   1043                     LOG_ERROR(BSL_LS_SOC_COMMON,
   1044                               (BSL_META_U(unit,
   1045                                           "soc_internal_write_aggrmem:mem=%d"
   1046                                           "Unable to handle Aggregate Mem component %d\n"),
   1047                                mem, m[i]));
   1048                 }
   1049                 soc_internal_write_mem(pcid_info,
   1050                                 soc_mem_addr(unit, m[i], 0,
   1051                                     SOC_MEM_BLOCK_ANY(unit, m[i]),
   1052                                     adj_offset), ent);
   1053             }
   1054             return(0);
   1055         }
   1056         index++;
   1057     } while (m[0] != INVALIDm);
   1058 
   1059     /* Not found in the table of aggregate memories */
   1060     LOG_ERROR(BSL_LS_SOC_COMMON,
   1061               (BSL_META_U(unit,
   1062                           "soc_internal_write_aggrmem:mem=%d missing in Aggregate Mem List\n"),
   1063                mem));
   1064     return(0);
   1065 }
   1066 
   1067 #ifdef    BCM_FIREBOLT_SUPPORT
   1068 void
   1069 _soc_l2x2_nak_check(int unit, schan_msg_t    *msg)
   1070 {
   1071     int             op_fail_pos;
   1072 
   1073     /*
   1074      * ==================================================
   1075      * | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
   1076      * ==================================================
   1077      */
   1078     op_fail_pos = (_shr_popcount(soc_mem_index_max(unit, L2Xm)) +
   1079                    soc_mem_entry_bits(unit, L2Xm)) % 32;
   1080 
   1081     if (msg->readresp.data[3] & (0x3 << op_fail_pos)) {
   1082         msg->readresp.header.v2.nack = 1;
   1083     }
   1084 }
   1085 #endif    /* BCM_FIREBOLT_SUPPORT */
   1086 
   1087 #ifdef BCM_TRX_SUPPORT
   1088 static int ing_ipfix_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 };
   1089 static int egr_ipfix_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 };
   1090 static int ext_l2mod_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 };
   1091 static int l2mod_fifo_count[SOC_MAX_NUM_DEVICES]     = { 0 };
   1092 
   1093 /*
   1094  * soc_internal_ing_ipfix_fifo_pop
   1095  */
   1096 static int
   1097 soc_internal_fifo_pop(pcid_info_t * pcid_info, soc_mem_t mem, uint32 *result)
   1098 {
   1099     int      *count, i;
   1100     uint32   tmp[SOC_MAX_MEM_WORDS];
   1101     int      unit = pcid_info->unit;
   1102 
   1103     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1104                 (BSL_META_U(unit,
   1105                             "Ingress IPFIX fifo pop\n")));
   1106 
   1107     *result = 0;
   1108     switch (mem) {
   1109         case ING_IPFIX_EXPORT_FIFOm:
   1110             count = &ing_ipfix_fifo_count[unit];
   1111             break;
   1112         case EGR_IPFIX_EXPORT_FIFOm:
   1113             count = &egr_ipfix_fifo_count[unit];
   1114             break;
   1115         case EXT_L2_MOD_FIFOm:
   1116             count = &ext_l2mod_fifo_count[unit];
   1117             break;
   1118         case L2_MOD_FIFOm:
   1119             count = &l2mod_fifo_count[unit];
   1120             break;
   1121         default:
   1122             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1123                         (BSL_META_U(unit,
   1124                                     "Pop not supported on this memory\n")));
   1125 /*             PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; */
   1126             pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST);
   1127             return 0;
   1128     }
   1129 
   1130     if (*count > 0) {
   1131         soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1132                                          SOC_MEM_BLOCK_ANY(unit, mem),
   1133                                          0), result);
   1134 
   1135         /* Shift up the remaining entries */
   1136         for (i = 0; i < *count; i++) {
   1137             soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1138                                              SOC_MEM_BLOCK_ANY(unit, mem),
   1139                                              i + 1), tmp);
   1140             soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1141                                               SOC_MEM_BLOCK_ANY(unit, mem),
   1142                                               i), tmp);
   1143         }
   1144         *count -= 1;
   1145         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1146                     (BSL_META_U(unit,
   1147                                 "Fifo entry popped.\n")));
   1148     } else {
   1149         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1150                     (BSL_META_U(unit,
   1151                                 "Fifo Empty\n")));
   1152         return 1;
   1153     }
   1154     return 0;
   1155 }
   1156 
   1157 /*
   1158  * soc_internal_ing_ipfix_fifo_push
   1159  */
   1160 static int
   1161 soc_internal_fifo_push(pcid_info_t * pcid_info, soc_mem_t mem, uint32 *entry)
   1162 {
   1163     int       *count, i;
   1164     uint32    tmp[SOC_MAX_MEM_WORDS];
   1165     int       unit = pcid_info->unit;
   1166 
   1167     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1168                 (BSL_META_U(unit,
   1169                             "Ingress IPFIX fifo push\n")));
   1170 
   1171     switch (mem) {
   1172         case ING_IPFIX_EXPORT_FIFOm:
   1173             count = &ing_ipfix_fifo_count[unit];
   1174             break;
   1175         case EGR_IPFIX_EXPORT_FIFOm:
   1176             count = &egr_ipfix_fifo_count[unit];
   1177             break;
   1178         case EXT_L2_MOD_FIFOm:
   1179             count = &ext_l2mod_fifo_count[unit];
   1180             break;
   1181         case L2_MOD_FIFOm:
   1182             count = &l2mod_fifo_count[unit];
   1183             break;
   1184         default:
   1185             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1186                         (BSL_META_U(unit,
   1187                                     "Pop not supported on this memory\n")));
   1188 /*            PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; */
   1189             pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST);
   1190             return 0;
   1191     }
   1192 
   1193     if (*count == soc_mem_index_count(unit, mem)) {
   1194         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1195                     (BSL_META_U(unit,
   1196                                 "Fifo Full\n")));
   1197         return 1;
   1198     } else {
   1199         /* Shift down the existing entries */
   1200         for (i = *count; i > 0; i--) {
   1201             soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1202                                              SOC_MEM_BLOCK_ANY(unit, mem),
   1203                                              i - 1), tmp);
   1204             soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1205                                               SOC_MEM_BLOCK_ANY(unit, mem),
   1206                                               i), tmp);
   1207         }
   1208         soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0,
   1209                                           SOC_MEM_BLOCK_ANY(unit, mem),
   1210                                           0), entry);
   1211         *count += 1;
   1212         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1213                     (BSL_META_U(unit,
   1214                                 "Fifo entry pushed.\n")));
   1215     }
   1216     return 0;
   1217 }
   1218 
   1219 #endif /* BCM_TRX_SUPPORT */
   1220 
   1221 /*
   1222  * schan_op
   1223  *
   1224  * Look at schan header, perform action(s), and make response.
   1225  */
   1226 
   1227 int
   1228 schan_op(pcid_info_t *pcid_info, int unit, schan_msg_t* data)
   1229 {
   1230     schan_msg_t    *msg;
   1231     int             opcode, dst_blk, src_blk, acc_type, data_byte_len, dma;
   1232     uint32          bank_ignore_mask;
   1233     int             rv = -1;
   1234 #ifdef    BCM_TRX_SUPPORT
   1235     int32           banks = 0;
   1236 #endif
   1237 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_SCORPION_SUPPORT)
   1238     soc_mem_t mem;
   1239 #endif
   1240 
   1241 #ifdef BCM_CMICM_SUPPORT
   1242     if (pcid_info->cmicm >= CMC0) {
   1243         msg = (schan_msg_t *)&PCIM(pcid_info, CMIC_CMCx_SCHAN_MESSAGEn(CMC0, 0));
   1244     } else 
   1245 #endif
   1246     {
   1247         msg = (schan_msg_t *)&PCIM(pcid_info, CMIC_SCHAN_MESSAGE(unit, 0));
   1248     }
   1249 
   1250     if(data) {
   1251         *msg = *data; 
   1252     }
   1253 
   1254     /* Clear nak bit in schan control */
   1255 #ifdef BCM_CMICM_SUPPORT
   1256     if (pcid_info->cmicm >= CMC0) {
   1257 /*         PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= ~SC_CMCx_MSG_NAK; */
   1258        pcid_reg_and_write(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET, SC_CMCx_MSG_NAK);
   1259        
   1260     } else 
   1261 #endif
   1262     {
   1263 /*        PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; */
   1264         pcid_reg_and_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST);
   1265     }
   1266 
   1267     soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode,
   1268                              &dst_blk, &src_blk, &acc_type, &data_byte_len,
   1269                              &dma, &bank_ignore_mask);
   1270     switch (opcode) {
   1271     case WRITE_REGISTER_CMD_MSG:
   1272        if (pcid_info->opt_pli_verbose)
   1273           LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1274                       (BSL_META_U(unit,
   1275                                   "S-Channel operation: WRITE_REGISTER_CMD 0x%x\n"),
   1276                        msg->writecmd.address));
   1277         opcode = WRITE_REGISTER_ACK_MSG;
   1278         rv = soc_internal_extended_write_reg(pcid_info, dst_blk, acc_type,
   1279                                              msg->writecmd.address,
   1280                                              msg->writecmd.data); 
   1281         break;
   1282     case READ_REGISTER_CMD_MSG:
   1283        if (pcid_info->opt_pli_verbose)
   1284           LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1285                       (BSL_META_U(unit,
   1286                                   "S-Channel operation: READ_REGISTER_CMD 0x%x\n"),
   1287                        msg->readcmd.address));
   1288         opcode = READ_REGISTER_ACK_MSG;
   1289         rv = soc_internal_extended_read_reg(pcid_info, dst_blk, acc_type,
   1290                                             msg->readcmd.address,
   1291                                             msg->readresp.data);
   1292         break;
   1293     case WRITE_MEMORY_CMD_MSG:
   1294        if (pcid_info->opt_pli_verbose)
   1295           LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1296                       (BSL_META_U(unit,
   1297                                   "S-Channel operation: WRITE_MEMORY_CMD 0x%x\n"),
   1298                        msg->writecmd.address));
   1299         opcode = WRITE_MEMORY_ACK_MSG;
   1300         rv = soc_internal_extended_write_mem(pcid_info, dst_blk, acc_type,
   1301                                              msg->writecmd.address,
   1302                                              msg->writecmd.data); 
   1303         break;
   1304     case READ_MEMORY_CMD_MSG:
   1305        if (pcid_info->opt_pli_verbose)
   1306           LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1307                       (BSL_META_U(unit,
   1308                                   "S-Channel operation: READ_MEMORY_CMD 0x%x\n"),
   1309                        msg->readcmd.address));
   1310         opcode = READ_MEMORY_ACK_MSG;
   1311         rv = soc_internal_extended_read_mem(pcid_info, dst_blk, acc_type,
   1312                                             msg->readcmd.address,
   1313                                             msg->readresp.data);
   1314         break;
   1315     case ARL_INSERT_CMD_MSG:
   1316         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1317                     (BSL_META_U(unit,
   1318                                 "S-Channel operation: ARL_INSERT_CMD_MSG\n")));
   1319 #ifdef    BCM_FIREBOLT_SUPPORT
   1320         if (SOC_IS_FBX(pcid_info->unit)) {
   1321             opcode = ARL_INSERT_DONE_MSG;
   1322             rv = soc_internal_l2x2_entry_ins(pcid_info, bank_ignore_mask,
   1323                                              (l2x_entry_t *)msg->l2x2.data,
   1324                                              msg->readresp.data);
   1325             _soc_l2x2_nak_check(pcid_info->unit, msg);
   1326             break;
   1327         }
   1328 #endif    /* BCM_FIREBOLT_SUPPORT */
   1329         if (SOC_IS_XGS_FABRIC(pcid_info->unit)) {
   1330             LOG_WARN(BSL_LS_SOC_COMMON,
   1331                      (BSL_META_U(unit,
   1332                                  "Bad call for Hercules: ARL_INSERT_CMD_MSG\n")));
   1333             break;
   1334         }
   1335         break;
   1336     case ARL_DELETE_CMD_MSG:
   1337         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1338                     (BSL_META_U(unit,
   1339                                 "S-Channel operation: ARL_DELETE_CMD_MSG\n")));
   1340 #ifdef    BCM_FIREBOLT_SUPPORT
   1341         if (SOC_IS_FBX(pcid_info->unit)) {
   1342             opcode = ARL_DELETE_DONE_MSG;
   1343             rv = soc_internal_l2x2_entry_del(pcid_info, bank_ignore_mask,
   1344                                              (l2x_entry_t *)msg->l2x2.data,
   1345                                              msg->readresp.data);
   1346             _soc_l2x2_nak_check(pcid_info->unit, msg);
   1347             break;
   1348         }
   1349 #endif    /* BCM_FIREBOLT_SUPPORT */
   1350         if (SOC_IS_XGS_FABRIC(pcid_info->unit)) {
   1351             LOG_WARN(BSL_LS_SOC_COMMON,
   1352                      (BSL_META_U(unit,
   1353                                  "Bad call for Hercules: ARL_DELETE_CMD_MSG\n")));
   1354             break;
   1355         }
   1356         break;
   1357     case L2_LOOKUP_CMD_MSG:
   1358 #ifdef    BCM_FIREBOLT_SUPPORT
   1359         if (SOC_IS_FBX(pcid_info->unit)) {
   1360             opcode = L2_LOOKUP_ACK_MSG;
   1361             rv = soc_internal_l2x2_entry_lkup(pcid_info, bank_ignore_mask,
   1362                                               (l2x_entry_t *)msg->l2x2.data,
   1363                                               msg->readresp.data);
   1364             _soc_l2x2_nak_check(pcid_info->unit, msg);
   1365             break;
   1366         }
   1367         break;
   1368 #endif    /* BCM_FIREBOLT_SUPPORT */
   1369     case ARL_LOOKUP_CMD_MSG:
   1370         if (SOC_IS_XGS_FABRIC(pcid_info->unit)) {
   1371             LOG_WARN(BSL_LS_SOC_COMMON,
   1372                      (BSL_META_U(unit,
   1373                                  "Bad call for Hercules: ARL_LOOKUP_CMD_MSG\n")));
   1374             break;
   1375         }
   1376         break;
   1377     case L3_INSERT_CMD_MSG:
   1378         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1379                     (BSL_META_U(unit,
   1380                                 "S-Channel operation: L3_INSERT_CMD_MSG\n")));
   1381 #ifdef    BCM_FIREBOLT_SUPPORT
   1382         if (SOC_IS_FBX(pcid_info->unit)) {
   1383             opcode = L3_INSERT_DONE_MSG;
   1384             /* Coverity
   1385              * This is being called under #ifdef FIREBOLT
   1386              * The coverity is reporting error
   1387              * from the called function in case of TRIDENT2
   1388              * which will not be called
   1389  */
   1390             /* coverity[overrun-buffer-val] */
   1391             rv = soc_internal_l3x2_entry_ins(pcid_info, bank_ignore_mask,
   1392                           (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data,
   1393                           msg->readresp.data);
   1394             break;
   1395         }
   1396 #endif    /* BCM_FIREBOLT_SUPPORT */
   1397         LOG_WARN(BSL_LS_SOC_COMMON,
   1398                  (BSL_META_U(unit,
   1399                              "Bad call for Non-XGS3: L3_INSERT_CMD_MSG\n")));
   1400         rv = -1;
   1401         break;
   1402     case L3_DELETE_CMD_MSG:
   1403         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1404                     (BSL_META_U(unit,
   1405                                 "S-Channel operation: L3_DELETE_CMD_MSG\n")));
   1406 #ifdef    BCM_FIREBOLT_SUPPORT
   1407         if (SOC_IS_FBX(pcid_info->unit)) {
   1408             opcode = L3_DELETE_DONE_MSG;
   1409             rv = soc_internal_l3x2_entry_del(pcid_info, bank_ignore_mask,
   1410                           (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data,
   1411                           msg->readresp.data);
   1412             break;
   1413         }
   1414 #endif    /* BCM_FIREBOLT_SUPPORT */
   1415         LOG_WARN(BSL_LS_SOC_COMMON,
   1416                  (BSL_META_U(unit,
   1417                              "Bad call for Non-XGS3: L3_DELETE_CMD_MSG\n")));
   1418         rv = -1;
   1419         break;
   1420     case L3X2_LOOKUP_CMD_MSG:
   1421 #ifdef    BCM_FIREBOLT_SUPPORT
   1422         if (SOC_IS_FBX(pcid_info->unit)) {
   1423             opcode = L3X2_LOOKUP_ACK_MSG;
   1424             rv = soc_internal_l3x2_entry_lkup(pcid_info, bank_ignore_mask,
   1425                           (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data,
   1426                           msg->readresp.data);
   1427             if (msg->readresp.data[0] == -1) {
   1428                 msg->readresp.header.v2.nack = 1;
   1429             }
   1430             break;
   1431         }
   1432         break;
   1433 #endif    /* BCM_FIREBOLT_SUPPORT */
   1434 
   1435 #if defined(BCM_TRX_SUPPORT)
   1436     case TABLE_INSERT_CMD_MSG:
   1437         if (soc_feature(unit, soc_feature_generic_table_ops)) {
   1438             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1439                         (BSL_META_U(unit,
   1440                                     "S-Channel operation: TABLE_INSERT_CMD_MSG\n")));
   1441 
   1442             opcode = TABLE_INSERT_DONE_MSG;
   1443             banks = bank_ignore_mask;
   1444             if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   1445                 uint32 address;
   1446                 address = msg->gencmd.address;
   1447                 if (soc_feature(unit, soc_feature_ism_memory)) {
   1448                     address &= ~SOC_HASH_BANK_MASK_ISM;
   1449                 }
   1450                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1451                     address &= ~SOC_HASH_BANK_MASK_SHARED;
   1452                 }
   1453                 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk,
   1454                                                acc_type, address);
   1455             } else {
   1456                 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL);
   1457             } 
   1458 #ifdef BCM_ISM_SUPPORT
   1459             if (soc_feature(unit, soc_feature_ism_memory)) {
   1460                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM;
   1461                 if (!banks) {
   1462                     banks = SOC_MEM_HASH_BANK_ALL;
   1463                 } else {
   1464                     banks = ~banks & SOC_HASH_BANK_MASK_ISM;
   1465                 }
   1466                 rv = soc_internal_generic_hash_insert(pcid_info, mem, banks,
   1467                                                       msg->gencmd.data,
   1468                                                       (uint32 *)&msg->genresp.response);
   1469             } else
   1470 #endif
   1471             if (mem == L2Xm) {
   1472                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1473                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1474                 }
   1475                 /* coverity[overrun-buffer-val] */
   1476                 rv = soc_internal_l2_tr_entry_ins(pcid_info, banks,
   1477                                           (l2x_entry_t *)msg->gencmd.data,
   1478                                           (uint32 *)&msg->genresp.response);
   1479             } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) {
   1480                 rv = soc_internal_vlan_xlate_entry_ins(pcid_info, banks,
   1481                                           (vlan_xlate_entry_t *)msg->gencmd.data,
   1482                                           (uint32 *)&msg->genresp.response);
   1483             } else if (mem == EGR_VLAN_XLATEm) {
   1484                 rv = soc_internal_egr_vlan_xlate_entry_ins(pcid_info, banks,
   1485                                           (egr_vlan_xlate_entry_t *)msg->gencmd.data,
   1486                                           (uint32 *)&msg->genresp.response);
   1487 #ifdef BCM_TRIUMPH_SUPPORT
   1488             } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) || mem == MPLS_ENTRYm) {
   1489                 rv = soc_internal_mpls_entry_ins(pcid_info, banks,
   1490                                           (mpls_entry_entry_t *)msg->gencmd.data,
   1491                                           (uint32 *)&msg->genresp.response);
   1492 #endif
   1493 #ifdef BCM_TRIDENT2_SUPPORT
   1494             } else if (mem == ING_VP_VLAN_MEMBERSHIPm) {
   1495                 rv = soc_internal_ing_vp_vlan_member_ins
   1496                     (pcid_info, banks, msg->gencmd.data,
   1497                      (uint32 *)&msg->genresp.response);
   1498             } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) {
   1499                 rv = soc_internal_egr_vp_vlan_member_ins
   1500                     (pcid_info, banks, msg->gencmd.data,
   1501                      (uint32 *)&msg->genresp.response);
   1502             } else if (mem == ING_DNAT_ADDRESS_TYPEm) {
   1503                 rv = soc_internal_ing_dnat_address_type_ins
   1504                     (pcid_info, banks, msg->gencmd.data,
   1505                      (uint32 *)&msg->genresp.response);
   1506             } else if (mem == L2_ENDPOINT_IDm) {
   1507                 rv = soc_internal_l2_endpoint_id_ins
   1508                     (pcid_info, banks, msg->gencmd.data,
   1509                      (uint32 *)&msg->genresp.response);
   1510             } else if (mem == ENDPOINT_QUEUE_MAPm) {
   1511                 rv = soc_internal_endpoint_queue_map_ins
   1512                     (pcid_info, banks, msg->gencmd.data,
   1513                      (uint32 *)&msg->genresp.response);
   1514 #endif
   1515 #ifdef BCM_TOMAHAWK_SUPPORT
   1516             } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) {
   1517                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1518                 rv = soc_internal_exact_match_ins
   1519                     (pcid_info, banks, msg->gencmd.data,
   1520                      (uint32 *)&msg->genresp.response);
   1521 #endif /* BCM_TOMAHAWK_SUPPORT */
   1522 #ifdef BCM_TOMAHAWK3_SUPPORT
   1523             } else if (mem == L3_TUNNEL_SINGLEm ||
   1524                 mem == L3_TUNNEL_DOUBLEm || mem == L3_TUNNEL_QUADm) {
   1525                 rv = soc_internal_tunnel_entry_ins(pcid_info,
   1526                                  banks,
   1527                                  (void *)msg->gencmd.data,
   1528                                  (uint32 *)&msg->genresp.response);
   1529 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1530             } else {
   1531                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1532                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1533                 }
   1534                 /* coverity[overrun-buffer-val] */
   1535                 rv = soc_internal_l3x2_entry_ins(pcid_info, banks,
   1536                               (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data,
   1537                               (uint32 *)&msg->genresp.response);
   1538             }
   1539             if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1540 		        !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1541                 if ((msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_INSERTED) &&
   1542                     (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_REPLACED)) {
   1543                     msg->genresp_v2.header.v2.nack = 1;
   1544                 }
   1545             } else {
   1546                 if ((msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_INSERTED) &&
   1547                     (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_REPLACED)) {
   1548                     msg->genresp.header.v2.nack = 1;
   1549                 }
   1550             }
   1551             break;
   1552         }
   1553     case TABLE_DELETE_CMD_MSG:
   1554         if (soc_feature(unit, soc_feature_generic_table_ops)) {
   1555             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1556                         (BSL_META_U(unit,
   1557                                     "S-Channel operation: TABLE_DELETE_CMD_MSG\n")));
   1558 
   1559             opcode = TABLE_DELETE_DONE_MSG;
   1560             banks = bank_ignore_mask;
   1561             if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   1562                 uint32 address;
   1563                 address = msg->gencmd.address;
   1564                 if (soc_feature(unit, soc_feature_ism_memory)) {
   1565                     address &= ~SOC_HASH_BANK_MASK_ISM;
   1566                 }
   1567                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1568                     address &= ~SOC_HASH_BANK_MASK_SHARED;
   1569                 }
   1570                 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk,
   1571                                                acc_type, address);
   1572             } else {
   1573                 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL);
   1574             } 
   1575 #ifdef BCM_ISM_SUPPORT
   1576             if (soc_feature(unit, soc_feature_ism_memory)) {
   1577                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM;
   1578                 if (!banks) {
   1579                     banks = SOC_MEM_HASH_BANK_ALL;
   1580                 } else {
   1581                     banks = ~banks & SOC_HASH_BANK_MASK_ISM;
   1582                 }
   1583                 rv = soc_internal_generic_hash_delete(pcid_info, mem, banks,
   1584                                                       msg->gencmd.data,
   1585                                                       (uint32 *)&msg->genresp.response);
   1586             } else
   1587 #endif
   1588             if (mem == L2Xm) {
   1589                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1590                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1591                 }
   1592                 rv = soc_internal_l2_tr_entry_del(pcid_info, banks,
   1593                                           (l2x_entry_t *)msg->gencmd.data,
   1594                                           (uint32 *)&msg->genresp.response);
   1595             } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) {
   1596                 rv = soc_internal_vlan_xlate_entry_del(pcid_info, banks,
   1597                                           (vlan_xlate_entry_t *)msg->gencmd.data,
   1598                                           (uint32 *)&msg->genresp.response);
   1599             } else if (mem == EGR_VLAN_XLATEm) {
   1600                 rv = soc_internal_egr_vlan_xlate_entry_del(pcid_info, banks,
   1601                                           (egr_vlan_xlate_entry_t *)msg->gencmd.data,
   1602                                           (uint32 *)&msg->genresp.response);
   1603 #ifdef BCM_TRIUMPH_SUPPORT
   1604             } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) ||
   1605                        mem == MPLS_ENTRYm) {
   1606                 /* coverity[callee_ptr_arith] */
   1607                 rv = soc_internal_mpls_entry_del(pcid_info, banks,
   1608                                           (mpls_entry_entry_t *)msg->gencmd.data,
   1609                                           (uint32 *)&msg->genresp.response);
   1610 #endif
   1611 #ifdef BCM_TRIDENT2_SUPPORT
   1612             } else if (mem == ING_VP_VLAN_MEMBERSHIPm) {
   1613                 rv = soc_internal_ing_vp_vlan_member_del
   1614                     (pcid_info, banks, msg->gencmd.data,
   1615                      (uint32 *)&msg->genresp.response);
   1616             } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) {
   1617                 rv = soc_internal_egr_vp_vlan_member_del
   1618                     (pcid_info, banks, msg->gencmd.data,
   1619                      (uint32 *)&msg->genresp.response);
   1620             } else if (mem == ING_DNAT_ADDRESS_TYPEm) {
   1621                 rv = soc_internal_ing_dnat_address_type_del
   1622                     (pcid_info, banks, msg->gencmd.data,
   1623                      (uint32 *)&msg->genresp.response);
   1624             } else if (mem == L2_ENDPOINT_IDm) {
   1625                 rv = soc_internal_l2_endpoint_id_del
   1626                     (pcid_info, banks, msg->gencmd.data,
   1627                      (uint32 *)&msg->genresp.response);
   1628             } else if (mem == ENDPOINT_QUEUE_MAPm) {
   1629                 rv = soc_internal_endpoint_queue_map_del
   1630                     (pcid_info, banks, msg->gencmd.data,
   1631                      (uint32 *)&msg->genresp.response);
   1632 #endif
   1633 #ifdef BCM_TOMAHAWK_SUPPORT
   1634             } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) {
   1635                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1636                 rv = soc_internal_exact_match_del
   1637                     (pcid_info, banks, msg->gencmd.data,
   1638                      (uint32 *)&msg->genresp.response);
   1639 #endif /* BCM_TOMAHAWK_SUPPORT */
   1640             } else {
   1641                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1642                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1643                 }
   1644                 rv = soc_internal_l3x2_entry_del(pcid_info, banks,
   1645                               (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data,
   1646                               (uint32 *)&msg->genresp.response);
   1647             }
   1648             if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1649                 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1650                 if (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_DELETED) {
   1651                     msg->genresp_v2.header.v2.nack = 1;
   1652                 }
   1653             } else {
   1654                 if (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_DELETED) {
   1655                     msg->genresp.header.v2.nack = 1;
   1656                 }
   1657             }
   1658             break;
   1659         }
   1660     case TABLE_LOOKUP_CMD_MSG:
   1661         if (soc_feature(unit, soc_feature_generic_table_ops)) {
   1662             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1663                         (BSL_META_U(unit,
   1664                                     "S-Channel operation: TABLE_LOOKUP_CMD_MSG\n")));
   1665 
   1666             opcode = TABLE_LOOKUP_DONE_MSG;
   1667             banks = bank_ignore_mask;
   1668             if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   1669                 uint32 address;
   1670                 address = msg->gencmd.address;
   1671                 if (soc_feature(unit, soc_feature_ism_memory)) {
   1672                     address &= ~SOC_HASH_BANK_MASK_ISM;
   1673                 }
   1674                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1675                     address &= ~SOC_HASH_BANK_MASK_SHARED;
   1676                 }
   1677                 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk,
   1678                                                acc_type, address);
   1679             } else {
   1680                 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL);
   1681             } 
   1682             assert(mem != INVALIDm);
   1683 
   1684 #ifdef BCM_ISM_SUPPORT
   1685             if (soc_feature(unit, soc_feature_ism_memory)) {
   1686                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM;
   1687                 if (!banks) {
   1688                     banks = SOC_MEM_HASH_BANK_ALL;
   1689                 } else {
   1690                     banks = ~banks & SOC_HASH_BANK_MASK_ISM;
   1691                 }
   1692                 rv = soc_internal_generic_hash_lookup(pcid_info, mem, banks,
   1693                                                       msg->gencmd.data,
   1694                                                       (uint32 *)&msg->genresp.response);
   1695             } else
   1696 #endif
   1697             if (mem == L2Xm) {
   1698                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1699                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1700                 }
   1701                 rv = soc_internal_l2_tr_entry_lkup(pcid_info, banks,
   1702                                           (l2x_entry_t *)msg->gencmd.data,
   1703                                           (uint32 *)&msg->genresp.response);
   1704             } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) {
   1705                 rv = soc_internal_vlan_xlate_entry_lkup(pcid_info, banks,
   1706                                           (vlan_xlate_entry_t *)msg->gencmd.data,
   1707                                           (uint32 *)&msg->genresp.response);
   1708             } else if (mem == EGR_VLAN_XLATEm) {
   1709                 rv = soc_internal_egr_vlan_xlate_entry_lkup(pcid_info, banks,
   1710                                           (egr_vlan_xlate_entry_t *)msg->gencmd.data,
   1711                                           (uint32 *)&msg->genresp.response);
   1712 #ifdef BCM_TRIUMPH_SUPPORT
   1713             } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) ||
   1714                        mem == MPLS_ENTRYm) {
   1715                 rv = soc_internal_mpls_entry_lkup(pcid_info, banks,
   1716                                           (mpls_entry_entry_t *)msg->gencmd.data,
   1717                                           (uint32 *)&msg->genresp.response);
   1718 #endif
   1719 #ifdef BCM_TRIDENT2_SUPPORT
   1720             } else if (mem == ING_VP_VLAN_MEMBERSHIPm) {
   1721                 rv = soc_internal_ing_vp_vlan_member_lkup
   1722                     (pcid_info, banks, msg->gencmd.data,
   1723                      (uint32 *)&msg->genresp.response);
   1724             } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) {
   1725                 rv = soc_internal_egr_vp_vlan_member_lkup
   1726                     (pcid_info, banks, msg->gencmd.data,
   1727                      (uint32 *)&msg->genresp.response);
   1728             } else if (mem == ING_DNAT_ADDRESS_TYPEm) {
   1729                 rv = soc_internal_ing_dnat_address_type_lkup
   1730                     (pcid_info, banks, msg->gencmd.data,
   1731                      (uint32 *)&msg->genresp.response);
   1732             } else if (mem == L2_ENDPOINT_IDm) {
   1733                 rv = soc_internal_l2_endpoint_id_lkup
   1734                     (pcid_info, banks, msg->gencmd.data,
   1735                      (uint32 *)&msg->genresp.response);
   1736             } else if (mem == ENDPOINT_QUEUE_MAPm) {
   1737                 rv = soc_internal_endpoint_queue_map_lkup
   1738                     (pcid_info, banks, msg->gencmd.data,
   1739                      (uint32 *)&msg->genresp.response);
   1740 #endif
   1741 #ifdef BCM_TOMAHAWK_SUPPORT
   1742             } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) {
   1743                 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1744                 rv = soc_internal_exact_match_lkup
   1745                     (pcid_info, banks, msg->gencmd.data,
   1746                      (uint32 *)&msg->genresp.response);
   1747 #endif /* BCM_TOMAHAWK_SUPPORT */
   1748             } else {
   1749                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1750                     banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED;
   1751                 }
   1752                 rv = soc_internal_l3x2_entry_lkup(pcid_info, banks,
   1753                               (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data,
   1754                               (uint32 *)&msg->genresp.response);
   1755             }
   1756             if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1757                 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1758                 if (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_FOUND) {
   1759                     msg->genresp_v2.header.v2.nack = 1;
   1760                 }
   1761             } else {
   1762                 if (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_FOUND) {
   1763                     msg->genresp.header.v2.nack = 1;
   1764                 }
   1765             }
   1766             break;
   1767         }
   1768     case FIFO_POP_CMD_MSG:
   1769         if (soc_feature(unit, soc_feature_mem_push_pop)) {
   1770             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1771                         (BSL_META_U(unit,
   1772                                     "S-Channel operation: FIFO_POP_CMD_MSG\n")));
   1773 
   1774             mem = soc_addr_to_mem(pcid_info->unit, msg->popcmd.address, NULL);
   1775             /* coverity[overrun-buffer-val] */
   1776             rv = soc_internal_fifo_pop(pcid_info, mem, msg->popresp.data);
   1777             if (rv == 1) {
   1778                 /* Fifo empty */
   1779                 msg->popresp.header.v2.nack = 1;
   1780                 rv = 0;
   1781             }
   1782             opcode = FIFO_POP_DONE_MSG;
   1783         }
   1784         break;
   1785     case FIFO_PUSH_CMD_MSG:
   1786         if (soc_feature(unit, soc_feature_mem_push_pop)) {
   1787             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1788                         (BSL_META_U(unit,
   1789                                     "S-Channel operation: FIFO_PUSH_CMD_MSG\n")));
   1790             
   1791             mem = soc_addr_to_mem(pcid_info->unit, msg->pushcmd.address, NULL);
   1792             /* coverity[overrun-buffer-val] */
   1793             rv = soc_internal_fifo_push(pcid_info, mem, msg->pushcmd.data);
   1794             if (rv == 1) {
   1795                 /* Fifo full */
   1796                 msg->popresp.header.v2.nack = 1;
   1797                 rv = 0;
   1798             }
   1799             opcode = FIFO_PUSH_DONE_MSG;
   1800         }
   1801         break;
   1802 #endif /* BCM_TRX_SUPPORT */
   1803     default:
   1804         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1805                     (BSL_META_U(unit,
   1806                                 "S-Channel operation: message not handled: %s (%d)\n"),
   1807                      soc_schan_op_name(opcode), opcode));
   1808         break;
   1809     }
   1810 
   1811     msg->header.v2.opcode = opcode;
   1812     if (rv == 0) {
   1813 #ifdef BCM_CMICM_SUPPORT
   1814         if (pcid_info->cmicm >= CMC0) {
   1815 /*            PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) |= SC_CMCx_MSG_DONE;  */
   1816             pcid_reg_or_write(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET, SC_CMCx_MSG_DONE);
   1817         } else 
   1818 #endif
   1819         {
   1820 /*            PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_DONE_TST; */
   1821             pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_DONE_TST);
   1822         }
   1823     }
   1824 
   1825     if (soc_feature(unit, soc_feature_schmsg_alias)) {
   1826         /* Synchronize message buffer (at 0) with aliased memory */
   1827         memcpy(&(PCIM(pcid_info, 0)),
   1828                &(PCIM(pcid_info, PCIM_ALIAS_OFFSET)), PCIM_ALIASED_BYTES);
   1829     }
   1830 
   1831     if(data) {
   1832         *data = *msg; 
   1833     }
   1834 
   1835     return rv;
   1836 }
   1837 
   1838 /*
   1839  * soc_internal_table_dma
   1840  *
   1841  * Do a table DMA transfer
   1842  */
   1843 
   1844 void
   1845 soc_internal_table_dma(pcid_info_t *pcid_info)
   1846 {
   1847     uint32        entry[SOC_MAX_MEM_WORDS];
   1848     uint32        table_addr;
   1849     uint32        dma_addr;
   1850     uint32        dma_count;
   1851     uint32        dma_beats;
   1852 
   1853     table_addr = PCIM(pcid_info, CMIC_TABLE_DMA_START);
   1854     dma_addr = PCIM(pcid_info, CMIC_ARL_DMA_ADDR);
   1855     dma_count = PCIM(pcid_info, CMIC_ARL_DMA_CNT) & 0x1fffffff;
   1856     dma_beats = PCIM(pcid_info, CMIC_ARL_DMA_CNT) >> 29;
   1857 
   1858     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1859                 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x beats=%d dest=0x%x\n"),
   1860                  table_addr, dma_count, dma_beats, dma_addr));
   1861 
   1862     while (dma_count-- > 0) {
   1863         soc_internal_read_mem(pcid_info, table_addr, entry);
   1864         table_addr++;
   1865 
   1866         soc_internal_memory_store(pcid_info, dma_addr,
   1867                                   (uint8 *)entry, dma_beats * 4,
   1868                                   MF_ES_DMA_OTHER);
   1869         dma_addr += dma_beats * 4;
   1870     }
   1871 
   1872     
   1873 
   1874     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_ARL_DMA_DONE_TST;
   1875     PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_ARL_DMA_CNT0;
   1876     soc_internal_send_int(pcid_info);
   1877 }
   1878 
   1879 /*
   1880  * soc_internal_xgs3_table_dma
   1881  *
   1882  * Do a table DMA transfer
   1883  */
   1884 
   1885 #define DMA_BURST_SIZE  256 /* Max number of WORDS per DMA transfer */
   1886 
   1887 #if DMA_BURST_SIZE < SOC_MAX_MEM_WORDS
   1888 #error Burst size is too small
   1889 #endif
   1890 
   1891 #define DMA_BURST_ALLOC  (DMA_BURST_SIZE + SOC_MAX_MEM_WORDS)
   1892 /* Max number of WORDS per DMA transfer + datum mem read overhead*/
   1893 
   1894 void
   1895 soc_internal_xgs3_table_dma(pcid_info_t *pcid_info)
   1896 {
   1897     uint32 entry[DMA_BURST_ALLOC];
   1898     uint32 table_addr;
   1899     uint32 dma_addr;
   1900     uint32 dma_count;
   1901     uint32 dma_incr;
   1902     uint32 dma_beats;
   1903     int    i, burst_count;
   1904     schan_msg_t    *msg;
   1905     int             opcode, dst_blk, src_blk, acc_type, data_byte_len, dma;
   1906     uint32          bank_ignore_mask;
   1907 
   1908     msg = (schan_msg_t *)&PCIM(pcid_info,
   1909                                CMIC_SCHAN_MESSAGE(pcid_info->unit, 0));
   1910 
   1911     if (!(PCIM(pcid_info, CMIC_TABLE_DMA_CFG) & CMIC_TDMA_CFG_EN)) {
   1912         return;
   1913     }
   1914     soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode,
   1915                              &dst_blk, &src_blk, &acc_type, &data_byte_len,
   1916                              &dma, &bank_ignore_mask);
   1917 
   1918     table_addr = PCIM(pcid_info, CMIC_TABLE_DMA_SBUS_START_ADDR);
   1919     dma_addr = PCIM(pcid_info, CMIC_TABLE_DMA_PCIMEM_START_ADDR);
   1920     dma_count = PCIM(pcid_info, CMIC_TABLE_DMA_ENTRY_COUNT) & 0xffffff;
   1921     dma_incr = (PCIM(pcid_info, CMIC_TABLE_DMA_ENTRY_COUNT) >> 24) & 0x1f;
   1922     dma_beats = (PCIM(pcid_info, CMIC_TABLE_DMA_CFG) >> 16) & (0x1f);
   1923 
   1924     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1925                 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x inc=%d beats=%d dest=0x%x\n"),
   1926                  table_addr, dma_count, dma_incr, dma_beats, dma_addr));
   1927 
   1928     burst_count = DMA_BURST_SIZE / dma_beats;
   1929 
   1930     while (dma_count > 0) {
   1931         /* Adjust the burst size at the end of the table */
   1932         if (dma_count < burst_count) burst_count = dma_count;
   1933        
   1934         /* Read as many entries as can fit in the burst buffer */
   1935         for (i = 0; i < burst_count; i++) {
   1936             soc_internal_extended_read_bytes
   1937                 (pcid_info, dst_blk, 0, table_addr,
   1938                  (uint8 *) (entry + i * dma_beats),
   1939                  dma_beats * (sizeof(uint32)));
   1940             table_addr += 1 << dma_incr;
   1941         }
   1942 
   1943         /* convert to CPU endian-ness */
   1944         for (i=0; i < (burst_count * dma_beats); i++) {
   1945             *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 
   1946                                                     MF_ES_DMA_OTHER);
   1947         }
   1948         
   1949         /* Send all these entries in one shot */
   1950         soc_internal_bytes_store(pcid_info, dma_addr, (uint8 *)entry,
   1951                                  (dma_beats * sizeof(uint32) * burst_count));
   1952         dma_addr += dma_beats * sizeof(uint32) * burst_count;
   1953         dma_count -= burst_count;
   1954     }
   1955 
   1956     PCIM(pcid_info, CMIC_TABLE_DMA_CFG) |= CMIC_TDMA_CFG_DONE;
   1957     PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_TDMA_DONE;
   1958     soc_internal_send_int(pcid_info);
   1959 }
   1960 
   1961 #ifdef BCM_CMICM_SUPPORT
   1962 void
   1963 soc_internal_xgs3_cmicm_table_dma(pcid_info_t *pcid_info)
   1964 {
   1965     uint32      entry[DMA_BURST_ALLOC];
   1966     uint32      table_addr;
   1967     uint32      dma_addr;
   1968     uint32      dma_count;
   1969     uint32      dma_incr;
   1970     uint32      dma_beats;
   1971     int         i, burst_count;
   1972     soc_block_t block;
   1973     int         acc_type;
   1974 
   1975     if (!(PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_CFG_OFFSET) & CMIC_TDMA_CFG_EN)) {
   1976         return;
   1977     }
   1978 
   1979     table_addr = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_START_ADDR_OFFSET);
   1980     dma_addr = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_PCIMEM_START_ADDR_OFFSET);
   1981     dma_count = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_ENTRY_COUNT_OFFSET) & 0xffffff;
   1982     dma_incr = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_ENTRY_COUNT_OFFSET) >> 24) & 0x1f;
   1983     dma_beats = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_CFG_OFFSET) >> 11) & (0x1f);
   1984     
   1985     block = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIG_OFFSET) >> 3) & 0x3f;
   1986     acc_type = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIG_OFFSET) & 7;
   1987 
   1988     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1989                 (BSL_META("Table DMA: schan_addr=0x%x block: %d acc_type=%d "
   1990                           "count=0x%x inc=%d beats=%d dest=0x%x\n"),
   1991                  table_addr, block, acc_type, dma_count, dma_incr, dma_beats,
   1992                  dma_addr));
   1993 
   1994     burst_count = DMA_BURST_SIZE / dma_beats;
   1995 
   1996     while (dma_count > 0) {
   1997         /* Adjust the burst size at the end of the table */
   1998         if (dma_count < burst_count) burst_count = dma_count;
   1999        
   2000         /* Read as many entries as can fit in the burst buffer */
   2001         for (i = 0; i < burst_count; i++) {
   2002             soc_internal_extended_read_bytes(pcid_info, block, acc_type,
   2003                                              table_addr,
   2004                                              (uint8 *) (entry + i * dma_beats),
   2005                                              dma_beats * (sizeof(uint32)));
   2006             table_addr += 1 << dma_incr;
   2007         }
   2008 
   2009         /* convert to CPU endian-ness */
   2010         for (i=0; i < (burst_count * dma_beats); i++) {
   2011             *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 
   2012                                                     MF_ES_DMA_OTHER);
   2013         }
   2014         
   2015         /* Send all these entries in one shot */
   2016         soc_internal_bytes_store(pcid_info, dma_addr, (uint8 *)entry,
   2017                                  (dma_beats * sizeof(uint32) * burst_count));
   2018         dma_addr += dma_beats * sizeof(uint32) * burst_count;
   2019         dma_count -= burst_count;
   2020     }
   2021 
   2022     PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_STAT_OFFSET) |= TDMA_DONE;
   2023     PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_TDMA_DONE;
   2024     soc_internal_cmicm_send_int(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET);
   2025 }
   2026 #endif
   2027 
   2028 /*
   2029  * soc_internal_xgs3_tslam_dma
   2030  *
   2031  * Do a table SLAM DMA transfer
   2032  */
   2033 
   2034 void
   2035 soc_internal_xgs3_tslam_dma(pcid_info_t *pcid_info)
   2036 {
   2037     uint32        entry[DMA_BURST_SIZE];
   2038     uint32        table_addr;
   2039     uint32        dma_addr;
   2040     uint32        dma_count;
   2041     uint32      dma_incr;
   2042     uint32        dma_beats;
   2043     int         direction;
   2044     int         i, burst_count, entry_idx;
   2045     schan_msg_t    *msg;
   2046     int             opcode, dst_blk, src_blk, acc_type, data_byte_len, dma;
   2047     uint32          bank_ignore_mask;
   2048 
   2049     msg = (schan_msg_t *)&PCIM(pcid_info,
   2050                                CMIC_SCHAN_MESSAGE(pcid_info->unit, 0));
   2051 
   2052     if (!(PCIM(pcid_info, CMIC_SLAM_DMA_CFG) & CMIC_SLAM_CFG_EN)) {
   2053         return;
   2054     }
   2055     
   2056     soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode,
   2057                              &dst_blk, &src_blk, &acc_type, &data_byte_len,
   2058                              &dma, &bank_ignore_mask);
   2059 
   2060     table_addr = PCIM(pcid_info, CMIC_SLAM_DMA_SBUS_START_ADDR);
   2061     dma_addr = PCIM(pcid_info, CMIC_SLAM_DMA_PCIMEM_START_ADDR);
   2062     dma_count = PCIM(pcid_info, CMIC_SLAM_DMA_ENTRY_COUNT) & 0xffffff;
   2063     dma_incr = (PCIM(pcid_info, CMIC_SLAM_DMA_ENTRY_COUNT) >> 24) & 0x1f;
   2064     dma_beats = (PCIM(pcid_info, CMIC_SLAM_DMA_CFG) >> 16) & (0x1f);
   2065     direction = (PCIM(pcid_info, CMIC_SLAM_DMA_CFG) & CMIC_SLAM_CFG_DIR);
   2066 
   2067     if (direction) {
   2068         /* Last entry */
   2069         dma_addr = dma_addr + dma_count * 4 * dma_beats;
   2070         table_addr = table_addr + (dma_count - 1) * (1 << dma_incr);
   2071     }
   2072 
   2073     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2074                 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x inc=%d beats=%d dest=0x%x\n"),
   2075                  table_addr, dma_count, dma_incr, dma_beats, dma_addr));
   2076 
   2077     burst_count = DMA_BURST_SIZE / dma_beats;
   2078 
   2079     while (dma_count > 0) {
   2080         /* Adjust the burst size at the end of the table */
   2081         if (dma_count < burst_count) burst_count = dma_count;
   2082 
   2083         /* Get as many entries as can fit in the burst buffer */
   2084         soc_internal_bytes_fetch(pcid_info, 
   2085                                  (direction ? 
   2086                                    (dma_addr - burst_count * dma_beats * 4) : 
   2087                                    dma_addr),
   2088                                  (uint8 *)entry,
   2089                                  dma_beats * 4 * burst_count);
   2090         
   2091         /* convert to chip (same as host for sim) endian-ness */
   2092         for (i=0; i < (burst_count * dma_beats); i++) {
   2093             *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i),
   2094                                                     MF_ES_DMA_OTHER);
   2095         }
   2096 
   2097         /* Write all the entries we've got */
   2098         for (i = 0; i < burst_count; i++) {
   2099             entry_idx = direction ? burst_count - i - 1 : i;
   2100             soc_internal_extended_write_bytes
   2101                 (pcid_info, dst_blk, 0, table_addr,
   2102                  (uint8 *)(entry + entry_idx * dma_beats), dma_beats * 4);
   2103             table_addr += direction ? -(1 << dma_incr) : 1 << dma_incr;
   2104         }
   2105 
   2106         dma_addr += (direction ? -(dma_beats * 4 * burst_count) : 
   2107                                  (dma_beats * 4 * burst_count));
   2108         dma_count -= burst_count;
   2109     }
   2110 
   2111     PCIM(pcid_info, CMIC_SLAM_DMA_CFG) |= CMIC_SLAM_CFG_DONE;
   2112     PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_TSLAM_DONE;
   2113     soc_internal_send_int(pcid_info);
   2114 }
   2115 
   2116 #ifdef BCM_CMICM_SUPPORT
   2117 void
   2118 soc_internal_xgs3_cmicm_tslam_dma(pcid_info_t *pcid_info)
   2119 {
   2120     uint32      entry[DMA_BURST_SIZE];
   2121     uint32      table_addr;
   2122     uint32      dma_addr;
   2123     uint32      dma_count;
   2124     uint32      dma_incr;
   2125     uint32      dma_beats;
   2126     int         direction;
   2127     int         i, burst_count, entry_idx;
   2128     soc_block_t block;
   2129     int         acc_type;
   2130 
   2131     if (!(PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) & CMIC_SLAM_CFG_EN)) {
   2132         return;
   2133     }
   2134     
   2135     table_addr = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_START_ADDR_OFFSET);
   2136     dma_addr = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_PCIMEM_START_ADDR_OFFSET);
   2137     dma_count = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_ENTRY_COUNT_OFFSET) & 0xffffff;
   2138     dma_incr = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_ENTRY_COUNT_OFFSET) >> 24) & 0x1f;
   2139     dma_beats = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) >> 11) & (0x1f);
   2140     direction = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) & SLDMA_CFG_DIR);
   2141 
   2142     block = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIG_OFFSET) >> 3) & 0x3f;
   2143     acc_type = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIG_OFFSET) & 7;
   2144 
   2145     if (direction) {
   2146         /* Last entry */
   2147         dma_addr = dma_addr + dma_count * 4 * dma_beats;
   2148         table_addr = table_addr + (dma_count - 1) * (1 << dma_incr);
   2149     }
   2150 
   2151     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2152                 (BSL_META("Table DMA: schan_addr=0x%x block=%d acc_type=%d "
   2153                           "count=0x%x inc=%d beats=%d dest=0x%x\n"),
   2154                  table_addr, block, acc_type, dma_count, dma_incr, dma_beats,
   2155                  dma_addr));
   2156 
   2157     burst_count = DMA_BURST_SIZE / dma_beats;
   2158 
   2159     while (dma_count > 0) {
   2160         /* Adjust the burst size at the end of the table */
   2161         if (dma_count < burst_count) burst_count = dma_count;
   2162 
   2163         /* Get as many entries as can fit in the burst buffer */
   2164         soc_internal_bytes_fetch(pcid_info, 
   2165                                  (direction ? 
   2166                                    (dma_addr - burst_count * dma_beats * 4) : 
   2167                                    dma_addr),
   2168                                  (uint8 *)entry,
   2169                                  dma_beats * 4 * burst_count);
   2170         
   2171         /* convert to chip (same as host for sim) endian-ness */
   2172         for (i=0; i < (burst_count * dma_beats); i++) {
   2173             *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i),
   2174                                                     MF_ES_DMA_OTHER);
   2175         }
   2176 
   2177         /* Write all the entries we've got */
   2178         for (i = 0; i < burst_count; i++) {
   2179             entry_idx = direction ? burst_count - i - 1 : i;
   2180             soc_internal_extended_write_bytes(pcid_info, block, acc_type,
   2181                                               table_addr, 
   2182                                      (uint8 *)(entry + entry_idx * dma_beats),
   2183                                      dma_beats * 4);
   2184             table_addr += direction ? -(1 << dma_incr) : 1 << dma_incr;
   2185         }
   2186 
   2187         dma_addr += (direction ? -(dma_beats * 4 * burst_count) : 
   2188                                  (dma_beats * 4 * burst_count));
   2189         dma_count -= burst_count;
   2190     }
   2191 
   2192     PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_STAT_OFFSET) |= SLDMA_DONE;
   2193     PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_TSLAM_DONE;
   2194     soc_internal_cmicm_send_int(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET);
   2195 }
   2196 
   2197 void
   2198 soc_internal_cmicm_sbusdma(pcid_info_t *pcid_info, uint32 reg)
   2199 {
   2200     schan_msg_t msg;
   2201     int         opcode, dst_blk, src_blk, acc_type, data_byte_len, dma;
   2202     uint32      bank_ignore_mask;
   2203     uint32      buffer[DMA_BURST_ALLOC];
   2204     uint32      rval;
   2205     uint32      host_addr, sbus_addr, index, offset;
   2206     int         host_incr, sbus_incr, index_incr, offset_incr;
   2207     uint32      dma_count, beats;
   2208     int         i, burst_count, burst_size;
   2209     int8        ch;
   2210     int         cmc;
   2211     soc_mem_t   mem;
   2212     soc_field_t field;
   2213 
   2214     cmc = ((reg >> 12) & 0x3) - 1;
   2215     ch = ((reg & 0xfff) - 0x600) / 0x50;
   2216 
   2217     rval = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
   2218     if (!soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr,
   2219                            rval, STARTf)) {
   2220         return;
   2221     }
   2222 
   2223     msg.header_dword = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_OPCODE(cmc, ch));
   2224     soc_schan_header_cmd_get(pcid_info->unit, &msg.header, &opcode,
   2225                              &dst_blk, &src_blk, &acc_type, &data_byte_len,
   2226                              &dma, &bank_ignore_mask);
   2227 
   2228     switch (opcode) {
   2229     case WRITE_MEMORY_CMD_MSG:
   2230         field = REQ_WORDSf;
   2231         break;
   2232     case READ_MEMORY_CMD_MSG:
   2233         field = REP_WORDSf;
   2234         break;
   2235     default:
   2236         return;
   2237     }
   2238     host_addr = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_HOSTADDR(cmc, ch));
   2239     sbus_addr = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_ADDRESS(cmc, ch));
   2240     dma_count = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_COUNT(cmc, ch));
   2241 
   2242     mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk, acc_type, sbus_addr);
   2243     assert(mem != INVALIDm);
   2244     index = sbus_addr ^ SOC_MEM_INFO(pcid_info->unit, mem).base;
   2245 
   2246     rval = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch));
   2247     beats = soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr,
   2248                               rval, field);
   2249     offset_incr = soc_reg_field_get(pcid_info->unit,
   2250                                     CMIC_CMC0_SBUSDMA_CH0_REQUESTr, rval,
   2251                                     REQ_SINGLEf) ? 0 : beats;
   2252     host_incr = offset_incr * sizeof(uint32);
   2253     if (soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr,
   2254                           rval, INCR_NOADDf)) {
   2255         sbus_incr = 0;
   2256         index_incr = 0;
   2257     } else {
   2258         sbus_incr =
   2259             1 << soc_reg_field_get(pcid_info->unit,
   2260                                    CMIC_CMC0_SBUSDMA_CH0_REQUESTr,
   2261                                    rval, INCR_SHIFTf);
   2262         index_incr = 1;
   2263     }
   2264 
   2265     if (host_incr == 0) {
   2266         burst_count = dma_count;
   2267         burst_size = beats * sizeof(uint32);
   2268     } else {
   2269         burst_count = DMA_BURST_SIZE / beats;
   2270         burst_size = burst_count * beats * sizeof(uint32);
   2271     }
   2272 
   2273     if (soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr,
   2274                            rval, DECRf)) {
   2275         sbus_addr += (dma_count - 1) * sbus_incr;
   2276         sbus_incr = -sbus_incr;
   2277         index_incr = -index_incr;
   2278     }
   2279 
   2280     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2281                 (BSL_META("SBUS DMA: mem=%d index=0x%x sbus_addr=0x%x dst_blk=%d acc_type=%d"
   2282                           "dma_cout=0x%x beats=%d sbus_incr=%d host_addr=0x%x host_incr=%d\n"),
   2283                  mem, index, sbus_addr, dst_blk, acc_type, dma_count, beats, sbus_incr,
   2284                  host_addr, host_incr));
   2285 
   2286     if (opcode == WRITE_MEMORY_CMD_MSG) {
   2287         while (dma_count > 0) {
   2288             /* Adjust the burst size at the end of the table */
   2289             if (dma_count < burst_count) {
   2290                 burst_count = dma_count;
   2291                 burst_size = burst_count * beats * sizeof(uint32);
   2292             }
   2293 
   2294             /* Fill the burst buffer from S-chan socket */
   2295             soc_internal_bytes_fetch(pcid_info, host_addr, (uint8 *)buffer,
   2296                                      burst_size);
   2297 
   2298             /* Convert to device (same as host for sim) endian-ness */
   2299             for (i = 0; i < burst_size / sizeof(uint32); i++) {
   2300                 buffer[i] = soc_internal_endian_swap(pcid_info, buffer[i],
   2301                                                      MF_ES_DMA_OTHER);
   2302             }
   2303 
   2304             /* Write entries from burst buffer to sim storage */
   2305             offset = 0;
   2306             for (i = 0; i < burst_count; i++) {
   2307                 soc_internal_extended_write_mem_index(pcid_info, mem, index,
   2308                                                       &buffer[offset]);
   2309                 index += index_incr;
   2310                 offset += offset_incr;
   2311             }
   2312 
   2313             sbus_addr += sbus_incr * burst_count;
   2314             host_addr += host_incr * burst_count;
   2315             dma_count -= burst_count;
   2316         }
   2317     } else {
   2318         while (dma_count > 0) {
   2319             /* Adjust the burst size at the end of the table */
   2320             if (dma_count < burst_count) {
   2321                 burst_count = dma_count;
   2322                 burst_size = burst_count * beats * sizeof(uint32);
   2323             }
   2324 
   2325             /* Read entries sim storage into burst buffer */
   2326             offset = 0;
   2327             for (i = 0; i < burst_count; i++) {
   2328                 soc_internal_extended_read_mem_index(pcid_info, mem, index,
   2329                                                      &buffer[offset]);
   2330                 index += index_incr;
   2331                 offset += offset_incr;
   2332             }
   2333 
   2334             /* Convert to host (same as device for sim) endian-ness */
   2335             for (i = 0; i < burst_size / sizeof(uint32); i++) {
   2336                 buffer[i] = soc_internal_endian_swap(pcid_info, buffer[i],
   2337                                                      MF_ES_DMA_OTHER);
   2338             }
   2339 
   2340             /* Flush the burst buffer into S-chan socket */
   2341             soc_internal_bytes_store(pcid_info, host_addr, (uint8 *)buffer,
   2342                                      burst_size);
   2343 
   2344             sbus_addr += sbus_incr * burst_count;
   2345             host_addr += host_incr * burst_count;
   2346             dma_count -= burst_count;
   2347         }
   2348     }
   2349 
   2350     PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)) |=
   2351         ST_CMCx_SBUSDMA_DONE;
   2352     PCIM(pcid_info, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)) |=
   2353         IRQ_CMCx_SBUSDMA_CH_DONE(ch);
   2354     soc_internal_cmicm_send_int(pcid_info,
   2355                                 CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc));
   2356 }
   2357 #endif
   2358 
   2359 void
   2360 soc_internal_schan_ctrl_write(pcid_info_t *pcid_info, uint32 value)
   2361 {
   2362     if (value & 0x80) {
   2363         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2364                     (BSL_META("Set SCHAN_CTRL bit %d\n"), value & 0x1f));
   2365         switch (value & 0xff) {
   2366         case SC_MSG_START_SET:
   2367             if ((pcid_info->schan_cb) && 
   2368                 (pcid_info->schan_cb(pcid_info, pcid_info->unit, NULL) == 0)) {
   2369                 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_SCH_MSG_DONE;
   2370                 soc_internal_send_int(pcid_info);
   2371                 break;
   2372             } else {
   2373                 if (schan_op(pcid_info, pcid_info->unit, NULL) == 0) {
   2374                     PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_SCH_MSG_DONE;
   2375                     soc_internal_send_int(pcid_info);
   2376                 }
   2377             }
   2378             break;
   2379         case SC_MIIM_RD_START_SET:
   2380             soc_internal_miim_op(pcid_info, 1);
   2381             PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_MIIM_OP_DONE;
   2382             soc_internal_send_int(pcid_info);
   2383             break;
   2384         case SC_MIIM_WR_START_SET:
   2385             soc_internal_miim_op(pcid_info, 0);
   2386             PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_MIIM_OP_DONE;
   2387             soc_internal_send_int(pcid_info);
   2388             break;
   2389         case SC_ARL_DMA_EN_SET:
   2390             if (SOC_IS_XGS_SWITCH(pcid_info->unit)) {
   2391                 soc_internal_table_dma(pcid_info);
   2392                 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_ARL_DMA_CNT0;
   2393                 soc_internal_send_int(pcid_info);
   2394             } else {
   2395                 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= 1 << (value & 0x1f);
   2396             }
   2397             break;
   2398         default:
   2399             PCIM(pcid_info, CMIC_SCHAN_CTRL) |= 1 << (value & 0x1f);
   2400             break;
   2401         }
   2402     } else {
   2403         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2404                     (BSL_META("Clear SCHAN_CTRL bit %d\n"), value & 0x1f));
   2405         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~(1 << (value & 0x1f));
   2406         switch (value & 0xff) {
   2407         case SC_MSG_DONE_CLR:
   2408             PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_SCH_MSG_DONE;
   2409             break;
   2410         case SC_MIIM_OP_DONE_CLR:
   2411             PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_MIIM_OP_DONE;
   2412             break;
   2413         case SC_ARL_DMA_EN_CLR:
   2414             PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_ARL_DMA_CNT0;
   2415             break;
   2416         default:
   2417             break;
   2418         }
   2419     }
   2420 }
   2421 
   2422 #ifdef BCM_CMICM_SUPPORT
   2423 void
   2424 soc_internal_cmicm_schan_ctrl_write(pcid_info_t *pcid_info, uint32 reg, uint32 value)
   2425 {
   2426     if (value & SC_CMCx_MSG_START) {
   2427         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2428                     (BSL_META("SCHAN_CTRL msg start.\n")));
   2429         if ((pcid_info->schan_cb) && 
   2430             (pcid_info->schan_cb(pcid_info, pcid_info->unit, NULL) == 0)) {
   2431             PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_SCH_OP_DONE;
   2432             soc_internal_cmicm_send_int(pcid_info, reg);
   2433         } else {
   2434             if (schan_op(pcid_info, pcid_info->unit, NULL) == 0) {
   2435                 PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= 
   2436                     ~(SC_CMCx_MSG_SER_CHECK_FAIL | SC_CMCx_MSG_NAK | SC_CMCx_MSG_TIMEOUT_TST);
   2437                 PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_SCH_OP_DONE;
   2438                 soc_internal_cmicm_send_int(pcid_info, reg);
   2439             }
   2440         }
   2441     } else {
   2442         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2443                     (BSL_META("SCHAN_CTRL msg done.\n")));
   2444         PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= 
   2445                 ~(SC_CMCx_MSG_DONE | SC_CMCx_MSG_SER_CHECK_FAIL | 
   2446                 SC_CMCx_MSG_NAK | SC_CMCx_MSG_TIMEOUT_TST);
   2447     }
   2448 }
   2449 #endif
   2450 
   2451 void
   2452 soc_internal_reset(pcid_info_t *pcid_info)
   2453 {
   2454     int index;
   2455     soc_datum_t *d;
   2456 
   2457     memset(&PCIM(pcid_info, 0), 0, PCIM_SIZE(0));
   2458 
   2459 #ifdef BCM_CMICM_SUPPORT
   2460     if (pcid_info->single_mode) {
   2461         pcid_info->cmicm = CMC0; 
   2462     } else {
   2463         if (soc_feature(pcid_info->unit, soc_feature_cmicm)) {
   2464             pcid_info->cmicm = CMC0;
   2465             
   2466         } else
   2467 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
   2468         if (soc_feature(pcid_info->unit, soc_feature_cmicx) &&
   2469           (SOC_IS_DNX(pcid_info->unit) || SOC_IS_DNXF(pcid_info->unit))) {
   2470             /* Use CMICM simulation instead of CMICX simulation */
   2471             pcid_info->cmicm = CMC0;
   2472         } else
   2473 #endif /* BCM_DNX_SUPPORT || BCM_DNXF_SUPPORT */
   2474 #endif
   2475         {
   2476             pcid_info->cmicm = -1;
   2477             PCIM(pcid_info, CMIC_SCHAN_CTRL) = 0x48002;
   2478         }
   2479 #ifdef BCM_CMICM_SUPPORT
   2480     }
   2481 #endif
   2482     /*
   2483      * Delete all register values from hash table, which effectively
   2484      * returns them to their reset default values.
   2485      */
   2486     for (index = 0; index < SOC_DATUM_HASH_SIZE; index++) {
   2487         while ((d = pcid_info->reg_ht[index]) != NULL) {
   2488             pcid_info->reg_ht[index] = d->next;
   2489             sal_free(d);
   2490         }
   2491     }
   2492 
   2493     /*
   2494      * Delete all memory entries from hash table, which effectively
   2495      * returns them to their null entry values.
   2496      */
   2497     for (index = 0; index < SOC_DATUM_HASH_SIZE; index++) {
   2498         while ((d = pcid_info->mem_ht[index]) != NULL) {
   2499             pcid_info->mem_ht[index] = d->next;
   2500             sal_free(d);
   2501         }
   2502     }
   2503 
   2504     /*
   2505      * Invoke reset callback if installed.
   2506      */
   2507     if (pcid_info->reset_cb) {
   2508         pcid_info->reset_cb(pcid_info, pcid_info->unit);
   2509     }
   2510 }
   2511 
   2512 uint32
   2513 soc_internal_endian_swap(pcid_info_t *pcid_info, uint32 data, int mode)
   2514 {
   2515     if (((mode == MF_ES_DMA_PACKET) &&
   2516          (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_DMA_PACKET))
   2517         ||
   2518         ((mode == MF_ES_DMA_OTHER) &&
   2519          (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_DMA_OTHER))
   2520         ||
   2521         ((mode == MF_ES_PIO) &&
   2522          (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_PIO))) {
   2523         data = (data << 16) | (data >> 16);
   2524         return (data & 0xff00ffff) >> 8 | (data & 0xffff00ff) << 8;
   2525     } else {
   2526         return(data);
   2527     }
   2528 }
   2529 
   2530 void
   2531 soc_internal_memory_fetch(pcid_info_t *pcid_info, uint32 addr, uint8 *b,
   2532                           int length, int mode)
   2533 {
   2534     uint32        offset;
   2535 
   2536     if (pcid_info->opt_rpc_error) {
   2537         return;
   2538     }
   2539 
   2540     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2541                 (BSL_META("soc_internal_memory_fetch: addr=0x%08x length=%d\n"),
   2542                  addr, length));
   2543 
   2544     /*
   2545      * For memory fetch, any alignment is allowed, but 4-byte accesses
   2546      * are always made. This is slow but ....
   2547      */
   2548     offset = addr & 3;
   2549 
   2550     addr &= ~3;            /* Only read 4-bytes */
   2551 
   2552     while (length) {
   2553         uint32    data;
   2554         int    tl;
   2555         int rv;
   2556 
   2557         rv = dma_readmem(pcid_info->client->dmasock, addr, &data);
   2558         if (rv != RPC_OK) {
   2559             LOG_ERROR(BSL_LS_SOC_COMMON,
   2560                       (BSL_META("RPC error: soc_internal_memory_fetch failed. \n")));
   2561             pcid_info->opt_rpc_error = 1;
   2562             break;
   2563         }
   2564 
   2565         data =
   2566             soc_internal_endian_swap(pcid_info,
   2567                                      data,
   2568                                      mode);
   2569         tl = (sizeof(uint32) - offset);
   2570         if (length < tl) {
   2571             tl = length;
   2572         }
   2573 
   2574         sal_memcpy(b, ((uint8 *)&data) + offset, tl);
   2575         length -= tl;
   2576         addr += 4;
   2577         b += 4 - offset;
   2578         offset = 0;
   2579     }
   2580 }
   2581 
   2582 /* Get a string of bytes from memory addr given length; store in buf. */
   2583 void
   2584 soc_internal_bytes_fetch(pcid_info_t *pcid_info, uint32 addr, uint8 *buf,
   2585                           int length)
   2586 {
   2587     int read_len;
   2588 
   2589     if (pcid_info->opt_rpc_error) {
   2590         return;
   2591     }
   2592 
   2593     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2594                 (BSL_META("soc_internal_bytes_fetch: addr=0x%08x length=%d\n"),
   2595                  addr, length));
   2596 
   2597     read_len = dma_read_bytes(pcid_info->client->dmasock, addr, buf, length);
   2598 
   2599     if (read_len != length) {
   2600         LOG_ERROR(BSL_LS_SOC_COMMON,
   2601                   (BSL_META("soc_internal_bytes_fetch: length mismatch.  want %d. got %d\n"),
   2602                    length, read_len));
   2603     }
   2604 
   2605     if (read_len < 0) {
   2606         LOG_ERROR(BSL_LS_SOC_COMMON,
   2607                   (BSL_META("RPC error: soc_internal_bytes_fetch failed. \n")));
   2608         pcid_info->opt_rpc_error = 1;
   2609     }
   2610 }
   2611 
   2612 /* Get a string of bytes from memory addr given length; store in buf. */
   2613 void
   2614 soc_internal_bytes_store(pcid_info_t *pcid_info, uint32 addr, uint8 *buf,
   2615                          int length)
   2616 {
   2617     int rv;
   2618 
   2619     if (pcid_info->opt_rpc_error) {
   2620         return;
   2621     }
   2622 
   2623     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2624                 (BSL_META("soc_internal_bytes_store: addr=0x%08x length=%d\n"),
   2625                  addr, length));
   2626 
   2627     rv = dma_write_bytes(pcid_info->client->dmasock, addr, buf, length);
   2628     if (rv < 0) {
   2629         LOG_ERROR(BSL_LS_SOC_COMMON,
   2630                   (BSL_META("RPC error: soc_internal_bytes_store failed. \n")));
   2631         pcid_info->opt_rpc_error = 1;
   2632     }
   2633 }
   2634 
   2635 void
   2636 soc_internal_memory_store(pcid_info_t *pcid_info, uint32 addr, uint8 *b,
   2637                           int length, int mode)
   2638 {
   2639     uint32          data;
   2640     int             rv;
   2641 
   2642     if (pcid_info->opt_rpc_error) {
   2643         return;
   2644     }
   2645 
   2646     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2647                 (BSL_META("soc_internal_memory_store: addr=0x%08x length=%d\n"),
   2648                  addr, length));
   2649 
   2650     /*
   2651      * Strata (and friends) only support 4-byte aligned writes
   2652      */
   2653 
   2654    addr &= ~3;
   2655 
   2656     while (length > 0) {
   2657         sal_memcpy(&data, b, length < sizeof(data) ? length : sizeof(data));
   2658         rv = dma_writemem(pcid_info->client->dmasock,
   2659                      addr, soc_internal_endian_swap(pcid_info, data, mode));
   2660         if (rv != RPC_OK) {
   2661             LOG_ERROR(BSL_LS_SOC_COMMON,
   2662                       (BSL_META("RPC error: soc_internal_memory_store failed. \n")));
   2663             pcid_info->opt_rpc_error = 1;
   2664             break;
   2665         }
   2666         b += sizeof(uint32);
   2667         addr += sizeof(uint32);
   2668         length -= sizeof(uint32);
   2669     }
   2670 }
   2671 
   2672 /*
   2673  * soc_internal_send_int
   2674  *
   2675  *    Checks if any interrupt is pending, and if so, sends an interrupt
   2676  *    over the PLI socket.
   2677  */
   2678 
   2679 void
   2680 soc_internal_send_int(pcid_info_t *pcid_info)
   2681 {
   2682     int rv;
   2683 
   2684     if (pcid_info->opt_rpc_error) {
   2685         return;
   2686     }
   2687     if (PCIM(pcid_info, CMIC_IRQ_MASK) & PCIM(pcid_info, CMIC_IRQ_STAT)) {
   2688         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2689                     (BSL_META("Send interrupt: msk 0x%x stat 0x%x\n"),
   2690                      PCIM(pcid_info, CMIC_IRQ_MASK), PCIM(pcid_info, CMIC_IRQ_STAT)));
   2691         rv = send_interrupt(pcid_info->client->intsock, 0);
   2692         if (rv < 0) {
   2693             LOG_ERROR(BSL_LS_SOC_COMMON,
   2694                       (BSL_META("RPC error: soc_internal_send_int failed. \n")));
   2695             pcid_info->opt_rpc_error = 1;
   2696         }
   2697     } else {
   2698         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2699                     (BSL_META("Interrupt masked: msk 0x%x stat 0x%x\n"),
   2700                      PCIM(pcid_info, CMIC_IRQ_MASK), PCIM(pcid_info, CMIC_IRQ_STAT)));
   2701     }
   2702 }
   2703 
   2704 #ifdef BCM_CMICM_SUPPORT
   2705 void
   2706 soc_internal_cmicm_send_int(pcid_info_t *pcid_info, uint32 reg)
   2707 {
   2708     int rv;
   2709 
   2710     if (pcid_info->opt_rpc_error) {
   2711         return;
   2712     }
   2713     switch (reg) {
   2714     case CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET:
   2715         if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET) & 
   2716             pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET)) {
   2717             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2718                         (BSL_META("Send interrupt: msk0 0x%x stat0 0x%x\n"),
   2719                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET), 
   2720                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET)));
   2721             rv = send_interrupt(pcid_info->client->intsock, 0);
   2722             if (rv < 0) {
   2723                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2724                           (BSL_META("RPC error: soc_internal_send_int failed. \n")));
   2725                 pcid_info->opt_rpc_error = 1;
   2726             }
   2727         } else {
   2728             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2729                         (BSL_META("Interrupt masked: msk0 0x%x stat0 0x%x\n"),
   2730                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET), 
   2731                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET)));
   2732         }
   2733         break;
   2734     case CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET:
   2735         if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET) & 
   2736             pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET)) {
   2737             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2738                         (BSL_META("Send interrupt: msk1 0x%x stat1 0x%x\n"),
   2739                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET), 
   2740                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET)));
   2741             rv = send_interrupt(pcid_info->client->intsock, 0);
   2742             if (rv < 0) {
   2743                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2744                           (BSL_META("RPC error: soc_internal_send_int failed. \n")));
   2745                 pcid_info->opt_rpc_error = 1;
   2746             }
   2747         } else {
   2748             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2749                         (BSL_META("Interrupt masked: msk1 0x%x stat1 0x%x\n"),
   2750                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET), 
   2751                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET)));
   2752         }
   2753         break;
   2754     case CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET:
   2755         if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET) & 
   2756             pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET)) {
   2757             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2758                         (BSL_META("Send interrupt: msk2 0x%x stat2 0x%x\n"),
   2759                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET), 
   2760                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET)));
   2761             rv = send_interrupt(pcid_info->client->intsock, 0);
   2762             if (rv < 0) {
   2763                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2764                           (BSL_META("RPC error: soc_internal_send_int failed. \n")));
   2765                 pcid_info->opt_rpc_error = 1;
   2766             }
   2767         } else {
   2768             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2769                         (BSL_META("Interrupt masked: msk2 0x%x stat2 0x%x\n"),
   2770                          pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET), 
   2771                          pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET)));
   2772         }
   2773     }
   2774 }
   2775 #endif
   2776 
   2777 static const soc_reg_t ing_mpls_tpid_regs[] = {
   2778     ING_MPLS_TPID_0r, ING_MPLS_TPID_1r,
   2779     ING_MPLS_TPID_2r, ING_MPLS_TPID_3r
   2780 };
   2781 static const soc_reg_t ing_outer_tpid_regs[] = {
   2782     ING_OUTER_TPID_0r, ING_OUTER_TPID_1r,
   2783     ING_OUTER_TPID_2r, ING_OUTER_TPID_3r
   2784 };
   2785 static const soc_reg_t egr_outer_tpid_regs[] = {
   2786     EGR_OUTER_TPID_0r, EGR_OUTER_TPID_1r,
   2787     EGR_OUTER_TPID_2r, EGR_OUTER_TPID_3r
   2788 };
   2789 
   2790 int
   2791 soc_internal_extended_write_reg(pcid_info_t *pcid_info,
   2792                                 soc_block_t block, int acc_type,
   2793                                 uint32 address, uint32 *data)
   2794 {
   2795     soc_regaddrinfo_t ainfo;
   2796     int rv;
   2797 
   2798     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   2799         /* To fill in */
   2800 
   2801         soc_regaddrinfo_extended_get(pcid_info->unit, &ainfo, block, acc_type,
   2802                                      address);
   2803     
   2804         if (!ainfo.valid || ainfo.reg < 0) {
   2805             LOG_ERROR(BSL_LS_SOC_COMMON,
   2806                       (BSL_META("Attempt to write to unknown S-channel "
   2807                                 "block %d acc_type %d address 0x%x\n"),
   2808                        block, acc_type, address));
   2809             return SOC_E_NOT_FOUND;
   2810         } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
   2811             SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags &
   2812                    SOC_REG_FLAG_RO) {
   2813             LOG_ERROR(BSL_LS_SOC_COMMON,
   2814                       (BSL_META("Attempt to write to read-only S-channel address 0x%x\n"),
   2815                        address));
   2816         }
   2817 
   2818         switch (ainfo.reg) {
   2819         case EGR_OUTER_TPIDr:
   2820             ainfo.reg = egr_outer_tpid_regs[(address >> 8) & 0x3];
   2821             ainfo.idx = -1;
   2822             break;
   2823         case ING_OUTER_TPIDr:
   2824             ainfo.reg = ing_outer_tpid_regs[(address >> 8) & 0x3];
   2825             ainfo.idx = -1;
   2826             break;
   2827         case ING_MPLS_TPIDr:
   2828             ainfo.reg = ing_mpls_tpid_regs[(address >> 8) & 0x3];
   2829             ainfo.idx = -1;
   2830             break;
   2831         }
   2832 
   2833 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
   2834         if (soc_feature(pcid_info->unit, soc_feature_logical_port_num)) {
   2835             soc_info_t *si;
   2836             int phy_port, num_phy_ports = SOC_MAX_NUM_PORTS;
   2837             int blk;
   2838             int field_len;
   2839 
   2840             si = &SOC_INFO(pcid_info->unit);
   2841             switch (ainfo.reg) {
   2842             case EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr:
   2843                 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg,
   2844                                              data[0], PHYSICAL_PORT_NUMBERf);
   2845                 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg,
   2846                                                  PHYSICAL_PORT_NUMBERf);
   2847 
   2848                 if (SOC_MEM_IS_VALID(pcid_info->unit, ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm))  {
   2849                     num_phy_ports = soc_mem_index_count(pcid_info->unit, ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm);
   2850                 }
   2851 
   2852                 if ((phy_port != (1 << field_len) - 1) &&
   2853                     (phy_port < num_phy_ports)){
   2854                     si->port_p2l_mapping[phy_port] = ainfo.port;
   2855                     si->port_l2p_mapping[ainfo.port] = phy_port;
   2856                     blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port);
   2857                     si->port_type[ainfo.port] =
   2858                         SOC_BLOCK_INFO(pcid_info->unit, blk).type;
   2859                     if (ainfo.port > si->port.max) {
   2860                         si->port.max = ainfo.port;
   2861                     }
   2862                 }
   2863                 break;
   2864             case MMU_TO_PHY_PORT_MAPPINGr:
   2865                 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg,
   2866                                              data[0], PHY_PORTf);
   2867                 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg,
   2868                                                  PHY_PORTf);
   2869                 if (phy_port != (1 << field_len) - 1) {
   2870                     si->port_p2m_mapping[phy_port] = ainfo.idx;
   2871                     /*    coverity[negative_returns : FALSE]    */
   2872                     si->port_m2p_mapping[ainfo.idx] = phy_port;
   2873                 }
   2874                 break;
   2875             case EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr:
   2876                 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg,
   2877                                              data[0], PHYSICAL_PORT_NUMBERf);
   2878                 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg,
   2879                                                  PHYSICAL_PORT_NUMBERf);
   2880                 if (phy_port != (1 << field_len) - 1) {
   2881                     si->port_p2l_mapping[phy_port] = ainfo.port;
   2882                     si->port_l2p_mapping[ainfo.port] = phy_port;
   2883                     blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port);
   2884                     si->port_type[ainfo.port] =
   2885                         SOC_BLOCK_INFO(pcid_info->unit, blk).type;
   2886                     if (ainfo.port > si->port.max) {
   2887                         si->port.max = ainfo.port;
   2888                     }
   2889                 }
   2890                 break;
   2891             case MMU_PORT_TO_PHY_PORT_MAPPINGr:
   2892                 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg,
   2893                                              data[0], PHY_PORTf);
   2894                 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg,
   2895                                                  PHY_PORTf);
   2896                 if (phy_port != (1 << field_len) - 1) {
   2897                     si->port_p2m_mapping[phy_port] = address & 0xff;
   2898                     /*    coverity[negative_returns : FALSE]    */
   2899                     si->port_m2p_mapping[address & 0xff] = phy_port;
   2900                 }
   2901                 break;
   2902             case MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPINGr:
   2903                 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg,
   2904                                              data[0], PHY_PORT_NUMf);
   2905                 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg,
   2906                                                  PHY_PORT_NUMf);
   2907                 if (phy_port != (1 << field_len) - 1) {
   2908                     si->port_p2m_mapping[phy_port] = address & 0xff;
   2909                     /*    coverity[negative_returns : FALSE]    */
   2910                     si->port_m2p_mapping[address & 0xff] = phy_port;
   2911                 }
   2912                 break;
   2913             default:
   2914                 break;
   2915             }
   2916         }
   2917 #endif /* BCM_TRIDENT_SUPPORT */
   2918         if (ainfo.acc_type < 0xff) {
   2919             block |= acc_type << 24;
   2920         }
   2921         if (ainfo.reg == Q_SCHED_RQE_SNAPSHOTr) {
   2922             *data &= ~0x1;  /* always assume flush is finished. */
   2923         }
   2924         rv = soc_datum_reg_write(pcid_info, ainfo, block, address, data);
   2925 
   2926         return rv;
   2927     } else {
   2928         return soc_internal_write_reg(pcid_info, address, data);
   2929     }
   2930 }
   2931 
   2932 int
   2933 soc_internal_extended_read_reg(pcid_info_t *pcid_info,
   2934                                soc_block_t block, int acc_type,
   2935                                uint32 address, uint32 *data)
   2936 {
   2937     soc_regaddrinfo_t ainfo;
   2938     int rv;
   2939 
   2940     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   2941         /* To fill in */
   2942 
   2943         soc_regaddrinfo_extended_get(pcid_info->unit, &ainfo, block, acc_type,
   2944                                      address);
   2945 
   2946         if (!ainfo.valid || ainfo.reg < 0) {
   2947             LOG_ERROR(BSL_LS_SOC_COMMON,
   2948                       (BSL_META("Attempt to read from unknown register S-channel "
   2949                                 "block %d acc_type %d address 0x%x\n"),
   2950                        block, acc_type, address));
   2951             return SOC_E_NOT_FOUND;
   2952         } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
   2953             SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & SOC_REG_FLAG_WO) {
   2954             LOG_ERROR(BSL_LS_SOC_COMMON,
   2955                       (BSL_META("Attempt to read from write-only S-channel address 0x%x\n"),
   2956                        address));
   2957         }
   2958 
   2959         switch (ainfo.reg) {
   2960         case EGR_OUTER_TPIDr:
   2961             if (SOC_IS_GREYHOUND(pcid_info->unit) || 
   2962                 SOC_IS_HURRICANE3(pcid_info->unit) ||
   2963                 SOC_IS_GREYHOUND2(pcid_info->unit)){
   2964                 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0x120013];
   2965             } else {
   2966                 ainfo.reg = egr_outer_tpid_regs[(address >> 8) & 0x3];
   2967             }
   2968             ainfo.idx = -1;
   2969             break;
   2970         case ING_OUTER_TPIDr:
   2971             if (SOC_IS_TRIUMPH3(pcid_info->unit)) {
   2972                 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa0016];
   2973             } else if (SOC_IS_KATANA2(pcid_info->unit)) {
   2974                 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa0017];
   2975             } else if (SOC_IS_HURRICANE2(pcid_info->unit) || 
   2976                 SOC_IS_GREYHOUND(pcid_info->unit) ||
   2977                 SOC_IS_HURRICANE3(pcid_info->unit) ||
   2978                 SOC_IS_GREYHOUND2(pcid_info->unit)) {
   2979                 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa000d];
   2980             } else {
   2981                 ainfo.reg = ing_outer_tpid_regs[(address >> 8) & 0x3];
   2982             }
   2983             ainfo.idx = -1;
   2984             break;
   2985         case ING_MPLS_TPIDr:
   2986             ainfo.reg = ing_mpls_tpid_regs[(address >> 8) & 0x3];
   2987             ainfo.idx = -1;
   2988             break;
   2989         }
   2990         if (ainfo.acc_type < 0xff) {
   2991             block |= acc_type << 24;
   2992         }
   2993         rv = soc_datum_reg_read(pcid_info, ainfo, block, address, data);
   2994         if (SOC_E_NOT_FOUND == rv) {
   2995             /*
   2996              * The register is not in the hash table, so it has not been
   2997              * written before.  Provide a default value.
   2998              */
   2999             if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) &&
   3000                 (ainfo.valid && ainfo.reg >= 0)) {
   3001                 /*This macro handle both 64 and above_64 regs*/
   3002                 SOC_REG_ABOVE_64_RST_VAL_GET(pcid_info->unit, ainfo.reg, data);
   3003             } else {
   3004                 data[0] = 0xffffffff;
   3005                 data[1] = 0xffffffff;
   3006             }
   3007             rv = SOC_E_NONE;
   3008         }
   3009 
   3010         if (SOC_E_NONE == rv) {
   3011             if (SOC_IS_TRIDENT3X(pcid_info->unit)) {
   3012                 static soc_field_t f_iter, field_done[] = {
   3013                                                   DONEf,
   3014                                                   INVALIDf
   3015                                                   };
   3016                 for(f_iter = 0; field_done[f_iter] != INVALIDf; f_iter++) {
   3017                     if (soc_reg_field_valid(pcid_info->unit, ainfo.reg,
   3018                                             field_done[f_iter])) {
   3019                         soc_reg_field_set(pcid_info->unit, ainfo.reg,
   3020                                           data, field_done[f_iter], 1);
   3021                     }
   3022                 }
   3023             } else if (SOC_IS_TOMAHAWK2(pcid_info->unit)) {
   3024                 soc_field_t f_iter;
   3025                 soc_field_t field_done[] = {DONEf, INVALIDf};
   3026                 for(f_iter = 0; field_done[f_iter] != INVALIDf; f_iter++) {
   3027                     if (soc_reg_field_valid(pcid_info->unit, ainfo.reg,
   3028                                             field_done[f_iter])) {
   3029                         soc_reg_field_set(pcid_info->unit, ainfo.reg,
   3030                                           data, field_done[f_iter], 1);
   3031                     }
   3032                 }
   3033             } else if (SOC_IS_TRIUMPH3(pcid_info->unit)) {
   3034                 /* ING/EGR/ISM_HW_RESET_CONTROL */
   3035                 if (((address == 0x2010200) && (block == 1)) ||
   3036                     ((address == 0x2010100) && (block == 2))) {
   3037                     data[0] |= (1 << 20);
   3038                 }
   3039                 if ((address == 0xfe000f00) && (block == 16)) {
   3040                     data[0] |= (1 << 31);
   3041                 }
   3042                 if ((address == 0x2000100) && (block == 3)) {
   3043                     data[0] |= 0x2;
   3044                 } 
   3045                 if ((address == 0xfe000200) && (block == 16)) {
   3046                     data[0] |= 0x10; /* L2 ageing complete */
   3047                 }
   3048                 if ((address == 0x5a000100) && (block == 3)) {
   3049                     data[0] |= 2; /* LLS init done */
   3050                 }
   3051             } else if (SOC_IS_TD2_TT2(pcid_info->unit)) {
   3052                 switch (ainfo.reg) {
   3053                 case ING_HW_RESET_CONTROL_2r:
   3054                 case ING_HW_RESET_CONTROL_2_Xr:
   3055                 case ING_HW_RESET_CONTROL_2_Yr:
   3056                     if(SOC_IS_TD2P_TT2P(pcid_info->unit)
   3057                        || SOC_IS_APACHE(pcid_info->unit)) {
   3058                         data[0] |= (1 << 22);
   3059                     }
   3060                     else {
   3061                         data[0] |= (1 << 21);
   3062                     }
   3063                     break;
   3064                 case EGR_HW_RESET_CONTROL_1r:
   3065                 case EGR_HW_RESET_CONTROL_1_Xr:
   3066                 case EGR_HW_RESET_CONTROL_1_Yr:
   3067                     data[0] |= (1 << 18);
   3068                     break;
   3069                 
   3070                 case TOP_TSC_AFE_PLL_STATUSr:
   3071                     data[0] = 0xffffffff;
   3072                     break;
   3073                 default:
   3074                     break;
   3075                 }
   3076             }
   3077         }
   3078         return rv;
   3079     } else {
   3080         return soc_internal_read_reg(pcid_info, address, data);
   3081     }
   3082 }
   3083 
   3084 int
   3085 _soc_internal_extended_write_mem(pcid_info_t *pcid_info, soc_mem_t mem,
   3086                                  soc_block_t block, int acc_type,
   3087                                  uint32 address, uint32 *data)
   3088 {
   3089     soc_mem_t       alt_mem;
   3090     uint32          offset, phy_port, field_len;
   3091     uint8           alt_acc_type;
   3092     int             blk;
   3093     soc_info_t      *si;
   3094 
   3095     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3096         if (mem != INVALIDm) {
   3097             alt_mem = INVALIDm;
   3098             switch(mem) {
   3099 #ifdef BCM_XGS_SWITCH_SUPPORT
   3100             case L3_ENTRY_IPV4_UNICASTm:
   3101             case L3_ENTRY_IPV4_MULTICASTm:
   3102             case L3_ENTRY_IPV6_UNICASTm:
   3103             case L3_ENTRY_IPV6_MULTICASTm:
   3104                 return soc_internal_l3x2_write(pcid_info, mem, address, data);
   3105 #ifdef BCM_TOMAHAWK_SUPPORT
   3106             case EXACT_MATCH_2m:
   3107             case EXACT_MATCH_4m:
   3108                 return soc_internal_exact_match_write(pcid_info, mem, address,
   3109                                                       data);
   3110 #endif /* BCM_TOMAHAWK_SUPPORT */
   3111             case VLAN_MACm:
   3112                 alt_mem = VLAN_XLATEm;
   3113                 break;
   3114 #endif
   3115             default:
   3116                 break;
   3117             }
   3118             if (alt_mem != INVALIDm) {
   3119                 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base;
   3120                 mem = alt_mem;
   3121                 address = soc_mem_addr_get(pcid_info->unit, mem, 0, block, offset,
   3122                                            &alt_acc_type);
   3123                 acc_type = alt_acc_type;
   3124             }
   3125             if (mem == EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm) {
   3126                 /* Update port mapping. */
   3127                 si = &SOC_INFO(pcid_info->unit);
   3128                 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base;
   3129                 soc_mem_field_get(pcid_info->unit, mem, data, DATAf, &phy_port);
   3130                 field_len = soc_mem_field_length(pcid_info->unit, mem, DATAf);
   3131                 if (phy_port != (1 << field_len) - 1) {
   3132                     si->port_p2l_mapping[phy_port] = offset;
   3133                     si->port_l2p_mapping[offset] = phy_port;
   3134                     blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port);
   3135                     si->port_type[offset] =
   3136                         SOC_BLOCK_INFO(pcid_info->unit, blk).type;
   3137                     if (offset > si->port.max) {
   3138                         si->port.max = offset;
   3139                     }
   3140                 }
   3141             }
   3142             if (soc_mem_is_aggr(pcid_info->unit, mem)) {
   3143                 return soc_internal_extended_write_aggrmem(pcid_info, block,
   3144                                                            acc_type, address,
   3145                                                            data);
   3146             }
   3147         }
   3148         if (acc_type >= 0) {
   3149             block |= acc_type << 24;
   3150         }
   3151         return soc_datum_mem_write(pcid_info, block, address, data);
   3152     } else {
   3153         return soc_internal_write_mem(pcid_info, address, data);
   3154     }
   3155 }
   3156 
   3157 int
   3158 _soc_internal_extended_read_mem(pcid_info_t *pcid_info, soc_mem_t mem,
   3159                                 soc_block_t block, int acc_type,
   3160                                 uint32 address, uint32 *data)
   3161 {
   3162     int             i, rv;
   3163     soc_mem_t       alt_mem;
   3164     uint32          offset;
   3165     uint8           alt_acc_type;
   3166 
   3167     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3168         if (mem != INVALIDm) {
   3169             alt_mem = INVALIDm;
   3170             switch(mem) {
   3171 #ifdef BCM_XGS_SWITCH_SUPPORT
   3172             case L3_ENTRY_IPV4_UNICASTm:
   3173             case L3_ENTRY_IPV4_MULTICASTm:
   3174             case L3_ENTRY_IPV6_UNICASTm:
   3175             case L3_ENTRY_IPV6_MULTICASTm:
   3176                 return soc_internal_l3x2_read(pcid_info, mem, address, data);
   3177 #ifdef BCM_TOMAHAWK_SUPPORT
   3178             case EXACT_MATCH_2m:
   3179             case EXACT_MATCH_4m:
   3180                 return soc_internal_exact_match_read(pcid_info, mem, address,
   3181                                                      data);
   3182 #endif /* BCM_TOMAHAWK_SUPPORT */
   3183             case VLAN_MACm:
   3184                 alt_mem = VLAN_XLATEm;
   3185                 break;
   3186 #endif
   3187             default:
   3188                 break;
   3189             }
   3190             if (alt_mem != INVALIDm) {
   3191                 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base;
   3192                 mem = alt_mem;
   3193                 address = soc_mem_addr_get(pcid_info->unit, mem, 0, block, offset,
   3194                                            &alt_acc_type);
   3195                 acc_type = alt_acc_type;
   3196             }
   3197             if  (soc_mem_is_aggr(pcid_info->unit, mem)) {
   3198                 return soc_internal_extended_read_aggrmem(pcid_info, block, 
   3199                                                           acc_type, address,
   3200                                                           data);
   3201             }
   3202         }
   3203         if (acc_type >= 0) {
   3204             block |= acc_type << 24;
   3205         }
   3206         rv = soc_datum_mem_read(pcid_info, block, address, data);
   3207         if (SOC_E_NOT_FOUND == rv) {
   3208             /* Return null entry value if recognized, otherwise 0xf's */
   3209             if (mem != INVALIDm) {
   3210                 if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) {
   3211                     memcpy(data,               /* Memory */
   3212                            soc_mem_entry_null(pcid_info->unit, mem),
   3213                            4 * soc_mem_entry_words(pcid_info->unit, mem));
   3214                 } else {
   3215                     memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem));
   3216                 }
   3217             } else {                   /* Other */
   3218                 for (i = 0; i < SOC_MAX_MEM_WORDS; i++) {
   3219                     data[i] = 0xffffffff;
   3220                 }
   3221             }
   3222             rv = SOC_E_NONE;
   3223         }
   3224 
   3225         return rv;
   3226     } else {
   3227         return soc_internal_read_mem(pcid_info, address, data);
   3228     }
   3229 }
   3230 
   3231 int
   3232 soc_internal_extended_write_mem(pcid_info_t *pcid_info,
   3233                                 soc_block_t block, int acc_type,
   3234                                 uint32 address, uint32 *data)
   3235 {
   3236     soc_mem_t       mem;
   3237 
   3238     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3239         if ((pcid_info->regmem_cb) 
   3240             && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, data, 
   3241                                      ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) {
   3242             return 0;
   3243         }
   3244     
   3245         mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, address);
   3246         return _soc_internal_extended_write_mem(pcid_info, mem, block,
   3247                                                 acc_type, address, data);
   3248     } else {
   3249         return soc_internal_write_mem(pcid_info, address, data);
   3250     }
   3251 }
   3252 
   3253 int
   3254 soc_internal_extended_read_mem(pcid_info_t *pcid_info,
   3255                                soc_block_t block, int acc_type,
   3256                                uint32 address, uint32 *data)
   3257 {
   3258     soc_mem_t       mem;
   3259 
   3260     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3261         /* To fill in */
   3262         if ((pcid_info->regmem_cb) 
   3263             && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, data, 
   3264                                      ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) {
   3265             return 0;
   3266         }
   3267 
   3268         mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, address);
   3269         return _soc_internal_extended_read_mem(pcid_info, mem, block,
   3270                                                acc_type, address, data);
   3271     } else {
   3272         return soc_internal_read_mem(pcid_info, address, data);
   3273     }
   3274 }
   3275 
   3276 int
   3277 soc_internal_extended_read_aggrmem(pcid_info_t *pcid_info,
   3278                                    soc_block_t block, int acc_type,
   3279                                    uint32 addr, uint32 *data)
   3280 {
   3281     uint32      ent[SOC_MAX_MEM_WORDS];
   3282     uint32      fv[SOC_MAX_MEM_WORDS];
   3283     soc_mem_t   *m = NULL;
   3284     int         index, i;
   3285     int         offset;
   3286     int         adj_offset = 0;
   3287     int         f;
   3288     int         nfield;
   3289     int         pck_factor;
   3290     soc_mem_t   mem;
   3291     soc_mem_info_t *amemp;
   3292     soc_mem_info_t *memp;
   3293     soc_field_info_t *fieldp;
   3294     soc_field_info_t *asflds; /* array for aggregate mem sorted fields */
   3295     soc_field_info_t *sflds; /* array for partial mem sorted fields */
   3296     uint8       acc_type_member;
   3297     uint32      member_addr;
   3298     int         unit = pcid_info->unit;
   3299 
   3300     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3301         /* To fill in */
   3302         mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, addr);
   3303     
   3304         if (mem == INVALIDm) {
   3305             return SOC_E_PARAM;
   3306         }
   3307     
   3308         offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0x3ffffff;
   3309         index = 0;
   3310         memset(data, 0, 4 * soc_mem_entry_words(unit, mem));
   3311         do {
   3312             m = SOC_MEM_AGGR(unit, index);
   3313             if (m[0] == mem) {
   3314                 /* Fetch the individual components */
   3315                 nfield = 1;
   3316                 for(i = 1; m[i] != INVALIDm; i++) {
   3317                     /*
   3318                     ** Multiple entries compacted into one entry like HIT
   3319                     ** requires special handling.
   3320                     */
   3321                     amemp = &SOC_MEM_INFO(unit, mem);
   3322                     if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) {
   3323                         continue;
   3324                     }
   3325                     pck_factor = (soc_mem_index_max(unit, mem) /
   3326                                   soc_mem_index_max(unit, m[i]));
   3327                     assert(pck_factor != 0);
   3328                     adj_offset = offset / pck_factor;
   3329                     member_addr =
   3330                         soc_mem_addr_get(unit, m[i], 0,
   3331                                          SOC_MEM_BLOCK_ANY(unit, m[i]),
   3332                                          adj_offset, &acc_type_member);
   3333                     soc_internal_extended_read_mem(pcid_info, block,
   3334                                                    acc_type_member,
   3335                                                    member_addr, ent);
   3336     
   3337                     /* Iterate thru' the fields in this View */
   3338                     memp = &SOC_MEM_INFO(unit, m[i]);
   3339                     if (pck_factor == 1) {
   3340                         for (f = memp->nFields - 1; f >= 0; f--) {
   3341                             fieldp = &memp->fields[f];
   3342                             soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
   3343                             if (soc_mem_field_valid(unit, mem, fieldp->field) &&
   3344                                 soc_mem_field_valid(unit, m[i], fieldp->field)) {
   3345                                 soc_mem_field_set(unit, mem, data, fieldp->field,
   3346                                                   fv);
   3347                             }
   3348                             nfield++;
   3349                         }
   3350                     } else if (memp->nFields == pck_factor) {
   3351                         asflds = sal_alloc(amemp->nFields *
   3352                                            sizeof(soc_field_info_t),
   3353                                            "aggregate fields");
   3354                         if (!asflds) {
   3355                             return SOC_E_INTERNAL;
   3356                         }
   3357                         sflds = sal_alloc(memp->nFields *
   3358                                           sizeof(soc_field_info_t),
   3359                                           "mem fields");
   3360                         if (!sflds) {
   3361                             sal_free(asflds);
   3362                             return SOC_E_INTERNAL;
   3363                         }
   3364                         _soc_internal_fields_sort(amemp->fields,
   3365                                                   amemp->nFields, asflds);
   3366                         _soc_internal_fields_sort(memp->fields, memp->nFields,
   3367                                                   sflds);
   3368                         fieldp = &sflds[memp->nFields -
   3369                                         (offset % pck_factor) - 1];
   3370                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
   3371                         fieldp = &asflds[(amemp->nFields - nfield)];
   3372                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
   3373                         nfield++;
   3374                         sal_free(asflds);
   3375                         sal_free(sflds);
   3376                     } else if (memp->nFields == (pck_factor * 2)) {
   3377                         asflds = sal_alloc(amemp->nFields *
   3378                                            sizeof(soc_field_info_t),
   3379                                            "aggregate fields");
   3380                         if (!asflds) {
   3381                             return SOC_E_INTERNAL;
   3382                         }
   3383                         sflds = sal_alloc(memp->nFields *
   3384                                           sizeof(soc_field_info_t),
   3385                                           "mem fields");
   3386                         if (!sflds) {
   3387                             sal_free(asflds);
   3388                             return SOC_E_INTERNAL;
   3389                         }
   3390                         _soc_internal_fields_sort(amemp->fields,
   3391                                                   amemp->nFields, asflds);
   3392                         _soc_internal_fields_sort(memp->fields, memp->nFields,
   3393                                                   sflds);
   3394                         fieldp = &sflds[memp->nFields -
   3395                                         (offset % pck_factor) - 1];
   3396                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
   3397                         fieldp = &asflds[(amemp->nFields - nfield)];
   3398                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
   3399                         nfield++;
   3400 
   3401                         fieldp = &sflds[memp->nFields - pck_factor - 
   3402                                     (offset % pck_factor) - 1];
   3403                         soc_mem_field_get(unit, m[i], ent, fieldp->field, fv);
   3404                         fieldp = &asflds[(amemp->nFields - nfield)];
   3405                         soc_mem_field_set(unit, mem, data, fieldp->field, fv);
   3406                         nfield++;
   3407                         sal_free(asflds);
   3408                         sal_free(sflds);
   3409                     } else {
   3410                         LOG_ERROR(BSL_LS_SOC_COMMON,
   3411                                   (BSL_META_U(unit,
   3412                                               "soc_internal_extended_read_aggrmem:mem=%d"
   3413                                               "Unable to handle Aggregate Mem component %d\n"),
   3414                                    mem, m[i]));
   3415                     }
   3416                 }
   3417                 return(0);
   3418             }
   3419             index++;
   3420         } while (m[0] != INVALIDm);
   3421     
   3422         /* Not found in the table of aggregate memories */
   3423         LOG_ERROR(BSL_LS_SOC_COMMON,
   3424                   (BSL_META_U(unit,
   3425                               "soc_internal_extended_read_aggrmem:mem=%d missing in Aggregate Mem List\n"),
   3426                    mem));
   3427         if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) {
   3428             memcpy(data,               /* Memory */
   3429                    soc_mem_entry_null(pcid_info->unit, mem),
   3430                    4 * soc_mem_entry_words(pcid_info->unit, mem));
   3431         } else {
   3432             memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem));
   3433         }
   3434 
   3435         return 0;
   3436     } else {
   3437         return soc_internal_read_aggrmem(pcid_info, addr, data);
   3438     }
   3439 }
   3440 
   3441 int
   3442 soc_internal_extended_write_aggrmem(pcid_info_t *pcid_info,
   3443                                     soc_block_t block, int acc_type,
   3444                                     uint32 addr, uint32 *data)
   3445 {
   3446     uint32      ent[SOC_MAX_MEM_WORDS];
   3447     uint32      fv[SOC_MAX_MEM_WORDS];
   3448     soc_mem_t   *m = NULL;
   3449     int         index, i;
   3450     int         offset;
   3451     int         adj_offset = 0;
   3452     int         f;
   3453     int         nfield;
   3454     int         pck_factor;
   3455     soc_mem_t   mem;
   3456     soc_mem_info_t *amemp;
   3457     soc_mem_info_t *memp;
   3458     soc_field_info_t *fieldp;
   3459     soc_field_info_t *asflds; /* array for aggregate mem sorted fields */
   3460     soc_field_info_t *sflds; /* array for partial mem sorted fields */
   3461     uint8       acc_type_member;
   3462     uint32      member_addr;
   3463     int         unit = pcid_info->unit;
   3464         
   3465     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3466         /* To fill in */
   3467 
   3468         mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, addr);
   3469     
   3470         if (mem == INVALIDm)
   3471         {
   3472             return SOC_E_PARAM;
   3473         }
   3474     
   3475         memset(ent, 0, 4 * soc_mem_entry_words(unit, mem));
   3476         offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0x3ffffff;
   3477         index = 0;
   3478         do {
   3479             m = SOC_MEM_AGGR(unit, index);
   3480             if (m[0] == mem) {
   3481                 /* Fetch the individual components */
   3482                 nfield = 1;
   3483                 for(i = 1; m[i] != INVALIDm; i++) {
   3484                     /*
   3485                     ** Multiple entries compacted into one entry like HIT
   3486                     ** requires special handling.
   3487                     */
   3488                     amemp = &SOC_MEM_INFO(unit, mem);
   3489                     if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) {
   3490                         continue;
   3491                     }
   3492                     pck_factor = (soc_mem_index_max(unit, mem) /
   3493                                   soc_mem_index_max(unit, m[i]));
   3494                     assert(pck_factor != 0);
   3495                     adj_offset = offset / pck_factor;
   3496                     memp = &SOC_MEM_INFO(unit, m[i]);
   3497                     member_addr =
   3498                         soc_mem_addr_get(unit, m[i], 0,
   3499                                          SOC_MEM_BLOCK_ANY(unit, m[i]),
   3500                                          adj_offset, &acc_type_member);
   3501 
   3502                     /* Iterate thru' the fields in this View */
   3503                     if (pck_factor == 1) {
   3504                         for (f = memp->nFields - 1; f >= 0; f--) {
   3505                             fieldp = &memp->fields[f];
   3506                             if (soc_mem_field_valid(unit, mem, fieldp->field) &&
   3507                                 soc_mem_field_valid(unit, m[i], fieldp->field)) {
   3508                                 soc_mem_field_get(unit, mem, data, fieldp->field,
   3509                                                   fv);
   3510                                 soc_mem_field_set(unit, m[i], ent, fieldp->field,
   3511                                                   fv);
   3512                             }
   3513                             nfield++;
   3514                         }
   3515                     } else if (memp->nFields == pck_factor) {
   3516                         asflds = sal_alloc(amemp->nFields *
   3517                                            sizeof(soc_field_info_t),
   3518                                            "aggregate fields");
   3519                         if (!asflds) {
   3520                             return SOC_E_INTERNAL;
   3521                         }
   3522                         sflds = sal_alloc(memp->nFields *
   3523                                           sizeof(soc_field_info_t),
   3524                                           "mem fields");
   3525                         if (!sflds) {
   3526                             sal_free(asflds);
   3527                             return SOC_E_INTERNAL;
   3528                         }
   3529                         _soc_internal_fields_sort(amemp->fields,
   3530                                                   amemp->nFields, asflds);
   3531                         _soc_internal_fields_sort(memp->fields, memp->nFields,
   3532                                                   sflds);
   3533                         fieldp = &asflds[amemp->nFields - nfield];
   3534                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
   3535                         soc_internal_extended_read_mem(pcid_info, block,
   3536                                                        acc_type_member,
   3537                                                        member_addr, ent);
   3538                         fieldp = &sflds[memp->nFields -
   3539                                         (offset % pck_factor) - 1];
   3540                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   3541                         nfield++;
   3542                         sal_free(asflds);
   3543                         sal_free(sflds);
   3544                     } else if (memp->nFields == (pck_factor * 2)) {
   3545                         asflds = sal_alloc(amemp->nFields *
   3546                                            sizeof(soc_field_info_t),
   3547                                            "aggregate fields");
   3548                         if (!asflds) {
   3549                             return SOC_E_INTERNAL;
   3550                         }
   3551                         sflds = sal_alloc(memp->nFields *
   3552                                           sizeof(soc_field_info_t),
   3553                                           "mem fields");
   3554                         if (!sflds) {
   3555                             sal_free(asflds);
   3556                             return SOC_E_INTERNAL;
   3557                         }
   3558                         _soc_internal_fields_sort(amemp->fields,
   3559                                                   amemp->nFields, asflds);
   3560                         _soc_internal_fields_sort(memp->fields, memp->nFields,
   3561                                                   sflds);
   3562                         fieldp = &asflds[amemp->nFields - nfield];
   3563                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
   3564                         soc_internal_extended_read_mem(pcid_info, block,
   3565                                                        acc_type_member,
   3566                                                        member_addr, ent);
   3567                         fieldp = &sflds[memp->nFields -
   3568                                         (offset % pck_factor) - 1];
   3569                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   3570                         nfield++;
   3571 
   3572                         fieldp = &asflds[(amemp->nFields - nfield)];
   3573                         soc_mem_field_get(unit, mem, data, fieldp->field, fv);
   3574                         fieldp = &sflds[memp->nFields - pck_factor -
   3575                                         (offset % pck_factor) - 1];
   3576                         soc_mem_field_set(unit, m[i], ent, fieldp->field, fv);
   3577                         nfield++;
   3578                         sal_free(asflds);
   3579                         sal_free(sflds);
   3580                     } else {
   3581                         LOG_ERROR(BSL_LS_SOC_COMMON,
   3582                                   (BSL_META_U(unit,
   3583                                               "soc_internal_extended_write_mem:mem=%d"
   3584                                               "Unable to handle Aggregate Mem component %d\n"),
   3585                                    mem, m[i]));
   3586                     }
   3587                     soc_internal_extended_write_mem
   3588                         (pcid_info, block, acc_type_member, member_addr, ent);
   3589                 }
   3590                 return(0);
   3591             }
   3592             index++;
   3593         } while (m[0] != INVALIDm);
   3594     
   3595         /* Not found in the table of aggregate memories */
   3596         LOG_ERROR(BSL_LS_SOC_COMMON,
   3597                   (BSL_META_U(unit,
   3598                               "soc_internal_write_aggrmem:mem=%d missing in Aggregate Mem List\n"),
   3599                    mem));        
   3600         return 0;
   3601     } else {
   3602         return soc_internal_write_aggrmem(pcid_info, addr, data);
   3603     }
   3604 }
   3605 
   3606 int
   3607 soc_internal_extended_read_bytes(pcid_info_t *pcid_info,
   3608                                  soc_block_t block, int acc_type,
   3609                                  uint32 address, uint8 *data, int len)
   3610 {
   3611     uint32  temp[SOC_MAX_MEM_WORDS];
   3612     int     rv;
   3613 
   3614     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3615         /* To fill in */
   3616     
   3617         if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) {
   3618             return 1;
   3619         }
   3620     
   3621         /* reading bytes is supported only for bcmsim */
   3622         if ((pcid_info->regmem_cb) && 
   3623             (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, 
   3624                                   (uint32 *) data, (len * 8)) == 0)) {
   3625             return 0;
   3626         }
   3627     
   3628         /* if no registered call-back, default to read_mem */
   3629         rv = soc_internal_extended_read_mem(pcid_info, block, acc_type, address, 
   3630                                             temp);
   3631         if (!rv) {
   3632             sal_memcpy(data, temp, len);
   3633         }
   3634         return rv;
   3635     } else {
   3636         return soc_internal_read_bytes(pcid_info, address, data, len);
   3637     }
   3638 }
   3639 
   3640 int
   3641 soc_internal_extended_write_bytes(pcid_info_t *pcid_info,
   3642                                   soc_block_t block, int acc_type,
   3643                                   uint32 address, uint8 *data, int len)
   3644 {
   3645     uint32  temp[SOC_MAX_MEM_WORDS];
   3646     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3647         /* To fill in */
   3648 
   3649         if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) {
   3650             return 1;
   3651         }
   3652         
   3653         /* writing bytes is supported only for bcmsim */
   3654         if ((pcid_info->regmem_cb) && 
   3655             (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, 
   3656                                   (uint32 *)data, (len * 8)) == 0)) {
   3657             return 0;
   3658         }
   3659         
   3660         /* if no registered call-back, default to write_mem */
   3661         sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32)));
   3662         sal_memcpy(temp, data, len);
   3663         return soc_internal_extended_write_mem(pcid_info, block, acc_type, 
   3664                                                address, temp);
   3665     } else {
   3666         return soc_internal_write_bytes(pcid_info, address, data, len);
   3667     }
   3668 }
   3669 
   3670 int
   3671 soc_internal_extended_write_mem_index(pcid_info_t *pcid_info, soc_mem_t mem,
   3672                                       int index, uint32 *data)
   3673 {
   3674     int             block_info_index;
   3675     int             block;
   3676     uint8           acc_type;
   3677     uint32          addr;
   3678 
   3679     block_info_index = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem);
   3680     block = SOC_BLOCK2SCH(pcid_info->unit, block_info_index);
   3681     addr = soc_mem_addr_get(pcid_info->unit, mem, 0, block_info_index, index,
   3682                             &acc_type);
   3683 
   3684     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {    
   3685         if (pcid_info->regmem_cb) {
   3686             if (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, addr,
   3687                                      data, SOC_MAX_MEM_WORDS * 4 * 8) == 0) {
   3688                 return 0;
   3689             }
   3690         }
   3691         return _soc_internal_extended_write_mem(pcid_info, mem, block,
   3692                                                 acc_type, addr, data);
   3693     } else {
   3694         return soc_internal_write_mem(pcid_info, addr, data);
   3695     }
   3696 }
   3697 
   3698 int
   3699 soc_internal_extended_read_mem_index(pcid_info_t *pcid_info, soc_mem_t mem,
   3700                                      int index, uint32 *data)
   3701 {
   3702     int             block_info_index;
   3703     int             block;
   3704     uint8           acc_type;
   3705     uint32          addr;
   3706 
   3707     block_info_index = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem);
   3708     block = SOC_BLOCK2SCH(pcid_info->unit, block_info_index);
   3709     addr = soc_mem_addr_get(pcid_info->unit, mem, 0, block_info_index, index,
   3710                             &acc_type);
   3711 
   3712     if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) {
   3713         if (pcid_info->regmem_cb != NULL) {
   3714             if (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, addr,
   3715                                      data, SOC_MAX_MEM_WORDS * 4 * 8) == 0) {
   3716                 return 0;
   3717             }
   3718         }
   3719         return _soc_internal_extended_read_mem(pcid_info, mem, block,
   3720                                                acc_type, addr, data);
   3721     } else {
   3722         return soc_internal_read_mem(pcid_info, addr, data);
   3723     }
   3724 }