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

vlan.c (91808B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        vlan.c
      8  *      
      9  * Provides:
     10  *      soc_internal_vlan_xlate_hash
     11  *      soc_internal_vlan_xlate_dual_banks
     12  *      soc_internal_vlan_xlate_entry_read
     13  *      soc_internal_vlan_xlate_entry_write
     14  *      soc_internal_vlan_xlate_entry_ins
     15  *      soc_internal_vlan_xlate_entry_del
     16  *      soc_internal_vlan_xlate_entry_lkup
     17  *      soc_internal_egr_vlan_xlate_hash
     18  *      soc_internal_egr_vlan_xlate_dual_banks
     19  *      soc_internal_egr_vlan_xlate_entry_read
     20  *      soc_internal_egr_vlan_xlate_entry_write
     21  *      soc_internal_egr_vlan_xlate_entry_ins
     22  *      soc_internal_egr_vlan_xlate_entry_del
     23  *      soc_internal_egr_vlan_xlate_entry_lkup
     24  *      
     25  * Requires:    
     26  */
     27 
     28 #include <shared/bsl.h>
     29 
     30 #include <soc/mem.h>
     31 #include <soc/hash.h>
     32 #include <soc/drv.h>
     33 #include <soc/l2x.h>
     34 #ifdef BCM_TRIDENT2_SUPPORT
     35 #include <soc/trident2.h>
     36 #endif
     37 
     38 #include "pcid.h"
     39 #include "mem.h"
     40 #include "cmicsim.h"
     41 
     42 #ifdef BCM_TRX_SUPPORT
     43 
     44 int
     45 soc_internal_vlan_xlate_hash(pcid_info_t * pcid_info, 
     46                              vlan_xlate_entry_t *entry, int dual)
     47 {
     48     uint32          tmp_hs[SOC_MAX_MEM_WORDS];
     49     int             hash_sel;
     50     uint8           at, key[8];
     51     int             index, bits;
     52     soc_block_t     blk; 
     53 
     54     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     55                 (BSL_META("VLAN_XLATE hash\n")));
     56 
     57     soc_internal_extended_read_reg(pcid_info, blk, at,
     58           soc_reg_addr_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr,
     59                            REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE,
     60                            &blk, &at),
     61           tmp_hs);
     62     if (dual) {
     63         hash_sel = soc_reg_field_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr,
     64                                      tmp_hs[0], HASH_SELECT_Bf);
     65     } else {
     66         hash_sel = soc_reg_field_get(pcid_info->unit, VLAN_XLATE_HASH_CONTROLr,
     67                                      tmp_hs[0], HASH_SELECT_Af);
     68     }
     69 
     70     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     71                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
     72 
     73 #ifdef BCM_TRIDENT2_SUPPORT
     74     if (SOC_IS_TD2_TT2(pcid_info->unit)) {
     75         bits = soc_td2_vlan_xlate_base_entry_to_key(pcid_info->unit, dual, entry,
     76                                                     key);
     77         index = soc_td2_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, entry,
     78                                         key);
     79     } else
     80 #endif /* BCM_TRIDENT2_SUPPORT */
     81     {
     82         bits = soc_tr_vlan_xlate_base_entry_to_key(pcid_info->unit, entry,
     83                                                    key);
     84         index = soc_tr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits, entry,
     85                                        key);
     86     }
     87 
     88     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     89                 (BSL_META("index %d\n"), index));
     90 
     91     return index;
     92 }
     93 
     94 void
     95 soc_internal_vlan_xlate_dual_banks(pcid_info_t *pcid_info, uint8 banks,
     96                                    int *dual, int *slot_min, int *slot_max)
     97 {
     98     /* Dual hash always enabled for VLAN_XLATE */
     99     *dual = TRUE;
    100 
    101     if (*dual) {
    102         switch (banks) {
    103         case 0:
    104             return; /* Nothing to do here */
    105         case 1:
    106             *slot_min = 4;
    107             *slot_max = 7;
    108             break;
    109         case 2:
    110             *slot_min = 0;
    111             *slot_max = 3;
    112             break;
    113         default:
    114             *slot_min = 0;
    115             *slot_max = -1;
    116             break;
    117         }
    118     }
    119 
    120     return;
    121 }
    122 
    123 int
    124 soc_internal_vlan_xlate_entry_read(pcid_info_t * pcid_info, uint32 addr,
    125                                    vlan_xlate_entry_t *entry)
    126 {
    127     int index = (addr & 0x3fff);
    128     int             blk;             
    129     soc_block_t     sblk;
    130     uint8           at;
    131     uint32          address;
    132 
    133     blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, VLAN_XLATEm);
    134     sblk = SOC_BLOCK2SCH(pcid_info->unit, blk);
    135 
    136     address = soc_mem_addr_get(pcid_info->unit, VLAN_XLATEm, 0, 
    137                                blk, index, &at);
    138 
    139     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    140                 (BSL_META("vlan_xlate read addr=0x%x\n"), addr));
    141 
    142     soc_internal_extended_read_mem(pcid_info, sblk, 0, address, 
    143                                    (uint32 *) entry);
    144 
    145     return 0;
    146 }
    147 
    148 int
    149 soc_internal_vlan_xlate_entry_write(pcid_info_t * pcid_info, uint32 addr,
    150                                     vlan_xlate_entry_t *entry)
    151 {
    152     int index = (addr & 0x3fff);
    153     int             blk;             
    154     soc_block_t     sblk;
    155     uint8           at;
    156     uint32          address;
    157 
    158     blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, VLAN_XLATEm);
    159     sblk = SOC_BLOCK2SCH(pcid_info->unit, blk);
    160     address = soc_mem_addr_get(pcid_info->unit, VLAN_XLATEm, 0, 
    161                                blk, index, &at);
    162 
    163     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    164                 (BSL_META("vlan_xlate write addr=0x%x\n"), addr));
    165 
    166     soc_internal_extended_write_mem(pcid_info, sblk, 0, address, 
    167                                     (uint32 *) entry);
    168 
    169     return 0;
    170 }
    171 
    172 int
    173 soc_internal_vlan_xlate_entry_ins(pcid_info_t *pcid_info, uint8 banks,
    174                                   vlan_xlate_entry_t *entry, uint32 *result)
    175 {
    176     uint32          tmp[SOC_MAX_MEM_WORDS];
    177     int             index = 0, bucket, slot, free_index;
    178     int             slot_min = 0, slot_max = 7, dual = FALSE;
    179     int             unit = pcid_info->unit;
    180     schan_genresp_t *genresp = (schan_genresp_t *)result;
    181     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    182     int             blk;
    183     soc_block_t     sblk;
    184     uint8           acc_type;
    185     uint32          addr;
    186 
    187     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    188                 (BSL_META_U(unit,
    189                             "VLAN_XLAEGT Insert\n")));
    190 
    191     bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE);
    192 
    193     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    194                 (BSL_META_U(unit,
    195                             "bucket %d\n"), bucket));
    196 
    197     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    198         soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual, &slot_min,
    199                                            &slot_max);
    200     }
    201     blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm);
    202     sblk = SOC_BLOCK2SCH(unit, blk);
    203 
    204     /* Check if it should overwrite an existing entry */
    205     free_index = -1;
    206     for (slot = slot_min; slot <= slot_max; slot++) {
    207         if (dual && (slot == 4)) {
    208             bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE);
    209         }
    210         index = bucket * 8 + slot;
    211         addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type);
    212         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    213         if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) {
    214             if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) {
    215                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    216                             (BSL_META_U(unit,
    217                                         "write sblk %d acc_type %d bucket %d, "
    218                                         "slot %d, index %d\n"),
    219                              sblk, acc_type, index / 8, index % 8, index));
    220 
    221                 /* Overwrite the existing entry */
    222                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    223                                                 addr, (uint32 *)entry);
    224 
    225                 /* Copy old entry immediately after response word */
    226                 memcpy(&result[1], tmp,
    227                        soc_mem_entry_bytes(unit, VLAN_XLATEm));
    228 
    229                 result[0] = 0;
    230                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    231                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    232                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    233                     genresp_v2->index = index;
    234                 } else {
    235                     genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    236                     genresp->index = index;
    237                 }
    238                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    239 
    240                 return 0;
    241             }
    242         } else {
    243             if (free_index == -1) {
    244                 free_index = index;
    245             }
    246         }
    247     }
    248 
    249     /* Find first unused slot in bucket */
    250     if (free_index != -1) {
    251         index = free_index;
    252         addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type);
    253 
    254         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    255                     (BSL_META_U(unit,
    256                                 "write sblk %d acc_type %d bucket %d, slot %d, "
    257                                 "index %d\n"),
    258                      sblk, acc_type, index / 8, index % 8, index));
    259 
    260         /* Write the new entry */
    261         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    262                                         (uint32 *)entry);
    263 
    264         result[0] = 0;
    265         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    266             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    267             genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    268             genresp_v2->index = index;
    269         } else {
    270             genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    271             genresp->index = index;
    272         }
    273         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    274 
    275         return 0;
    276     }
    277 
    278     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    279                 (BSL_META_U(unit,
    280                             "Bucket full\n")));
    281 
    282     result[0] = 0;
    283     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    284         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    285         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
    286     } else {
    287         genresp->type = SCHAN_GEN_RESP_TYPE_FULL;
    288     }
    289     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    290 
    291     return 0;
    292 }
    293 
    294 int
    295 soc_internal_vlan_xlate_entry_del(pcid_info_t * pcid_info, uint8 banks,
    296                                   vlan_xlate_entry_t *entry, uint32 *result)
    297 {
    298     uint32          tmp[SOC_MAX_MEM_WORDS];
    299     int             index = 0, bucket, slot;
    300     int             slot_min = 0, slot_max = 7, dual = FALSE;
    301     int             unit = pcid_info->unit;
    302     schan_genresp_t *genresp = (schan_genresp_t *)result;
    303     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    304     int             blk;
    305     soc_block_t     sblk;
    306     uint8           acc_type;
    307     uint32          addr;
    308 
    309     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    310                 (BSL_META_U(unit,
    311                             "VLAN_XLATE Delete\n")));
    312 
    313     bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE);
    314 
    315     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    316                 (BSL_META_U(unit,
    317                             "bucket %d\n"), bucket));
    318 
    319     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    320         soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual,
    321                                            &slot_min, &slot_max);
    322     }
    323     blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm);
    324     sblk = SOC_BLOCK2SCH(unit, blk);
    325 
    326     /* Check if entry exists */
    327     for (slot = slot_min; slot <= slot_max; slot++) {
    328         if (dual && (slot == 4)) {
    329             bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE);
    330         }
    331         index = bucket * 8 + slot;
    332         addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type);
    333         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    334         if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) {
    335             if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) {
    336                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    337                             (BSL_META_U(unit,
    338                                         "found sblk %d acc_type %d bucket %d, "
    339                                         "slot %d, index %d\n"),
    340                              sblk, acc_type, bucket, slot, index));
    341 
    342                 /* Copy entry immediately after response word */
    343                 memcpy(&result[1], tmp,
    344                        soc_mem_entry_bytes(unit, VLAN_XLATEm));
    345 
    346                 /* Invalidate entry */
    347                 soc_mem_field32_set(unit, VLAN_XLATEm, tmp, VALIDf, 0);
    348                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    349                                                 addr, tmp);
    350 
    351                 result[0] = 0;
    352                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    353                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    354                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
    355                     genresp_v2->index = index;
    356                 } else {
    357                     genresp->type = SCHAN_GEN_RESP_TYPE_DELETED;
    358                     genresp->index = index;
    359                 }
    360                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    361 
    362                 return 0;
    363             }
    364         }
    365     }
    366 
    367     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    368                 (BSL_META_U(unit,
    369                             "soc_internal_vlan_xlate_entry_del: Not found\n")));
    370 
    371     result[0] = 0;
    372     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    373         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    374         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    375     } else {
    376         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    377     }
    378     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    379     return 0;
    380 }
    381 
    382 int
    383 soc_internal_vlan_xlate_entry_lkup(pcid_info_t * pcid_info, uint8 banks,
    384                                    vlan_xlate_entry_t *entry, uint32 *result)
    385 {
    386     uint32          tmp[SOC_MAX_MEM_WORDS];
    387     int             index = 0, bucket, slot;
    388     int             slot_min = 0, slot_max = 7, dual = FALSE;
    389     int             unit = pcid_info->unit;
    390     schan_genresp_t *genresp = (schan_genresp_t *)result;
    391     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    392     int             blk;
    393     soc_block_t     sblk;
    394     uint8           acc_type;
    395     uint32          addr;
    396 
    397     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    398                 (BSL_META_U(unit,
    399                             "VLAN_XLATE Lookup\n")));
    400 
    401     bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, FALSE);
    402 
    403     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    404                 (BSL_META_U(unit,
    405                             "bucket %d\n"), bucket));
    406 
    407     if (soc_feature(unit, soc_feature_dual_hash)) {
    408         soc_internal_vlan_xlate_dual_banks(pcid_info, banks, &dual,
    409                                            &slot_min, &slot_max);
    410     }
    411     blk = SOC_MEM_BLOCK_ANY(unit, VLAN_XLATEm);
    412     sblk = SOC_BLOCK2SCH(unit, blk);
    413 
    414     /* Check if entry exists */
    415     for (slot = slot_min; slot <= slot_max; slot++) {
    416         if (dual && (slot == 4)) {
    417             bucket = soc_internal_vlan_xlate_hash(pcid_info, entry, TRUE);
    418         }
    419         index = bucket * 8 + slot;
    420         addr = soc_mem_addr_get(unit, VLAN_XLATEm, 0, blk, index, &acc_type);
    421         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    422         if (soc_mem_field32_get(unit, VLAN_XLATEm, tmp, VALIDf)) {
    423             if (soc_mem_compare_key(unit, VLAN_XLATEm, entry, tmp) == 0) {
    424                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    425                             (BSL_META_U(unit,
    426                                         "found sblk %d acc_type %d bucket %d, "
    427                                         "slot %d, index %d\n"),
    428                              sblk, acc_type, bucket, slot, index));
    429 
    430                 /* Copy entry immediately after response word */
    431                 memcpy(&result[1], tmp,
    432                        soc_mem_entry_bytes(unit, VLAN_XLATEm));
    433 
    434                 result[0] = 0;
    435                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    436                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    437                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
    438                     genresp_v2->index = index;
    439                 } else {
    440                     genresp->type = SCHAN_GEN_RESP_TYPE_FOUND;
    441                     genresp->index = index;
    442                 }
    443 
    444                 return 0;
    445             }
    446         }
    447     }
    448 
    449     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    450                 (BSL_META_U(unit,
    451                             "soc_internal_vlan_xlate_entry_lkup: Not found\n")));
    452 
    453     result[0] = 0;
    454     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    455         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    456         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    457     } else {
    458         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    459     }
    460     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    461     return 0;
    462 }
    463 
    464 int
    465 soc_internal_egr_vlan_xlate_hash(pcid_info_t * pcid_info,
    466                                  egr_vlan_xlate_entry_t *entry, int dual)
    467 {
    468     uint32          tmp_hs[SOC_MAX_MEM_WORDS];
    469     int             hash_sel;
    470     uint8           at, key[8];
    471     int             index, bits;
    472     soc_block_t     blk;
    473 
    474     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    475                 (BSL_META("EGR_VLAN_XLATE hash\n")));
    476 
    477     soc_internal_extended_read_reg(pcid_info, blk, at,
    478           soc_reg_addr_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr,
    479                            REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE,
    480                            &blk, &at),
    481           tmp_hs);
    482     if (dual) {
    483         hash_sel = soc_reg_field_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr,
    484                                      tmp_hs[0], HASH_SELECT_Bf);
    485     } else {
    486         hash_sel = soc_reg_field_get(pcid_info->unit, EGR_VLAN_XLATE_HASH_CONTROLr,
    487                                      tmp_hs[0], HASH_SELECT_Af);
    488     }
    489 
    490     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    491                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
    492 
    493 #ifdef BCM_TRIDENT2_SUPPORT
    494     if (SOC_IS_TD2_TT2(pcid_info->unit)) {
    495         bits = soc_td2_egr_vlan_xlate_base_entry_to_key(pcid_info->unit, dual,
    496                                                         entry, key);
    497         index = soc_td2_egr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits,
    498                                            entry, key);
    499     } else
    500 #endif /* BCM_TRIDENT2_SUPPORT */
    501     {
    502         bits = soc_tr_egr_vlan_xlate_base_entry_to_key(pcid_info->unit,
    503                                                        entry, key);
    504         index = soc_tr_egr_vlan_xlate_hash(pcid_info->unit, hash_sel, bits,
    505                                            entry, key);
    506     }
    507 
    508     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    509                 (BSL_META("index %d\n"), index));
    510 
    511     return index;
    512 }
    513 
    514 void
    515 soc_internal_egr_vlan_xlate_dual_banks(pcid_info_t *pcid_info, uint8 banks,
    516                                        int *dual, int *slot_min, int *slot_max)
    517 {
    518     /* Dual hash always enabled for EGR_VLAN_XLATE */
    519     *dual = TRUE;
    520 
    521     if (*dual) {
    522         switch (banks) {
    523         case 0:
    524             return; /* Nothing to do here */
    525         case 1:
    526             *slot_min = 4;
    527             *slot_max = 7;
    528             break;
    529         case 2:
    530             *slot_min = 0;
    531             *slot_max = 3;
    532             break;
    533         default:
    534             *slot_min = 0;
    535             *slot_max = -1;
    536             break;
    537         }
    538     }
    539 
    540     return;
    541 }
    542 
    543 int
    544 soc_internal_egr_vlan_xlate_entry_ins(pcid_info_t *pcid_info, uint8 banks,
    545                                       egr_vlan_xlate_entry_t *entry,
    546                                       uint32 *result)
    547 {
    548     uint32          tmp[SOC_MAX_MEM_WORDS];
    549     int             index = 0, bucket, slot, free_index;
    550     int             slot_min = 0, slot_max = 7, dual = FALSE;
    551     int             unit = pcid_info->unit;
    552     schan_genresp_t *genresp = (schan_genresp_t *)result;
    553     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    554     int             blk;
    555     soc_block_t     sblk;
    556     uint8           acc_type;
    557     uint32          addr;
    558 
    559     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    560                 (BSL_META_U(unit,
    561                             "EGR_VLAN_XLATE Insert\n")));
    562 
    563     bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE);
    564 
    565     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    566                 (BSL_META_U(unit,
    567                             "bucket %d\n"), bucket));
    568 
    569     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    570         soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual,
    571                                                &slot_min, &slot_max);
    572     }
    573     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm);
    574     sblk = SOC_BLOCK2SCH(unit, blk);
    575 
    576     /* Check if it should overwrite an existing entry */
    577     free_index = -1;
    578     for (slot = slot_min; slot <= slot_max; slot++) {
    579         if (dual && (slot == 4)) {
    580             bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE);
    581         }
    582         index = bucket * 8 + slot;
    583         addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index,
    584                                 &acc_type);
    585         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    586         if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) {
    587             if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) {
    588                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    589                             (BSL_META_U(unit,
    590                                         "write sblk %d acc_type %d bucket %d, "
    591                                         "slot %d, index %d\n"),
    592                              sblk, acc_type, index / 8, index % 8, index));
    593 
    594                 /* Overwrite the existing entry */
    595                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    596                                                 addr, (uint32 *)entry);
    597 
    598                 /* Copy old entry immediately after response word */
    599                 memcpy(&result[1], tmp,
    600                        soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm));
    601 
    602                 result[0] = 0;
    603                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    604                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    605                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    606                     genresp_v2->index = index;
    607                 } else {
    608                     genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    609                     genresp->index = index;
    610                 }
    611                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    612 
    613                 return 0;
    614             }
    615         } else {
    616             if (free_index == -1) {
    617                 free_index = index;
    618             }
    619         }
    620     }
    621 
    622     /* Find first unused slot in bucket */
    623     if (free_index != -1) {
    624         index = free_index;
    625         addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index,
    626                                 &acc_type);
    627 
    628         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    629                     (BSL_META_U(unit,
    630                                 "write sblk %d acc_type %d bucket %d, slot %d, "
    631                                 "index %d\n"),
    632                      sblk, acc_type, index / 8, index % 8, index));
    633 
    634         /* Write the new entry */
    635         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    636                                         (uint32 *)entry);
    637 
    638         result[0] = 0;
    639         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    640             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    641             genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    642             genresp_v2->index = index;
    643         } else {
    644             genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    645             genresp->index = index;
    646         }
    647         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    648 
    649         return 0;
    650     }
    651 
    652     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    653                 (BSL_META_U(unit,
    654                             "Bucket full\n")));
    655 
    656     result[0] = 0;
    657     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    658         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    659         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
    660     } else {
    661         genresp->type = SCHAN_GEN_RESP_TYPE_FULL;
    662     }
    663     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    664 
    665     return 0;
    666 }
    667 
    668 int
    669 soc_internal_egr_vlan_xlate_entry_del(pcid_info_t * pcid_info, uint8 banks,
    670                                       egr_vlan_xlate_entry_t *entry,
    671                                       uint32 *result)
    672 {
    673     uint32          tmp[SOC_MAX_MEM_WORDS];
    674     int             index = 0, bucket, slot;
    675     int             slot_min = 0, slot_max = 7, dual = FALSE;
    676     int             unit = pcid_info->unit;
    677     schan_genresp_t *genresp = (schan_genresp_t *)result;
    678     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    679     int             blk;
    680     soc_block_t     sblk;
    681     uint8           acc_type;
    682     uint32          addr;
    683 
    684     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    685                 (BSL_META_U(unit,
    686                             "EGR_VLAN_XLATE Delete\n")));
    687 
    688     bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE);
    689 
    690     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    691                 (BSL_META_U(unit,
    692                             "bucket %d\n"), bucket));
    693 
    694     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    695         soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual,
    696                                                &slot_min, &slot_max);
    697     }
    698     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm);
    699     sblk = SOC_BLOCK2SCH(unit, blk);
    700 
    701     /* Check if entry exists */
    702     for (slot = slot_min; slot <= slot_max; slot++) {
    703         if (dual && (slot == 4)) {
    704             bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE);
    705         }
    706         index = bucket * 8 + slot;
    707         addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index,
    708                                 &acc_type);
    709         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    710         if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) {
    711             if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) {
    712                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    713                             (BSL_META_U(unit,
    714                                         "found sblk %d acc_type %d bucket %d, "
    715                                         "slot %d, index %d\n"),
    716                              sblk, acc_type, bucket, slot, index));
    717 
    718                 /* Copy entry immediately after response word */
    719                 memcpy(&result[1], tmp,
    720                        soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm));
    721 
    722                 /* Invalidate entry */
    723                 soc_mem_field32_set(unit, EGR_VLAN_XLATEm, tmp, VALIDf, 0);
    724                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    725                                                 addr, tmp);
    726 
    727                 result[0] = 0;
    728                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    729                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    730                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
    731                     genresp_v2->index = index;
    732                 } else {
    733                     genresp->type = SCHAN_GEN_RESP_TYPE_DELETED;
    734                     genresp->index = index;
    735                 }
    736                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    737 
    738                 return 0;
    739             }
    740         }
    741     }
    742 
    743     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    744                 (BSL_META_U(unit,
    745                             "soc_internal_egr_vlan_xlate_entry_del: Not found\n")));
    746 
    747     result[0] = 0;
    748     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    749         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    750         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    751     } else {
    752         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    753     }
    754     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    755     return 0;
    756 }
    757 
    758 int
    759 soc_internal_egr_vlan_xlate_entry_lkup(pcid_info_t * pcid_info, uint8 banks,
    760                                        egr_vlan_xlate_entry_t *entry,
    761                                        uint32 *result)
    762 {
    763     uint32          tmp[SOC_MAX_MEM_WORDS];
    764     int             index = 0, bucket, slot;
    765     int             slot_min = 0, slot_max = 7, dual = FALSE;
    766     int             unit = pcid_info->unit;
    767     schan_genresp_t *genresp = (schan_genresp_t *)result;
    768     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    769     int             blk;
    770     soc_block_t     sblk;
    771     uint8           acc_type;
    772     uint32          addr;
    773 
    774     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    775                 (BSL_META_U(unit,
    776                             "EGR_VLAN_XLATE Lookup\n")));
    777 
    778     bucket = soc_internal_egr_vlan_xlate_hash(pcid_info, entry, FALSE);
    779 
    780     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    781                 (BSL_META_U(unit,
    782                             "bucket %d\n"), bucket));
    783 
    784     if (soc_feature(unit, soc_feature_dual_hash)) {
    785         soc_internal_egr_vlan_xlate_dual_banks(pcid_info, banks, &dual,
    786                                                &slot_min, &slot_max);
    787     }
    788     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VLAN_XLATEm);
    789     sblk = SOC_BLOCK2SCH(unit, blk);
    790 
    791     /* Check if entry exists */
    792     for (slot = slot_min; slot <= slot_max; slot++) {
    793         if (dual && (slot == 4)) {
    794             bucket =
    795                 soc_internal_egr_vlan_xlate_hash(pcid_info, entry, TRUE);
    796         }
    797         index = bucket * 8 + slot;
    798         addr = soc_mem_addr_get(unit, EGR_VLAN_XLATEm, 0, blk, index,
    799                                 &acc_type);
    800         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    801         if (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, tmp, VALIDf)) {
    802             if (soc_mem_compare_key(unit, EGR_VLAN_XLATEm, entry, tmp) == 0) {
    803                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    804                             (BSL_META_U(unit,
    805                                         "found sblk %d acc_type %d bucket %d, "
    806                                         "slot %d, index %d\n"),
    807                              sblk, acc_type, bucket, slot, index));
    808 
    809                 /* Copy entry immediately after response word */
    810                 memcpy(&result[1], tmp,
    811                        soc_mem_entry_bytes(unit, EGR_VLAN_XLATEm));
    812 
    813                 result[0] = 0;
    814                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    815                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    816                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
    817                     genresp_v2->index = index;
    818                 } else {
    819                     genresp->type = SCHAN_GEN_RESP_TYPE_FOUND;
    820                     genresp->index = index;
    821                 }
    822                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    823 
    824                 return 0;
    825             }
    826         }
    827     }
    828 
    829     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    830                 (BSL_META_U(unit,
    831                             "soc_internal_egr_vlan_xlate_entry_lkup: Not found\n")));
    832 
    833     result[0] = 0;
    834     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    835         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    836         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    837     } else {
    838         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    839     }
    840     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    841     return 0;
    842 }
    843 
    844 #ifdef BCM_TRIDENT2_SUPPORT
    845 int
    846 soc_internal_ing_vp_vlan_member_hash(pcid_info_t *pcid_info, void *entry,
    847                                      int dual)
    848 {
    849     soc_reg_t       reg;
    850     soc_field_t     field;
    851     uint32          tmp[SOC_MAX_MEM_WORDS];
    852     int             hash_sel;
    853     uint8           key[8];
    854     int             index, bits;
    855     soc_block_t     blk;
    856     uint8           acc_type;
    857     uint32          addr;
    858 
    859     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    860                 (BSL_META("ING_VP_VLAN_MEMBERSHIP hash\n")));
    861 
    862     reg = ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLr;
    863     field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af;
    864 
    865     addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0,
    866                             SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    867     soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp);
    868     hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field);
    869 
    870     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    871                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
    872 
    873     bits = soc_td2_ing_vp_vlan_member_base_entry_to_key(pcid_info->unit, dual,
    874                                                         entry, key);
    875     index = soc_td2_ing_vp_vlan_member_hash(pcid_info->unit, hash_sel, bits,
    876                                             entry, key);
    877 
    878     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    879                 (BSL_META("index %d\n"), index));
    880 
    881     return index;
    882 }
    883 
    884 void
    885 soc_internal_ing_vp_vlan_member_dual_banks(pcid_info_t *pcid_info, uint8 banks,
    886                                            int *dual, int *slot_min,
    887                                            int *slot_max)
    888 {
    889     /* Dual hash always enabled for ING_VP_VLAN_MEMBERSHIP */
    890     *dual = TRUE;
    891 
    892     if (*dual) {
    893         switch (banks) {
    894         case 0:
    895             return; /* Nothing to do here */
    896         case 1:
    897             *slot_min = 4;
    898             *slot_max = 7;
    899             break;
    900         case 2:
    901             *slot_min = 0;
    902             *slot_max = 3;
    903             break;
    904         default:
    905             *slot_min = 0;
    906             *slot_max = -1;
    907             break;
    908         }
    909     }
    910 
    911     return;
    912 }
    913 
    914 int
    915 soc_internal_ing_vp_vlan_member_ins(pcid_info_t *pcid_info, uint8 banks,
    916                                     void *entry, uint32 *result)
    917 {
    918     uint32          tmp[SOC_MAX_MEM_WORDS];
    919     int             index = 0, bucket, slot, free_index;
    920     int             slot_min = 0, slot_max = 7, dual = FALSE;
    921     int             unit = pcid_info->unit;
    922     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    923     int             blk;
    924     soc_block_t     sblk;
    925     uint8           acc_type;
    926     uint32          addr;
    927 
    928     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    929                 (BSL_META_U(unit,
    930                             "ING_VP_VLAN_MEMBERSHIP Insert\n")));
    931 
    932     bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE);
    933 
    934     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    935                 (BSL_META_U(unit,
    936                             "bucket %d\n"), bucket));
    937 
    938     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    939         soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
    940                                                    &slot_min, &slot_max);
    941     }
    942     blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm);
    943     sblk = SOC_BLOCK2SCH(unit, blk);
    944 
    945     /* Check if it should overwrite an existing entry */
    946     free_index = -1;
    947     for (slot = slot_min; slot <= slot_max; slot++) {
    948         if (dual && (slot == 4)) {
    949             bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry,
    950                                                           TRUE);
    951         }
    952         index = bucket * 8 + slot;
    953         addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index,
    954                                 &acc_type);
    955         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    956         if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
    957             if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp)
    958                 == 0) {
    959                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    960                             (BSL_META_U(unit,
    961                                         "write sblk %d acc_type %d bucket %d, "
    962                                         "slot %d, index %d\n"),
    963                              sblk, acc_type, index / 8, index % 8, index));
    964 
    965                 /* Overwrite the existing entry */
    966                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    967                                                 addr, entry);
    968 
    969                 /* Copy old entry immediately after response word */
    970                 memcpy(&result[1], tmp,
    971                        soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm));
    972 
    973                 result[0] = 0;
    974                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    975                 genresp_v2->index = index;
    976                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    977 
    978                 return 0;
    979             }
    980         } else {
    981             if (free_index == -1) {
    982                 free_index = index;
    983             }
    984         }
    985     }
    986 
    987     /* Find first unused slot in bucket */
    988     if (free_index != -1) {
    989         index = free_index;
    990         addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index,
    991                                 &acc_type);
    992 
    993         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    994                     (BSL_META_U(unit,
    995                                 "write sblk %d acc_type %d bucket %d, slot %d, "
    996                                 "index %d\n"),
    997                      sblk, acc_type, index / 8, index % 8, index));
    998 
    999         /* Write the new entry */
   1000         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
   1001                                         entry);
   1002 
   1003         result[0] = 0;
   1004         genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
   1005         genresp_v2->index = index;
   1006         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1007 
   1008         return 0;
   1009     }
   1010 
   1011     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1012                 (BSL_META_U(unit,
   1013                             "Bucket full\n")));
   1014 
   1015     result[0] = 0;
   1016     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
   1017     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1018 
   1019     return 0;
   1020 }
   1021 
   1022 int
   1023 soc_internal_ing_vp_vlan_member_del(pcid_info_t *pcid_info, uint8 banks,
   1024                                     void *entry, uint32 *result)
   1025 {
   1026     uint32          tmp[SOC_MAX_MEM_WORDS];
   1027     int             index = 0, bucket, slot;
   1028     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1029     int             unit = pcid_info->unit;
   1030     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1031     int             blk;
   1032     soc_block_t     sblk;
   1033     uint8           acc_type;
   1034     uint32          addr;
   1035 
   1036     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1037                 (BSL_META_U(unit,
   1038                             "ING_VP_VLAN_MEMBERSHIP Delete\n")));
   1039 
   1040     bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE);
   1041 
   1042     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1043                 (BSL_META_U(unit,
   1044                             "bucket %d\n"), bucket));
   1045 
   1046     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1047         soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
   1048                                                    &slot_min, &slot_max);
   1049     }
   1050     blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm);
   1051     sblk = SOC_BLOCK2SCH(unit, blk);
   1052 
   1053     /* Check if entry exists */
   1054     for (slot = slot_min; slot <= slot_max; slot++) {
   1055         if (dual && (slot == 4)) {
   1056             bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry,
   1057                                                           TRUE);
   1058         }
   1059         index = bucket * 8 + slot;
   1060         addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1061                                 &acc_type);
   1062         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1063         if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
   1064             if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp)
   1065                 == 0) {
   1066                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1067                             (BSL_META_U(unit,
   1068                                         "found sblk %d acc_type %d bucket %d, "
   1069                                         "slot %d, index %d\n"),
   1070                              sblk, acc_type, bucket, slot, index));
   1071 
   1072                 /* Copy entry immediately after response word */
   1073                 memcpy(&result[1], tmp,
   1074                        soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm));
   1075 
   1076                 /* Invalidate entry */
   1077                 soc_mem_field32_set(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf,
   1078                                     0);
   1079                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1080                                                 addr, tmp);
   1081 
   1082                 result[0] = 0;
   1083                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1084                 genresp_v2->index = index;
   1085                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1086 
   1087                 return 0;
   1088             }
   1089         }
   1090     }
   1091 
   1092     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1093                 (BSL_META_U(unit,
   1094                             "soc_internal_ing_vp_vlan_member_del: "
   1095                             "Not found\n")));
   1096 
   1097     result[0] = 0;
   1098     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1099     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1100     return 0;
   1101 }
   1102 
   1103 int
   1104 soc_internal_ing_vp_vlan_member_lkup(pcid_info_t *pcid_info, uint8 banks,
   1105                                      void *entry, uint32 *result)
   1106 {
   1107     uint32          tmp[SOC_MAX_MEM_WORDS];
   1108     int             index = 0, bucket, slot;
   1109     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1110     int             unit = pcid_info->unit;
   1111     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1112     int             blk;
   1113     soc_block_t     sblk;
   1114     uint8           acc_type;
   1115     uint32          addr;
   1116 
   1117     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1118                 (BSL_META_U(unit,
   1119                             "ING_VP_VLAN_MEMBERSHIP Lookup\n")));
   1120 
   1121     bucket = soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, FALSE);
   1122 
   1123     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1124                 (BSL_META_U(unit,
   1125                             "bucket %d\n"), bucket));
   1126 
   1127     if (soc_feature(unit, soc_feature_dual_hash)) {
   1128         soc_internal_ing_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
   1129                                                    &slot_min, &slot_max);
   1130     }
   1131     blk = SOC_MEM_BLOCK_ANY(unit, ING_VP_VLAN_MEMBERSHIPm);
   1132     sblk = SOC_BLOCK2SCH(unit, blk);
   1133 
   1134     /* Check if entry exists */
   1135     for (slot = slot_min; slot <= slot_max; slot++) {
   1136         if (dual && (slot == 4)) {
   1137             bucket =
   1138                 soc_internal_ing_vp_vlan_member_hash(pcid_info, entry, TRUE);
   1139         }
   1140         index = bucket * 8 + slot;
   1141         addr = soc_mem_addr_get(unit, ING_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1142                                 &acc_type);
   1143         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1144         if (soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
   1145             if (soc_mem_compare_key(unit, ING_VP_VLAN_MEMBERSHIPm, entry, tmp)
   1146                 == 0) {
   1147                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1148                             (BSL_META_U(unit,
   1149                                         "found sblk %d acc_type %d bucket %d, "
   1150                                         "slot %d, index %d\n"),
   1151                              sblk, acc_type, bucket, slot, index));
   1152 
   1153                 /* Copy entry immediately after response word */
   1154                 memcpy(&result[1], tmp,
   1155                        soc_mem_entry_bytes(unit, ING_VP_VLAN_MEMBERSHIPm));
   1156 
   1157                 result[0] = 0;
   1158                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1159                 genresp_v2->index = index;
   1160                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1161 
   1162                 return 0;
   1163             }
   1164         }
   1165     }
   1166 
   1167     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1168                 (BSL_META_U(unit,
   1169                             "soc_internal_ing_vp_vlan_member_lkup: Not found\n")));
   1170 
   1171     result[0] = 0;
   1172     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1173     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1174     return 0;
   1175 }
   1176 
   1177 int
   1178 soc_internal_egr_vp_vlan_member_hash(pcid_info_t *pcid_info, void *entry,
   1179                                      int dual)
   1180 {
   1181     soc_reg_t       reg;
   1182     soc_field_t     field;
   1183     uint32          tmp[SOC_MAX_MEM_WORDS];
   1184     int             hash_sel;
   1185     uint8           key[8];
   1186     int             index, bits;
   1187     soc_block_t     blk;
   1188     uint8           acc_type;
   1189     uint32          addr;
   1190 
   1191     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1192                 (BSL_META("EGR_VP_VLAN_MEMBERSHIP hash\n")));
   1193 
   1194     reg = EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLr;
   1195     field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af;
   1196 
   1197     addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0,
   1198                             SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
   1199     soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp);
   1200     hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field);
   1201 
   1202     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1203                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
   1204 
   1205     bits = soc_td2_egr_vp_vlan_member_base_entry_to_key(pcid_info->unit, dual,
   1206                                                         entry, key);
   1207     index = soc_td2_egr_vp_vlan_member_hash(pcid_info->unit, hash_sel, bits,
   1208                                             entry, key);
   1209 
   1210     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1211                 (BSL_META("index %d\n"), index));
   1212 
   1213     return index;
   1214 }
   1215 
   1216 void
   1217 soc_internal_egr_vp_vlan_member_dual_banks(pcid_info_t *pcid_info, uint8 banks,
   1218                                            int *dual, int *slot_min,
   1219                                            int *slot_max)
   1220 {
   1221     /* Dual hash always enabled for EGR_VP_VLAN_MEMBERSHIP */
   1222     *dual = TRUE;
   1223 
   1224     if (*dual) {
   1225         switch (banks) {
   1226         case 0:
   1227             return; /* Nothing to do here */
   1228         case 1:
   1229             *slot_min = 4;
   1230             *slot_max = 7;
   1231             break;
   1232         case 2:
   1233             *slot_min = 0;
   1234             *slot_max = 3;
   1235             break;
   1236         default:
   1237             *slot_min = 0;
   1238             *slot_max = -1;
   1239             break;
   1240         }
   1241     }
   1242 
   1243     return;
   1244 }
   1245 
   1246 int
   1247 soc_internal_egr_vp_vlan_member_ins(pcid_info_t *pcid_info, uint8 banks,
   1248                                     void *entry, uint32 *result)
   1249 {
   1250     uint32          tmp[SOC_MAX_MEM_WORDS];
   1251     int             index = 0, bucket, slot, free_index;
   1252     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1253     int             unit = pcid_info->unit;
   1254     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1255     int             blk;
   1256     soc_block_t     sblk;
   1257     uint8           acc_type;
   1258     uint32          addr;
   1259 
   1260     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1261                 (BSL_META_U(unit,
   1262                             "EGR_VP_VLAN_MEMBERSHIP Insert\n")));
   1263 
   1264     bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE);
   1265 
   1266     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1267                 (BSL_META_U(unit,
   1268                             "bucket %d\n"), bucket));
   1269 
   1270     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1271         soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
   1272                                                    &slot_min, &slot_max);
   1273     }
   1274     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm);
   1275     sblk = SOC_BLOCK2SCH(unit, blk);
   1276 
   1277     /* Check if it should overwrite an existing entry */
   1278     free_index = -1;
   1279     for (slot = slot_min; slot <= slot_max; slot++) {
   1280         if (dual && (slot == 4)) {
   1281             bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry,
   1282                                                           TRUE);
   1283         }
   1284         index = bucket * 8 + slot;
   1285         addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1286                                 &acc_type);
   1287         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1288         if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
   1289             if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp)
   1290                 == 0) {
   1291                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1292                             (BSL_META_U(unit,
   1293                                         "write sblk %d acc_type %d bucket %d, "
   1294                                         "slot %d, index %d\n"),
   1295                              sblk, acc_type, index / 8, index % 8, index));
   1296 
   1297                 /* Overwrite the existing entry */
   1298                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1299                                                 addr, entry);
   1300 
   1301                 /* Copy old entry immediately after response word */
   1302                 memcpy(&result[1], tmp,
   1303                        soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm));
   1304 
   1305                 result[0] = 0;
   1306                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
   1307                 genresp_v2->index = index;
   1308                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1309 
   1310                 return 0;
   1311             }
   1312         } else {
   1313             if (free_index == -1) {
   1314                 free_index = index;
   1315             }
   1316         }
   1317     }
   1318 
   1319     /* Find first unused slot in bucket */
   1320     if (free_index != -1) {
   1321         index = free_index;
   1322         addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1323                                 &acc_type);
   1324 
   1325         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1326                     (BSL_META_U(unit,
   1327                                 "write sblk %d acc_type %d bucket %d, slot %d, "
   1328                                 "index %d\n"),
   1329                      sblk, acc_type, index / 8, index % 8, index));
   1330 
   1331         /* Write the new entry */
   1332         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
   1333                                         entry);
   1334 
   1335         result[0] = 0;
   1336         genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
   1337         genresp_v2->index = index;
   1338         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1339 
   1340         return 0;
   1341     }
   1342 
   1343     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1344                 (BSL_META_U(unit,
   1345                             "Bucket full\n")));
   1346 
   1347     result[0] = 0;
   1348     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
   1349     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1350 
   1351     return 0;
   1352 }
   1353 
   1354 int
   1355 soc_internal_egr_vp_vlan_member_del(pcid_info_t *pcid_info, uint8 banks,
   1356                                     void *entry, uint32 *result)
   1357 {
   1358     uint32          tmp[SOC_MAX_MEM_WORDS];
   1359     int             index = 0, bucket, slot;
   1360     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1361     int             unit = pcid_info->unit;
   1362     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1363     int             blk;
   1364     soc_block_t     sblk;
   1365     uint8           acc_type;
   1366     uint32          addr;
   1367 
   1368     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1369                 (BSL_META_U(unit,
   1370                             "EGR_VP_VLAN_MEMBERSHIP Delete\n")));
   1371 
   1372     bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE);
   1373 
   1374     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1375                 (BSL_META_U(unit,
   1376                             "bucket %d\n"), bucket));
   1377 
   1378     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1379         soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
   1380                                                    &slot_min, &slot_max);
   1381     }
   1382     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm);
   1383     sblk = SOC_BLOCK2SCH(unit, blk);
   1384 
   1385     /* Check if entry exists */
   1386     for (slot = slot_min; slot <= slot_max; slot++) {
   1387         if (dual && (slot == 4)) {
   1388             bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry,
   1389                                                           TRUE);
   1390         }
   1391         index = bucket * 8 + slot;
   1392         addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1393                                 &acc_type);
   1394         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1395         if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
   1396             if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp)
   1397                 == 0) {
   1398                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1399                             (BSL_META_U(unit,
   1400                                         "found sblk %d acc_type %d bucket %d, "
   1401                                         "slot %d, index %d\n"),
   1402                              sblk, acc_type, bucket, slot, index));
   1403 
   1404                 /* Copy entry immediately after response word */
   1405                 memcpy(&result[1], tmp,
   1406                        soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm));
   1407 
   1408                 /* Invalidate entry */
   1409                 soc_mem_field32_set(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf,
   1410                                     0);
   1411                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1412                                                 addr, tmp);
   1413 
   1414                 result[0] = 0;
   1415                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1416                 genresp_v2->index = index;
   1417                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1418 
   1419                 return 0;
   1420             }
   1421         }
   1422     }
   1423 
   1424     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1425                 (BSL_META_U(unit,
   1426                             "soc_internal_egr_vp_vlan_member_del: "
   1427                             "Not found\n")));
   1428 
   1429     result[0] = 0;
   1430     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1431     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1432     return 0;
   1433 }
   1434 
   1435 int
   1436 soc_internal_egr_vp_vlan_member_lkup(pcid_info_t *pcid_info, uint8 banks,
   1437                                      void *entry, uint32 *result)
   1438 {
   1439     uint32          tmp[SOC_MAX_MEM_WORDS];
   1440     int             index = 0, bucket, slot;
   1441     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1442     int             unit = pcid_info->unit;
   1443     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1444     int             blk;
   1445     soc_block_t     sblk;
   1446     uint8           acc_type;
   1447     uint32          addr;
   1448 
   1449     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1450                 (BSL_META_U(unit,
   1451                             "EGR_VP_VLAN_MEMBERSHIP Lookup\n")));
   1452 
   1453     bucket = soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, FALSE);
   1454 
   1455     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1456                 (BSL_META_U(unit,
   1457                             "bucket %d\n"), bucket));
   1458 
   1459     if (soc_feature(unit, soc_feature_dual_hash)) {
   1460         soc_internal_egr_vp_vlan_member_dual_banks(pcid_info, banks, &dual,
   1461                                                    &slot_min, &slot_max);
   1462     }
   1463     blk = SOC_MEM_BLOCK_ANY(unit, EGR_VP_VLAN_MEMBERSHIPm);
   1464     sblk = SOC_BLOCK2SCH(unit, blk);
   1465 
   1466     /* Check if entry exists */
   1467     for (slot = slot_min; slot <= slot_max; slot++) {
   1468         if (dual && (slot == 4)) {
   1469             bucket =
   1470                 soc_internal_egr_vp_vlan_member_hash(pcid_info, entry, TRUE);
   1471         }
   1472         index = bucket * 8 + slot;
   1473         addr = soc_mem_addr_get(unit, EGR_VP_VLAN_MEMBERSHIPm, 0, blk, index,
   1474                                 &acc_type);
   1475         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1476         if (soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, tmp, VALIDf)) {
   1477             if (soc_mem_compare_key(unit, EGR_VP_VLAN_MEMBERSHIPm, entry, tmp)
   1478                 == 0) {
   1479                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1480                             (BSL_META_U(unit,
   1481                                         "found sblk %d acc_type %d bucket %d, "
   1482                                         "slot %d, index %d\n"),
   1483                              sblk, acc_type, bucket, slot, index));
   1484 
   1485                 /* Copy entry immediately after response word */
   1486                 memcpy(&result[1], tmp,
   1487                        soc_mem_entry_bytes(unit, EGR_VP_VLAN_MEMBERSHIPm));
   1488 
   1489                 result[0] = 0;
   1490                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1491                 genresp_v2->index = index;
   1492                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1493 
   1494                 return 0;
   1495             }
   1496         }
   1497     }
   1498 
   1499     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1500                 (BSL_META_U(unit,
   1501                             "soc_internal_egr_vp_vlan_member_lkup: Not found\n")));
   1502 
   1503     result[0] = 0;
   1504     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1505     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1506     return 0;
   1507 }
   1508 
   1509 int
   1510 soc_internal_ing_dnat_address_type_hash(pcid_info_t *pcid_info, void *entry,
   1511                                         int dual)
   1512 {
   1513     soc_reg_t       reg;
   1514     soc_field_t     field;
   1515     uint32          tmp[SOC_MAX_MEM_WORDS];
   1516     int             hash_sel;
   1517     uint8           key[8];
   1518     int             index, bits;
   1519     soc_block_t     blk;
   1520     uint8           acc_type;
   1521     uint32          addr;
   1522 
   1523     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1524                 (BSL_META("ING_DNAT_ADDRESS_TYPE hash\n")));
   1525 
   1526     reg = ING_DNAT_ADDRESS_TYPE_HASH_CONTROLr;
   1527     field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af;
   1528 
   1529     addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0,
   1530                             SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
   1531     soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp);
   1532     hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field);
   1533 
   1534     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1535                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
   1536 
   1537     bits = soc_td2_ing_dnat_address_type_base_entry_to_key(pcid_info->unit, dual,
   1538                                                            entry, key);
   1539     index = soc_td2_ing_dnat_address_type_hash(pcid_info->unit, hash_sel, bits,
   1540                                                entry, key);
   1541 
   1542     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1543                 (BSL_META("index %d\n"), index));
   1544 
   1545     return index;
   1546 }
   1547 
   1548 void
   1549 soc_internal_ing_dnat_address_type_dual_banks(pcid_info_t *pcid_info,
   1550                                               uint8 banks, int *dual,
   1551                                               int *slot_min, int *slot_max)
   1552 {
   1553     /* Dual hash always enabled for ING_DNAT_ADDRESS_TYPE */
   1554     *dual = TRUE;
   1555 
   1556     if (*dual) {
   1557         switch (banks) {
   1558         case 0:
   1559             return; /* Nothing to do here */
   1560         case 1:
   1561             *slot_min = 4;
   1562             *slot_max = 7;
   1563             break;
   1564         case 2:
   1565             *slot_min = 0;
   1566             *slot_max = 3;
   1567             break;
   1568         default:
   1569             *slot_min = 0;
   1570             *slot_max = -1;
   1571             break;
   1572         }
   1573     }
   1574 
   1575     return;
   1576 }
   1577 
   1578 int
   1579 soc_internal_ing_dnat_address_type_ins(pcid_info_t *pcid_info, uint8 banks,
   1580                                        void *entry, uint32 *result)
   1581 {
   1582     uint32          tmp[SOC_MAX_MEM_WORDS];
   1583     int             index = 0, bucket, slot, free_index;
   1584     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1585     int             unit = pcid_info->unit;
   1586     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1587     int             blk;
   1588     soc_block_t     sblk;
   1589     uint8           acc_type;
   1590     uint32          addr;
   1591 
   1592     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1593                 (BSL_META_U(unit,
   1594                             "ING_DNAT_ADDRESS_TYPE Insert\n")));
   1595 
   1596     bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE);
   1597 
   1598     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1599                 (BSL_META_U(unit,
   1600                             "bucket %d\n"), bucket));
   1601 
   1602     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1603         soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual,
   1604                                                       &slot_min, &slot_max);
   1605     }
   1606     blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm);
   1607     sblk = SOC_BLOCK2SCH(unit, blk);
   1608 
   1609     /* Check if it should overwrite an existing entry */
   1610     free_index = -1;
   1611     for (slot = slot_min; slot <= slot_max; slot++) {
   1612         if (dual && (slot == 4)) {
   1613             bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry,
   1614                                                              TRUE);
   1615         }
   1616         index = bucket * 8 + slot;
   1617         addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index,
   1618                                 &acc_type);
   1619         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1620         if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) {
   1621             if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp)
   1622                 == 0) {
   1623                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1624                             (BSL_META_U(unit,
   1625                                         "write sblk %d acc_type %d bucket %d, "
   1626                                         "slot %d, index %d\n"),
   1627                              sblk, acc_type, index / 8, index % 8, index));
   1628 
   1629                 /* Overwrite the existing entry */
   1630                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1631                                                 addr, entry);
   1632 
   1633                 /* Copy old entry immediately after response word */
   1634                 memcpy(&result[1], tmp,
   1635                        soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm));
   1636 
   1637                 result[0] = 0;
   1638                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
   1639                 genresp_v2->index = index;
   1640                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1641 
   1642                 return 0;
   1643             }
   1644         } else {
   1645             if (free_index == -1) {
   1646                 free_index = index;
   1647             }
   1648         }
   1649     }
   1650 
   1651     /* Find first unused slot in bucket */
   1652     if (free_index != -1) {
   1653         index = free_index;
   1654         addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index,
   1655                                 &acc_type);
   1656 
   1657         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1658                     (BSL_META_U(unit,
   1659                                 "write sblk %d acc_type %d bucket %d, slot %d, "
   1660                                 "index %d\n"),
   1661                      sblk, acc_type, index / 8, index % 8, index));
   1662 
   1663         /* Write the new entry */
   1664         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
   1665                                         entry);
   1666 
   1667         result[0] = 0;
   1668         genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
   1669         genresp_v2->index = index;
   1670         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1671 
   1672         return 0;
   1673     }
   1674 
   1675     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1676                 (BSL_META_U(unit,
   1677                             "Bucket full\n")));
   1678 
   1679     result[0] = 0;
   1680     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
   1681     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1682 
   1683     return 0;
   1684 }
   1685 
   1686 int
   1687 soc_internal_ing_dnat_address_type_del(pcid_info_t *pcid_info, uint8 banks,
   1688                                     void *entry, uint32 *result)
   1689 {
   1690     uint32          tmp[SOC_MAX_MEM_WORDS];
   1691     int             index = 0, bucket, slot;
   1692     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1693     int             unit = pcid_info->unit;
   1694     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1695     int             blk;
   1696     soc_block_t     sblk;
   1697     uint8           acc_type;
   1698     uint32          addr;
   1699 
   1700     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1701                 (BSL_META_U(unit,
   1702                             "ING_DNAT_ADDRESS_TYPE Delete\n")));
   1703 
   1704     bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE);
   1705 
   1706     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1707                 (BSL_META_U(unit,
   1708                             "bucket %d\n"), bucket));
   1709 
   1710     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1711         soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual,
   1712                                                       &slot_min, &slot_max);
   1713     }
   1714     blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm);
   1715     sblk = SOC_BLOCK2SCH(unit, blk);
   1716 
   1717     /* Check if entry exists */
   1718     for (slot = slot_min; slot <= slot_max; slot++) {
   1719         if (dual && (slot == 4)) {
   1720             bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry,
   1721                                                              TRUE);
   1722         }
   1723         index = bucket * 8 + slot;
   1724         addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index,
   1725                                 &acc_type);
   1726         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1727         if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) {
   1728             if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp)
   1729                 == 0) {
   1730                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1731                             (BSL_META_U(unit,
   1732                                         "found sblk %d acc_type %d bucket %d, "
   1733                                         "slot %d, index %d\n"),
   1734                              sblk, acc_type, bucket, slot, index));
   1735 
   1736                 /* Copy entry immediately after response word */
   1737                 memcpy(&result[1], tmp,
   1738                        soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm));
   1739 
   1740                 /* Invalidate entry */
   1741                 soc_mem_field32_set(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf,
   1742                                     0);
   1743                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1744                                                 addr, tmp);
   1745 
   1746                 result[0] = 0;
   1747                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1748                 genresp_v2->index = index;
   1749                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1750 
   1751                 return 0;
   1752             }
   1753         }
   1754     }
   1755 
   1756     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1757                 (BSL_META_U(unit,
   1758                             "soc_internal_ing_dnat_address_type_del: "
   1759                             "Not found\n")));
   1760 
   1761     result[0] = 0;
   1762     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1763     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1764     return 0;
   1765 }
   1766 
   1767 int
   1768 soc_internal_ing_dnat_address_type_lkup(pcid_info_t *pcid_info, uint8 banks,
   1769                                      void *entry, uint32 *result)
   1770 {
   1771     uint32          tmp[SOC_MAX_MEM_WORDS];
   1772     int             index = 0, bucket, slot;
   1773     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1774     int             unit = pcid_info->unit;
   1775     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1776     int             blk;
   1777     soc_block_t     sblk;
   1778     uint8           acc_type;
   1779     uint32          addr;
   1780 
   1781     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1782                 (BSL_META_U(unit,
   1783                             "ING_DNAT_ADDRESS_TYPE Lookup\n")));
   1784 
   1785     bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry, FALSE);
   1786 
   1787     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1788                 (BSL_META_U(unit,
   1789                             "bucket %d\n"), bucket));
   1790 
   1791     if (soc_feature(unit, soc_feature_dual_hash)) {
   1792         soc_internal_ing_dnat_address_type_dual_banks(pcid_info, banks, &dual,
   1793                                                       &slot_min, &slot_max);
   1794     }
   1795     blk = SOC_MEM_BLOCK_ANY(unit, ING_DNAT_ADDRESS_TYPEm);
   1796     sblk = SOC_BLOCK2SCH(unit, blk);
   1797 
   1798     /* Check if entry exists */
   1799     for (slot = slot_min; slot <= slot_max; slot++) {
   1800         if (dual && (slot == 4)) {
   1801             bucket = soc_internal_ing_dnat_address_type_hash(pcid_info, entry,
   1802                                                              TRUE);
   1803         }
   1804         index = bucket * 8 + slot;
   1805         addr = soc_mem_addr_get(unit, ING_DNAT_ADDRESS_TYPEm, 0, blk, index,
   1806                                 &acc_type);
   1807         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1808         if (soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, tmp, VALIDf)) {
   1809             if (soc_mem_compare_key(unit, ING_DNAT_ADDRESS_TYPEm, entry, tmp)
   1810                 == 0) {
   1811                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1812                             (BSL_META_U(unit,
   1813                                         "found sblk %d acc_type %d bucket %d, "
   1814                                         "slot %d, index %d\n"),
   1815                              sblk, acc_type, bucket, slot, index));
   1816 
   1817                 /* Copy entry immediately after response word */
   1818                 memcpy(&result[1], tmp,
   1819                        soc_mem_entry_bytes(unit, ING_DNAT_ADDRESS_TYPEm));
   1820 
   1821                 result[0] = 0;
   1822                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1823                 genresp_v2->index = index;
   1824                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1825 
   1826                 return 0;
   1827             }
   1828         }
   1829     }
   1830 
   1831     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1832                 (BSL_META_U(unit,
   1833                             "soc_internal_ing_dnat_address_type_lkup: Not found\n")));
   1834 
   1835     result[0] = 0;
   1836     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1837     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1838     return 0;
   1839 }
   1840 
   1841 int
   1842 soc_internal_l2_endpoint_id_hash(pcid_info_t *pcid_info, void *entry,
   1843                                  int dual)
   1844 {
   1845     soc_reg_t       reg;
   1846     soc_field_t     field;
   1847     uint32          tmp[SOC_MAX_MEM_WORDS];
   1848     int             hash_sel;
   1849     uint8           key[8];
   1850     int             index, bits;
   1851     soc_block_t     blk;
   1852     uint8           acc_type;
   1853     uint32          addr;
   1854 
   1855     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1856                 (BSL_META("L2_ENDPOINT_ID hash\n")));
   1857 
   1858     reg = L2_ENDPOINT_ID_HASH_CONTROLr;
   1859     field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af;
   1860 
   1861     addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0,
   1862                             SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
   1863     soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp);
   1864     hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field);
   1865 
   1866     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1867                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
   1868 
   1869     bits = soc_td2_l2_endpoint_id_base_entry_to_key(pcid_info->unit, dual,
   1870                                                     entry, key);
   1871     index = soc_td2_l2_endpoint_id_hash(pcid_info->unit, hash_sel, bits, entry,
   1872                                         key);
   1873 
   1874     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1875                 (BSL_META("index %d\n"), index));
   1876 
   1877     return index;
   1878 }
   1879 
   1880 void
   1881 soc_internal_l2_endpoint_id_dual_banks(pcid_info_t *pcid_info, uint8 banks,
   1882                                        int *dual, int *slot_min, int *slot_max)
   1883 {
   1884     /* Dual hash always enabled for L2_ENDPOINT_ID */
   1885     *dual = TRUE;
   1886 
   1887     if (*dual) {
   1888         switch (banks) {
   1889         case 0:
   1890             return; /* Nothing to do here */
   1891         case 1:
   1892             *slot_min = 4;
   1893             *slot_max = 7;
   1894             break;
   1895         case 2:
   1896             *slot_min = 0;
   1897             *slot_max = 3;
   1898             break;
   1899         default:
   1900             *slot_min = 0;
   1901             *slot_max = -1;
   1902             break;
   1903         }
   1904     }
   1905 
   1906     return;
   1907 }
   1908 
   1909 int
   1910 soc_internal_l2_endpoint_id_ins(pcid_info_t *pcid_info, uint8 banks,
   1911                                 void *entry, uint32 *result)
   1912 {
   1913     uint32          tmp[SOC_MAX_MEM_WORDS];
   1914     int             index = 0, bucket, slot, free_index;
   1915     int             slot_min = 0, slot_max = 7, dual = FALSE;
   1916     int             unit = pcid_info->unit;
   1917     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   1918     int             blk;
   1919     soc_block_t     sblk;
   1920     uint8           acc_type;
   1921     uint32          addr;
   1922 
   1923     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1924                 (BSL_META_U(unit,
   1925                             "L2_ENDPOINT_ID Insert\n")));
   1926 
   1927     bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE);
   1928 
   1929     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1930                 (BSL_META_U(unit,
   1931                             "bucket %d\n"), bucket));
   1932 
   1933     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   1934         soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual,
   1935                                                &slot_min, &slot_max);
   1936     }
   1937     blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm);
   1938     sblk = SOC_BLOCK2SCH(unit, blk);
   1939 
   1940     /* Check if it should overwrite an existing entry */
   1941     free_index = -1;
   1942     for (slot = slot_min; slot <= slot_max; slot++) {
   1943         if (dual && (slot == 4)) {
   1944             bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE);
   1945         }
   1946         index = bucket * 8 + slot;
   1947         addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index,
   1948                                 &acc_type);
   1949         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   1950         if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) {
   1951             if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp) == 0) {
   1952                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1953                             (BSL_META_U(unit,
   1954                                         "write sblk %d acc_type %d bucket %d, "
   1955                                         "slot %d, index %d\n"),
   1956                              sblk, acc_type, index / 8, index % 8, index));
   1957 
   1958                 /* Overwrite the existing entry */
   1959                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1960                                                 addr, entry);
   1961 
   1962                 /* Copy old entry immediately after response word */
   1963                 memcpy(&result[1], tmp,
   1964                        soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm));
   1965 
   1966                 result[0] = 0;
   1967                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
   1968                 genresp_v2->index = index;
   1969                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1970 
   1971                 return 0;
   1972             }
   1973         } else {
   1974             if (free_index == -1) {
   1975                 free_index = index;
   1976             }
   1977         }
   1978     }
   1979 
   1980     /* Find first unused slot in bucket */
   1981     if (free_index != -1) {
   1982         index = free_index;
   1983         addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index,
   1984                                 &acc_type);
   1985 
   1986         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1987                     (BSL_META_U(unit,
   1988                                 "write sblk %d acc_type %d bucket %d, slot %d, "
   1989                                 "index %d\n"),
   1990                      sblk, acc_type, index / 8, index % 8, index));
   1991 
   1992         /* Write the new entry */
   1993         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
   1994                                         entry);
   1995 
   1996         result[0] = 0;
   1997         genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
   1998         genresp_v2->index = index;
   1999         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2000 
   2001         return 0;
   2002     }
   2003 
   2004     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2005                 (BSL_META_U(unit,
   2006                             "Bucket full\n")));
   2007 
   2008     result[0] = 0;
   2009     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
   2010     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2011 
   2012     return 0;
   2013 }
   2014 
   2015 int
   2016 soc_internal_l2_endpoint_id_del(pcid_info_t *pcid_info, uint8 banks,
   2017                                 void *entry, uint32 *result)
   2018 {
   2019     uint32          tmp[SOC_MAX_MEM_WORDS];
   2020     int             index = 0, bucket, slot;
   2021     int             slot_min = 0, slot_max = 7, dual = FALSE;
   2022     int             unit = pcid_info->unit;
   2023     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   2024     int             blk;
   2025     soc_block_t     sblk;
   2026     uint8           acc_type;
   2027     uint32          addr;
   2028 
   2029     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2030                 (BSL_META_U(unit,
   2031                             "L2_ENDPOINT_ID Delete\n")));
   2032 
   2033     bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE);
   2034 
   2035     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2036                 (BSL_META_U(unit,
   2037                             "bucket %d\n"), bucket));
   2038 
   2039     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   2040         soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual,
   2041                                                &slot_min, &slot_max);
   2042     }
   2043     blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm);
   2044     sblk = SOC_BLOCK2SCH(unit, blk);
   2045 
   2046     /* Check if entry exists */
   2047     for (slot = slot_min; slot <= slot_max; slot++) {
   2048         if (dual && (slot == 4)) {
   2049             bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE);
   2050         }
   2051         index = bucket * 8 + slot;
   2052         addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index,
   2053                                 &acc_type);
   2054         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   2055         if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) {
   2056             if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp) == 0) {
   2057                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2058                             (BSL_META_U(unit,
   2059                                         "found sblk %d acc_type %d bucket %d, "
   2060                                         "slot %d, index %d\n"),
   2061                              sblk, acc_type, bucket, slot, index));
   2062 
   2063                 /* Copy entry immediately after response word */
   2064                 memcpy(&result[1], tmp,
   2065                        soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm));
   2066 
   2067                 /* Invalidate entry */
   2068                 soc_mem_field32_set(unit, L2_ENDPOINT_IDm, tmp, VALIDf, 0);
   2069                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   2070                                                 addr, tmp);
   2071 
   2072                 result[0] = 0;
   2073                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   2074                 genresp_v2->index = index;
   2075                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2076 
   2077                 return 0;
   2078             }
   2079         }
   2080     }
   2081 
   2082     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2083                 (BSL_META_U(unit,
   2084                             "soc_internal_l2_endpoint_id_del: "
   2085                             "Not found\n")));
   2086 
   2087     result[0] = 0;
   2088     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   2089     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2090     return 0;
   2091 }
   2092 
   2093 int
   2094 soc_internal_l2_endpoint_id_lkup(pcid_info_t *pcid_info, uint8 banks,
   2095                                  void *entry, uint32 *result)
   2096 {
   2097     uint32          tmp[SOC_MAX_MEM_WORDS];
   2098     int             index = 0, bucket, slot;
   2099     int             slot_min = 0, slot_max = 7, dual = FALSE;
   2100     int             unit = pcid_info->unit;
   2101     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   2102     int             blk;
   2103     soc_block_t     sblk;
   2104     uint8           acc_type;
   2105     uint32          addr;
   2106 
   2107     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2108                 (BSL_META_U(unit,
   2109                             "L2_ENDPOINT_ID Lookup\n")));
   2110 
   2111     bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, FALSE);
   2112 
   2113     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2114                 (BSL_META_U(unit,
   2115                             "bucket %d\n"), bucket));
   2116 
   2117     if (soc_feature(unit, soc_feature_dual_hash)) {
   2118         soc_internal_l2_endpoint_id_dual_banks(pcid_info, banks, &dual,
   2119                                                &slot_min, &slot_max);
   2120     }
   2121     blk = SOC_MEM_BLOCK_ANY(unit, L2_ENDPOINT_IDm);
   2122     sblk = SOC_BLOCK2SCH(unit, blk);
   2123 
   2124     /* Check if entry exists */
   2125     for (slot = slot_min; slot <= slot_max; slot++) {
   2126         if (dual && (slot == 4)) {
   2127             bucket = soc_internal_l2_endpoint_id_hash(pcid_info, entry, TRUE);
   2128         }
   2129         index = bucket * 8 + slot;
   2130         addr = soc_mem_addr_get(unit, L2_ENDPOINT_IDm, 0, blk, index,
   2131                                 &acc_type);
   2132         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   2133         if (soc_mem_field32_get(unit, L2_ENDPOINT_IDm, tmp, VALIDf)) {
   2134             if (soc_mem_compare_key(unit, L2_ENDPOINT_IDm, entry, tmp)
   2135                 == 0) {
   2136                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2137                             (BSL_META_U(unit,
   2138                                         "found sblk %d acc_type %d bucket %d, "
   2139                                         "slot %d, index %d\n"),
   2140                              sblk, acc_type, bucket, slot, index));
   2141 
   2142                 /* Copy entry immediately after response word */
   2143                 memcpy(&result[1], tmp,
   2144                        soc_mem_entry_bytes(unit, L2_ENDPOINT_IDm));
   2145 
   2146                 result[0] = 0;
   2147                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   2148                 genresp_v2->index = index;
   2149                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2150 
   2151                 return 0;
   2152             }
   2153         }
   2154     }
   2155 
   2156     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2157                 (BSL_META_U(unit,
   2158                             "soc_internal_l2_endpoint_id_lkup: Not found\n")));
   2159 
   2160     result[0] = 0;
   2161     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   2162     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2163     return 0;
   2164 }
   2165 
   2166 int
   2167 soc_internal_endpoint_queue_map_hash(pcid_info_t *pcid_info, void *entry,
   2168                                      int dual)
   2169 {
   2170     soc_reg_t       reg;
   2171     soc_field_t     field;
   2172     uint32          tmp[SOC_MAX_MEM_WORDS];
   2173     int             hash_sel;
   2174     uint8           key[8];
   2175     int             index, bits;
   2176     soc_block_t     blk;
   2177     uint8           acc_type;
   2178     uint32          addr;
   2179 
   2180     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2181                 (BSL_META("ENDPOINT_QUEUE_MAP hash\n")));
   2182 
   2183     reg = ENDPOINT_QUEUE_MAP_HASH_CONTROLr;
   2184     field = dual ? HASH_SELECT_Bf : HASH_SELECT_Af;
   2185 
   2186     addr = soc_reg_addr_get(pcid_info->unit, reg, REG_PORT_ANY, 0,
   2187                             SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
   2188     soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, tmp);
   2189     hash_sel = soc_reg_field_get(pcid_info->unit, reg, tmp[0], field);
   2190 
   2191     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2192                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
   2193 
   2194     bits = soc_td2_endpoint_queue_map_base_entry_to_key(pcid_info->unit, dual,
   2195                                                         entry, key);
   2196     index = soc_td2_endpoint_queue_map_hash(pcid_info->unit, hash_sel, bits,
   2197                                             entry, key);
   2198 
   2199     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2200                 (BSL_META("index %d\n"), index));
   2201 
   2202     return index;
   2203 }
   2204 
   2205 void
   2206 soc_internal_endpoint_queue_map_dual_banks(pcid_info_t *pcid_info, uint8 banks,
   2207                                            int *dual, int *slot_min,
   2208                                            int *slot_max)
   2209 {
   2210     /* Dual hash always enabled for ENDPOINT_QUEUE_MAP */
   2211     *dual = TRUE;
   2212 
   2213     if (*dual) {
   2214         switch (banks) {
   2215         case 0:
   2216             return; /* Nothing to do here */
   2217         case 1:
   2218             *slot_min = 4;
   2219             *slot_max = 7;
   2220             break;
   2221         case 2:
   2222             *slot_min = 0;
   2223             *slot_max = 3;
   2224             break;
   2225         default:
   2226             *slot_min = 0;
   2227             *slot_max = -1;
   2228             break;
   2229         }
   2230     }
   2231 
   2232     return;
   2233 }
   2234 
   2235 int
   2236 soc_internal_endpoint_queue_map_ins(pcid_info_t *pcid_info, uint8 banks,
   2237                                     void *entry, uint32 *result)
   2238 {
   2239     uint32          tmp[SOC_MAX_MEM_WORDS];
   2240     int             index = 0, bucket, slot, free_index;
   2241     int             slot_min = 0, slot_max = 7, dual = FALSE;
   2242     int             unit = pcid_info->unit;
   2243     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   2244     int             blk;
   2245     soc_block_t     sblk;
   2246     uint8           acc_type;
   2247     uint32          addr;
   2248 
   2249     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2250                 (BSL_META_U(unit,
   2251                             "ENDPOINT_QUEUE_MAP Insert\n")));
   2252 
   2253     bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE);
   2254 
   2255     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2256                 (BSL_META_U(unit,
   2257                             "bucket %d\n"), bucket));
   2258 
   2259     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   2260         soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual,
   2261                                                    &slot_min, &slot_max);
   2262     }
   2263     blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm);
   2264     sblk = SOC_BLOCK2SCH(unit, blk);
   2265 
   2266     /* Check if it should overwrite an existing entry */
   2267     free_index = -1;
   2268     for (slot = slot_min; slot <= slot_max; slot++) {
   2269         if (dual && (slot == 4)) {
   2270             bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry,
   2271                                                           TRUE);
   2272         }
   2273         index = bucket * 8 + slot;
   2274         addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index,
   2275                                 &acc_type);
   2276         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   2277         if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) {
   2278             if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp)
   2279                 == 0) {
   2280                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2281                             (BSL_META_U(unit,
   2282                                         "write sblk %d acc_type %d bucket %d, "
   2283                                         "slot %d, index %d\n"),
   2284                              sblk, acc_type, index / 8, index % 8, index));
   2285 
   2286                 /* Overwrite the existing entry */
   2287                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   2288                                                 addr, entry);
   2289 
   2290                 /* Copy old entry immediately after response word */
   2291                 memcpy(&result[1], tmp,
   2292                        soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm));
   2293 
   2294                 result[0] = 0;
   2295                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
   2296                 genresp_v2->index = index;
   2297                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2298 
   2299                 return 0;
   2300             }
   2301         } else {
   2302             if (free_index == -1) {
   2303                 free_index = index;
   2304             }
   2305         }
   2306     }
   2307 
   2308     /* Find first unused slot in bucket */
   2309     if (free_index != -1) {
   2310         index = free_index;
   2311         addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index,
   2312                                 &acc_type);
   2313 
   2314         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2315                     (BSL_META_U(unit,
   2316                                 "write sblk %d acc_type %d bucket %d, slot %d, "
   2317                                 "index %d\n"),
   2318                      sblk, acc_type, index / 8, index % 8, index));
   2319 
   2320         /* Write the new entry */
   2321         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
   2322                                         entry);
   2323 
   2324         result[0] = 0;
   2325         genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
   2326         genresp_v2->index = index;
   2327         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2328 
   2329         return 0;
   2330     }
   2331 
   2332     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2333                 (BSL_META_U(unit,
   2334                             "Bucket full\n")));
   2335 
   2336     result[0] = 0;
   2337     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
   2338     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2339 
   2340     return 0;
   2341 }
   2342 
   2343 int
   2344 soc_internal_endpoint_queue_map_del(pcid_info_t *pcid_info, uint8 banks,
   2345                                     void *entry, uint32 *result)
   2346 {
   2347     uint32          tmp[SOC_MAX_MEM_WORDS];
   2348     int             index = 0, bucket, slot;
   2349     int             slot_min = 0, slot_max = 7, dual = FALSE;
   2350     int             unit = pcid_info->unit;
   2351     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   2352     int             blk;
   2353     soc_block_t     sblk;
   2354     uint8           acc_type;
   2355     uint32          addr;
   2356 
   2357     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2358                 (BSL_META_U(unit,
   2359                             "ENDPOINT_QUEUE_MAP Delete\n")));
   2360 
   2361     bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE);
   2362 
   2363     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2364                 (BSL_META_U(unit,
   2365                             "bucket %d\n"), bucket));
   2366 
   2367     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
   2368         soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual,
   2369                                                    &slot_min, &slot_max);
   2370     }
   2371     blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm);
   2372     sblk = SOC_BLOCK2SCH(unit, blk);
   2373 
   2374     /* Check if entry exists */
   2375     for (slot = slot_min; slot <= slot_max; slot++) {
   2376         if (dual && (slot == 4)) {
   2377             bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry,
   2378                                                           TRUE);
   2379         }
   2380         index = bucket * 8 + slot;
   2381         addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index,
   2382                                 &acc_type);
   2383         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   2384         if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) {
   2385             if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp)
   2386                 == 0) {
   2387                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2388                             (BSL_META_U(unit,
   2389                                         "found sblk %d acc_type %d bucket %d, "
   2390                                         "slot %d, index %d\n"),
   2391                              sblk, acc_type, bucket, slot, index));
   2392 
   2393                 /* Copy entry immediately after response word */
   2394                 memcpy(&result[1], tmp,
   2395                        soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm));
   2396 
   2397                 /* Invalidate entry */
   2398                 soc_mem_field32_set(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf, 0);
   2399                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   2400                                                 addr, tmp);
   2401 
   2402                 result[0] = 0;
   2403                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   2404                 genresp_v2->index = index;
   2405                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2406 
   2407                 return 0;
   2408             }
   2409         }
   2410     }
   2411 
   2412     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2413                 (BSL_META_U(unit,
   2414                             "soc_internal_endpoint_queue_map_del: "
   2415                             "Not found\n")));
   2416 
   2417     result[0] = 0;
   2418     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   2419     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2420     return 0;
   2421 }
   2422 
   2423 int
   2424 soc_internal_endpoint_queue_map_lkup(pcid_info_t *pcid_info, uint8 banks,
   2425                                      void *entry, uint32 *result)
   2426 {
   2427     uint32          tmp[SOC_MAX_MEM_WORDS];
   2428     int             index = 0, bucket, slot;
   2429     int             slot_min = 0, slot_max = 7, dual = FALSE;
   2430     int             unit = pcid_info->unit;
   2431     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
   2432     int             blk;
   2433     soc_block_t     sblk;
   2434     uint8           acc_type;
   2435     uint32          addr;
   2436 
   2437     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2438                 (BSL_META_U(unit,
   2439                             "ENDPOINT_QUEUE_MAP Lookup\n")));
   2440 
   2441     bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry, FALSE);
   2442 
   2443     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2444                 (BSL_META_U(unit,
   2445                             "bucket %d\n"), bucket));
   2446 
   2447     if (soc_feature(unit, soc_feature_dual_hash)) {
   2448         soc_internal_endpoint_queue_map_dual_banks(pcid_info, banks, &dual,
   2449                                                    &slot_min, &slot_max);
   2450     }
   2451     blk = SOC_MEM_BLOCK_ANY(unit, ENDPOINT_QUEUE_MAPm);
   2452     sblk = SOC_BLOCK2SCH(unit, blk);
   2453 
   2454     /* Check if entry exists */
   2455     for (slot = slot_min; slot <= slot_max; slot++) {
   2456         if (dual && (slot == 4)) {
   2457             bucket = soc_internal_endpoint_queue_map_hash(pcid_info, entry,
   2458                                                           TRUE);
   2459         }
   2460         index = bucket * 8 + slot;
   2461         addr = soc_mem_addr_get(unit, ENDPOINT_QUEUE_MAPm, 0, blk, index,
   2462                                 &acc_type);
   2463         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
   2464         if (soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, tmp, VALIDf)) {
   2465             if (soc_mem_compare_key(unit, ENDPOINT_QUEUE_MAPm, entry, tmp)
   2466                 == 0) {
   2467                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2468                             (BSL_META_U(unit,
   2469                                         "found sblk %d acc_type %d bucket %d, "
   2470                                         "slot %d, index %d\n"),
   2471                              sblk, acc_type, bucket, slot, index));
   2472 
   2473                 /* Copy entry immediately after response word */
   2474                 memcpy(&result[1], tmp,
   2475                        soc_mem_entry_bytes(unit, ENDPOINT_QUEUE_MAPm));
   2476 
   2477                 result[0] = 0;
   2478                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   2479                 genresp_v2->index = index;
   2480                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   2481 
   2482                 return 0;
   2483             }
   2484         }
   2485     }
   2486 
   2487     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2488                 (BSL_META_U(unit,
   2489                             "soc_internal_endpoint_queue_map_lkup: Not found\n")));
   2490 
   2491     result[0] = 0;
   2492     genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   2493     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   2494 
   2495     return 0;
   2496 }
   2497 
   2498 #endif /* BCM_TRIDENT2_SUPPORT */
   2499 #endif /* BCM_TRX_SUPPORT */