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

drvmem.c (121845B)


      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  * Memory address and field manipulations.
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <assert.h>
     13 
     14 #include <sal/core/libc.h>
     15 
     16 #include <soc/dnxc/multithread_analyzer.h>
     17 
     18 #include <soc/drv.h>
     19 #include <soc/mem.h>
     20 #include <soc/error.h>
     21 #ifdef BCM_ESW_SUPPORT
     22 #include <soc/er_tcam.h>
     23 #endif
     24 #ifdef BCM_DFE_SUPPORT
     25 #include <soc/dfe/cmn/dfe_drv.h>
     26 #endif
     27 #ifdef BCM_ESW_SUPPORT
     28 #include <soc/format.h>
     29 #endif
     30 #ifdef BCM_TOMAHAWK3_SUPPORT
     31 #include <soc/tomahawk3.h>
     32 #endif
     33 #ifdef BCM_TRIDENT3_SUPPORT
     34 #include <soc/esw/flow_db.h>
     35 #endif
     36 
     37 /*
     38  * save the last memory used in direct access (usually used for cache)
     39  * No init required since no harm is done if invalid memory saved here.
     40  * Thread safe - since the last memory used first copied to a local variable and then used.
     41  */
     42 soc_mem_t drvmem_last_used_mem_direct_acc[SOC_MAX_NUM_DEVICES] = {0};
     43 
     44 
     45 /*
     46  * Macro used by memory accessor functions to fix order
     47  */
     48 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \
     49                                 BYTES2WORDS((m)->bytes)-1-(v) : \
     50                                 (v))
     51 
     52 #ifdef BCM_TRIDENT3_SUPPORT
     53 /*
     54  * Function:      soc_meminfo_field_get_helper
     55  * Purpose:       Get a memory field without reference to chip.
     56  * Parameters:    meminfo   --  direct reference to memory description
     57  */
     58 STATIC uint32 *
     59 soc_meminfo_field_get_helper(soc_mem_info_t *meminfo,
     60                       const uint32 *entbuf, 
     61                       soc_field_info_t *fieldinfo,
     62                       uint32 *fldbuf, uint32 fldbuf_size)
     63 {
     64     int len;
     65 
     66     assert(fieldinfo);
     67 
     68     len = fieldinfo->len;
     69     assert(len / 32 <= fldbuf_size); /* assert we do not write beyond the end of the output buffer */
     70 
     71     return soc_meminfo_fieldinfo_field_get(entbuf,
     72                                     meminfo,
     73                                     fieldinfo,
     74                                     fldbuf);
     75 }
     76 #endif
     77 
     78 /*
     79  * Function:      _soc_field_value_fit
     80  * Purpose:       Check if value will fit into a memory field. 
     81  * Parameters:    fieldinfo --  (IN)Direct reference to field description.
     82  *                value     --  (IN)Value to be checked.   
     83  * Returns: 
     84  *      TRUE  - buffer fits into the field. 
     85  *      FALSE - Otherwise. 
     86  */
     87 STATIC int
     88 _soc_field_value_fit(soc_field_info_t *fieldinfo, uint32 *value)
     89 {
     90     uint32      mask;    /* Value mask                      */
     91     uint16      len;     /* Bits in field                   */
     92     int         idx;     /* Iteration index.                */
     93 
     94     idx = (fieldinfo->len - 1) >> 5;
     95     len = fieldinfo->len % 32;
     96 
     97     if (!len) {
     98        return TRUE; 
     99     }
    100 
    101     mask = (1 << len) - 1;
    102     if((value[idx] & ~mask) != 0) {
    103         return (FALSE);
    104     }
    105     return (TRUE);
    106 }
    107 
    108 
    109 #ifdef BCM_TRIDENT3_SUPPORT
    110 
    111 /*
    112  * Function:      _soc_mem_view_sub_field_set
    113  * Purpose:       Write to a sub field specified by the start and end positions
    114  *                to the given user field.
    115  *
    116  * Parameters:    usr_field -- the given user field that sub field written to
    117  *                pos_min --  the start bit position in the given field.
    118  *                pos_max --  The end bit position in the given field.
    119  *                frag_field -- point to the sub_field value 
    120  * Returns:
    121  *      SOC_E_XXX.
    122  */
    123 
    124 STATIC int
    125 _soc_mem_view_sub_field_set(uint32 *usr_field,
    126                      int pos_min, int pos_max,
    127                      uint32 *frag_field)
    128 {
    129     int i;
    130     int word_start;
    131     int bit_start;
    132     int bit_end;
    133     int word_num;
    134     int r_shifter;
    135     int l_shifter;
    136     int last_idx;
    137 
    138     word_start = pos_min/32;
    139     bit_start  = pos_min%32;
    140     bit_end    = pos_max%32;
    141     word_num = pos_max/32 - pos_min/32;
    142     l_shifter = bit_start;
    143     r_shifter  = 32 - l_shifter;
    144 
    145     /* safety check */
    146     if (pos_min > pos_max) {
    147         return SOC_E_INTERNAL;
    148     }
    149     /* frag_field must have exact number of bits value. extra bits
    150      * in the 32-bit word must be cleared
    151      */
    152     if ((pos_max - pos_min + 1)%32) {
    153         frag_field[(pos_max - pos_min + 1)/32] &= 
    154             ((1 << ((pos_max - pos_min + 1)%32)) - 1);
    155     }
    156     for (last_idx = 0, i = 0; i < word_num; i++) {
    157         usr_field[word_start + i] |= (frag_field[i] << l_shifter);
    158         if (l_shifter) {
    159             usr_field[word_start + i + 1] |= (frag_field[i] >> r_shifter);
    160         }
    161         last_idx = i + 1;
    162     }
    163     if (bit_end >= l_shifter) {
    164         usr_field[word_start + last_idx] |= (frag_field[last_idx] <<
    165                               l_shifter);
    166     }
    167     return SOC_E_NONE;
    168 }
    169 
    170 /*
    171  * Function:      _soc_mem_view_sub_field_get
    172  * Purpose:       Retrieve a sub field specified by the start and end positions of
    173  *                the given user field.
    174  *
    175  * Parameters:    usr_field -- the given user field that sub field resides in 
    176  *                pos_min --   the start bit position in the given field.
    177  *                pos_max --   the end bit position in the given field.
    178  *                frag_field -- point to the retrieved sub_field value
    179  * Returns:
    180  *      SOC_E_XXX.
    181  */
    182 
    183 STATIC int
    184 _soc_mem_view_sub_field_get(uint32 *usr_field, int pos_min,
    185                        int pos_max, uint32 *frag_field)
    186 {
    187     int i;
    188     uint32 mask;
    189     int last_idx;
    190     int word_start;
    191     int bit_start;
    192     int bit_end;
    193     int word_num;
    194     int r_shifter;
    195     int l_shfter;
    196 
    197     word_start = pos_min/32;
    198     bit_start  = pos_min%32;
    199     bit_end    = pos_max%32;
    200     word_num = pos_max/32 - pos_min/32;
    201     r_shifter = bit_start;
    202     l_shfter  = 32 - r_shifter;
    203 
    204     /* safety check */
    205     if (pos_min > pos_max) {
    206         return SOC_E_INTERNAL;
    207     }
    208     for (i = 0; i < word_num; i++) {
    209         frag_field[i] = usr_field[word_start + i] >> r_shifter;
    210         if (r_shifter) {
    211             frag_field[i] |= usr_field[word_start + i + 1] << l_shfter;
    212         }
    213     }
    214     last_idx = i - 1;
    215     if (r_shifter > bit_end) {
    216         /* last_idx < 0 should never happen if r_shifter > bit_end */
    217         if (last_idx >= 0) { /* safety check */
    218             mask = ((uint32)0xFFFFFFFF) >> (r_shifter - (bit_end + 1));
    219             frag_field[last_idx] &= mask;
    220         }
    221     } else {
    222         mask = ((uint32)0xFFFFFFFF) >> (31 - (bit_end - r_shifter));
    223         frag_field[last_idx+1] = (usr_field[word_start + last_idx + 1] >>
    224                               r_shifter) & mask;
    225     }
    226     return SOC_E_NONE;
    227 }
    228 
    229 /*
    230  * Function:    _soc_mem_view_field_set
    231  * Purpose:     Set a memory field (of a memory view)
    232  * Parameters:  unit - device
    233  *              mem_view - mem view
    234  *              entbuf - table entry buffer
    235  *              field - which field to set
    236  *              fldbuf - field buffer
    237  */
    238 STATIC void
    239 _soc_mem_view_field_set(int unit, soc_mem_t mem_view, uint32 *entbuf, soc_field_t field,
    240                   uint32 *fldbuf)
    241 {
    242     int rv = SOC_E_NONE;
    243     soc_mem_t phy_mem;
    244     soc_field_info_t fieldinfo;
    245     soc_mem_view_split_field_info_t *sf_info;  /* split field info */
    246     soc_mem_info_t *meminfo;
    247     uint32 *val_field;
    248     int i;
    249     char *buf_ptr;
    250     int alloc_size;
    251  
    252     if (!soc_feature(unit, soc_feature_flex_flow)) {
    253         return;
    254     }
    255 
    256     if (!SOC_MEM_IS_VIEW(unit, mem_view)) {
    257         return;
    258     }
    259 
    260     rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    261     if (rv != SOC_E_NONE) {
    262         return;
    263     }
    264     meminfo = &SOC_MEM_INFO(unit, phy_mem);
    265 
    266     /* check if it is virtual field */
    267     rv = soc_flow_db_mem_view_field_is_virtual(unit, mem_view,field);
    268 
    269     if (rv) {
    270 
    271         /* use malloc to avoid coverity stack overflow issue */
    272         alloc_size = sizeof(soc_mem_view_split_field_info_t);
    273         alloc_size += SOC_MAX_MEM_WORDS * sizeof(uint32);
    274 
    275         buf_ptr = sal_alloc(alloc_size, "Temp buffer for _soc_mem_view_field_set");
    276         sal_memset((void *)buf_ptr,0,alloc_size);
    277         sf_info = (soc_mem_view_split_field_info_t *)buf_ptr;
    278         val_field = (uint32 *)(sf_info + 1);
    279 
    280         rv = soc_mem_view_split_field_info_get(unit,mem_view,field,sf_info);
    281         if (rv != SOC_E_NONE) {
    282             sal_free(buf_ptr);
    283             return;
    284         }
    285 
    286         for (i = 0; i < sf_info->num_fld; i++) {
    287             rv = _soc_mem_view_sub_field_get(fldbuf,
    288                   sf_info->fld[i].v_offset,
    289                   sf_info->fld[i].field.len + sf_info->fld[i].v_offset - 1, 
    290                   val_field);
    291             if (rv != SOC_E_NONE) {
    292                 sal_free(buf_ptr);
    293                 return;
    294             }
    295             soc_meminfo_fieldinfo_field_set(entbuf, meminfo, 
    296                     &sf_info->fld[i].field, val_field);
    297         }
    298         sal_free(buf_ptr);
    299 
    300     } else {
    301         sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo));
    302         rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo);
    303         if (rv != SOC_E_NONE) {
    304             return;
    305         }
    306         soc_meminfo_fieldinfo_field_set(entbuf, meminfo, &fieldinfo, fldbuf);
    307     }
    308 
    309     return;
    310 }
    311 
    312 /*
    313  * Function:    _soc_mem_view_field_get
    314  * Purpose:     Get a memory field
    315  * Parameters:  unit - device
    316  *              mem_view - table
    317  *              entbuf - table entry buffer
    318  *              field - which field to get
    319  *              fldbuf - field buffer
    320  */
    321 STATIC uint32*
    322 _soc_mem_view_field_get(int unit, soc_mem_t mem_view, const uint32 *entbuf,
    323                   soc_field_t field, uint32 *fldbuf, uint32 words)
    324 {
    325     int rv = SOC_E_NONE;
    326     soc_mem_t phy_mem;
    327     soc_field_info_t fieldinfo;
    328     soc_mem_info_t *meminfo;
    329     uint32 *val_field;
    330     soc_mem_view_split_field_info_t *sf_info;  /* split field info */
    331     int i;
    332     int fld_word_len;
    333     char *buf_ptr;
    334     int alloc_size;
    335 
    336     if (!soc_feature(unit, soc_feature_flex_flow)) {
    337         return fldbuf;
    338     }
    339 
    340     if (!SOC_MEM_IS_VIEW(unit, mem_view)) {
    341         return fldbuf;
    342     }
    343 
    344     rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    345     if (rv != SOC_E_NONE) {
    346         return fldbuf;
    347     }
    348 
    349     rv = soc_flow_db_mem_view_field_is_virtual(unit, mem_view,field);
    350 
    351     if (rv) {
    352 
    353         /* use malloc to avoid coverity stack overflow issue */
    354         alloc_size = sizeof(soc_mem_view_split_field_info_t);
    355         alloc_size += SOC_MAX_MEM_WORDS * sizeof(uint32);
    356  
    357         buf_ptr = sal_alloc(alloc_size, "Temp buffer for _soc_mem_view_field_get");
    358         sal_memset((void *)buf_ptr,0,alloc_size);
    359         sf_info = (soc_mem_view_split_field_info_t *)buf_ptr;
    360         val_field = (uint32 *)(sf_info + 1);
    361 
    362         rv = soc_mem_view_split_field_info_get(unit,mem_view,field,sf_info);
    363         if (rv != SOC_E_NONE) {
    364             sal_free(buf_ptr);
    365             return fldbuf;
    366         }
    367 
    368         /* initialize the fldbuf */
    369         fld_word_len = (sf_info->width + 31)/32;
    370         assert (fld_word_len <= words);
    371         for (i = 0; i < fld_word_len; i++) {
    372             fldbuf[i] = 0;
    373         }
    374         meminfo = &SOC_MEM_INFO(unit, phy_mem);
    375 
    376         for (i = 0; i < sf_info->num_fld; i++) { 
    377             (void)soc_meminfo_field_get_helper(meminfo, entbuf, &sf_info->fld[i].field, 
    378                                                val_field, words);
    379         
    380             rv = _soc_mem_view_sub_field_set(fldbuf, sf_info->fld[i].v_offset, 
    381                      sf_info->fld[i].v_offset + sf_info->fld[i].field.len - 1,   
    382                      val_field);
    383             if (rv != SOC_E_NONE) {
    384                 sal_free(buf_ptr);
    385                 return fldbuf;
    386             }
    387         }
    388         sal_free(buf_ptr);
    389 
    390     } else {
    391 
    392         sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo));
    393         rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo);
    394         if (rv != SOC_E_NONE) {
    395             return fldbuf;
    396         }
    397 
    398         meminfo = &SOC_MEM_INFO(unit, phy_mem);
    399         return soc_meminfo_field_get_helper(meminfo, entbuf, &fieldinfo, fldbuf, words);
    400     }
    401     return fldbuf;
    402 }
    403 
    404 /*
    405  * Function:
    406  *      _soc_mem_view_field_valid
    407  * Purpose:
    408  *      Verify if field is valid & present in memory view
    409  * Parameters:
    410  *      mem_view     - (IN)Memory view id
    411  *      field   - (IN)Field id.
    412  * Return:
    413  *      TRUE  -If field is present & valid.
    414  *      FALSE -Otherwise.
    415  */
    416 STATIC int
    417 _soc_mem_view_field_valid(int unit, soc_mem_t mem_view, soc_field_t field)
    418 {
    419     return soc_mem_view_field_valid(unit, mem_view, field);
    420 }
    421 
    422 /*
    423  * Function:
    424  *      _soc_mem_view_field32_fit
    425  * Purpose:
    426  *      Check if uint32 value fits into a memory view field.
    427  * Parameters: 
    428  *      unit    - (IN)SOC unit number.
    429  *      mem     - (IN)Memory view id.
    430  *      field   - (IN)Field id.
    431  *      value   - (IN)Value to be checked. 
    432  * Return:     
    433  *      SOC_E_PARAM -If value is too big for field, or some other error.
    434  *      SOC_E_NONE  -Otherwise.
    435  */
    436 STATIC int 
    437 _soc_mem_view_field32_fit(int unit, soc_mem_t mem_view,
    438                        soc_field_t field, uint32 value)
    439 {
    440     int rv = SOC_E_NONE;
    441     soc_mem_t phy_mem;
    442     soc_field_info_t fieldinfo;
    443 
    444     rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    445     if (rv != SOC_E_NONE) {
    446         return rv;
    447     }
    448 
    449     sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo));
    450     rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo);
    451     if (rv != SOC_E_NONE) {
    452         return rv;
    453     }
    454 
    455     return (_soc_field_value_fit(&fieldinfo, &value)) ?
    456         SOC_E_NONE : SOC_E_PARAM;
    457 }
    458 
    459 /*
    460  * Function:
    461  *     _soc_mem_view_field_length
    462  * Purpose:
    463  *     the length of a memory view field in bits.
    464  * Parameters:
    465  *     unit    - (IN)SOC unit number.
    466  *     mem     - (IN)Memory view id.
    467  *     field   - (IN)Field id.
    468  * Return:
    469  *     bits in field.
    470  *     0 if the field is not found.
    471  */ 
    472 STATIC int
    473 _soc_mem_view_field_length(int unit, soc_mem_t mem_view, soc_field_t field)
    474 {
    475     int rv = SOC_E_NONE;
    476     soc_field_info_t fieldinfo;
    477 
    478     sal_memset(&fieldinfo, 0x0, sizeof(fieldinfo));
    479     rv = soc_mem_view_fieldinfo_get(unit, mem_view, field, &fieldinfo);
    480     if (rv != SOC_E_NONE) {
    481         return 0;
    482     }
    483     return fieldinfo.len;
    484 }
    485 
    486 /*
    487  * Function:   _soc_mem_view_fields32_modify
    488  * Purpose:    Modify the value of a fields in a memory view
    489  * Parameters:
    490  *       unit         - (IN) SOC unit number.
    491  *       mem          - (IN) Memory view
    492  *       index        - (IN) Memory entry index.
    493  *       field_count  - (IN) Number of fields to modify.
    494  *       fields       - (IN) Modified fields array.
    495  *       values       - (IN) New value for each member of fields array.
    496  * Returns:
    497  *       SOC_E_XXX
    498  */
    499 int
    500 _soc_mem_view_fields32_modify(int unit, soc_mem_t mem_view, int index,
    501                         int field_count, soc_field_t *fields, uint32 *values)
    502 {
    503     uint32 buf[SOC_MAX_MEM_WORDS];       /* Buffer to read memory entry. */
    504     int idx;                             /* Iteration index.             */
    505     int rv;                              /* Operation return status.     */
    506     int value_changed = 0;               /* Flag of value changed comparing
    507                                             between input and current reading*/
    508     soc_mem_t phy_mem;
    509 
    510     /* Field count check before continue. */
    511     if (field_count == 0) {
    512         return (SOC_E_NONE);
    513     }
    514 
    515     rv = soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    516     if (rv != SOC_E_NONE) {
    517         return rv;
    518     }
    519 
    520     /* Check entry index range. */
    521     if ((index > soc_mem_index_max(unit, phy_mem)) ||
    522         (index < soc_mem_index_min(unit, phy_mem))) {
    523         return (SOC_E_PARAM);
    524     }
    525 
    526     /*  Fields & values sanity check. */
    527     for (idx = 0; idx < field_count; idx++) {
    528         if ((NULL == fields + idx) || (NULL == values + idx)) {
    529            /*
    530             * COVERITY
    531             * This is kept intentional for future use
    532             * or as defensive statement.
    533             */
    534             /* coverity[dead_error_line] */
    535             return (SOC_E_PARAM);
    536         }
    537 
    538         /* Make sure value fits into memory field. */
    539         SOC_IF_ERROR_RETURN
    540             (soc_mem_field32_fit(unit, mem_view, fields[idx], values[idx]));
    541     }
    542 
    543     /* Lock the memory. */
    544     soc_mem_lock(unit, phy_mem);
    545     rv = soc_mem_read(unit, mem_view, MEM_BLOCK_ANY, index, buf);
    546     if (SOC_FAILURE(rv)) {
    547         soc_mem_unlock(unit, phy_mem);
    548         return (rv);
    549     }
    550 
    551     /* Set updated values in the buffer. */
    552     for (idx = 0; idx < field_count; idx ++) {
    553         if(values[idx] != soc_mem_field32_get(unit, mem_view, buf, fields[idx])) {
    554             value_changed = 1;
    555             soc_mem_field32_set(unit, mem_view, buf, fields[idx], values[idx]);
    556         }
    557     }
    558 
    559     /* Write buffer back to memory. */
    560     if(value_changed) {
    561         rv = soc_mem_write(unit, mem_view, MEM_BLOCK_ALL, index, buf);
    562     }
    563 
    564     soc_mem_unlock(unit, phy_mem);
    565     return (rv);
    566 }
    567 #endif
    568 
    569 /*
    570  * Function:     soc_mem_field_length
    571  * Purpose:      Return the length of a memory field in bits.
    572  *               Value is 0 if field is not found.
    573  * Returns:      bits in field
    574  */
    575 int
    576 soc_mem_field_length(int unit, soc_mem_t mem, soc_field_t field)
    577 {
    578     soc_field_info_t    *fld;
    579 
    580 #ifdef BCM_TRIDENT3_SUPPORT
    581     if (soc_feature(unit, soc_feature_flex_flow)) {
    582         if (SOC_MEM_IS_VIEW(unit, mem)) {
    583             return _soc_mem_view_field_length(unit, mem, field);
    584         }
    585     }
    586 #endif
    587 
    588     SOC_FIND_FIELD(field,
    589                    SOC_MEM_INFO(unit, mem).fields,
    590                    SOC_MEM_INFO(unit, mem).nFields,
    591                    fld);
    592     if (fld == NULL) {
    593         return 0;
    594     }
    595     return fld->len;
    596 }
    597 
    598 /****************************************************************
    599  *
    600  * MEMORY ENTRY VALUE MANIPULATION FUNCTIONS
    601  */
    602 
    603 /*
    604  * Function:      soc_memacc_get
    605  * Purpose:       Get a (memory, field) access information structure
    606  * Parameters:    unit - device
    607  *                mem - table
    608  *                field - which field to get
    609  *                memacc - (OUT) Memory access structure
    610  */
    611 int
    612 soc_memacc_init(int unit, soc_mem_t mem, soc_field_t fld,
    613                 soc_memacc_t *memacc)
    614 {
    615     soc_mem_info_t *meminfo;
    616     soc_field_info_t *finfop;
    617 
    618     if (!SOC_MEM_IS_VALID(unit, mem))  {
    619         return SOC_E_PARAM;
    620     }
    621 
    622     meminfo = &SOC_MEM_INFO(unit, mem);
    623         
    624     SOC_FIND_FIELD(fld,
    625                    meminfo->fields,
    626                    meminfo->nFields,
    627                    finfop);
    628 
    629     if (finfop == NULL) {
    630         return SOC_E_PARAM;
    631     }
    632 
    633     memacc->minfo = meminfo;
    634     memacc->finfo = finfop;
    635 
    636     return SOC_E_NONE;
    637 }
    638 
    639 /*
    640  * Function:      soc_memacc_field_get
    641  * Purpose:       Get a memory field without reference to chip.
    642  * Parameters:    memacc - Memory access structure
    643  */
    644 uint32 *
    645 soc_memacc_field_get(soc_memacc_t *memacc, const uint32 *entbuf,
    646                      uint32 *fldbuf)
    647 {
    648     soc_mem_info_t *meminfo = memacc->minfo;
    649     soc_field_info_t *fieldinfo = memacc->finfo;
    650     int                 i, wp, bp, len;
    651 
    652     bp = fieldinfo->bp;
    653     len = fieldinfo->len;
    654 
    655     if (len == 1) {     /* special case single bits */
    656         wp = bp / 32;
    657         bp = bp & (32 - 1);
    658         if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) {
    659             fldbuf[0] = 1;
    660         } else {
    661             fldbuf[0] = 0;
    662         }
    663         return fldbuf;
    664     }
    665 
    666     if (fieldinfo->flags & SOCF_LE) {
    667         wp = bp / 32;
    668         bp = bp & (32 - 1);
    669         i = 0;
    670 
    671         for (; len > 0; len -= 32) {
    672             if (bp) {
    673                 fldbuf[i] =
    674                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp &
    675                     ((1 << (32 - bp)) - 1);
    676                 if ( len > (32 - bp) ) {
    677                     fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] <<
    678                         (32 - bp);
    679                 }
    680             } else {
    681                 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)];
    682             }
    683 
    684             if (len < 32) {
    685                 fldbuf[i] &= ((1 << len) - 1);
    686             }
    687 
    688             i++;
    689         }
    690     } else {
    691         i = (len - 1) / 32;
    692 
    693         while (len > 0) {
    694             assert(i >= 0);
    695 
    696             fldbuf[i] = 0;
    697 
    698             do {
    699                 fldbuf[i] =
    700                     (fldbuf[i] << 1) |
    701                     ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >>
    702                       (bp & (32 - 1))) & 1);
    703                 len--;
    704                 bp++;
    705             } while (len & (32 - 1));
    706 
    707             i--;
    708         }
    709     }
    710 
    711     return fldbuf;
    712 }
    713 
    714 uint32
    715 soc_memacc_field32_get(soc_memacc_t *memacc, void *entry)
    716 {
    717     uint32 value;
    718 
    719     /*
    720      * COVERITY
    721      *
    722      * We do this intentionally to use the generic function
    723      * soc_memacc_field_get() which does the necessary handling.
    724  */
    725     /* coverity[address_of] */
    726     /* coverity[callee_ptr_arith] */
    727     soc_memacc_field_get(memacc, entry, &value);
    728 
    729     return value;
    730 }
    731 
    732 void
    733 soc_memacc_field64_get(soc_memacc_t *memacc, void *entry, uint64 *val64)
    734 {
    735     uint32 val64_field[2] = {0, 0};
    736 
    737     soc_memacc_field_get(memacc, entry, val64_field);
    738 
    739     COMPILER_64_SET(*val64, val64_field[1], val64_field[0]);
    740 }
    741 
    742 /*
    743  * Function:     soc_memacc_mac_addr_get
    744  * Purpose:      Get a mac address field in a memory from a mac addr type
    745  * Returns:      SOC_E_xxx
    746  */
    747 void
    748 soc_memacc_mac_addr_get(soc_memacc_t *memacc, void *entry, sal_mac_addr_t mac)
    749 {
    750     uint32              mac_field[2];
    751 
    752     soc_memacc_field_get(memacc, entry, mac_field);
    753 
    754     SAL_MAC_ADDR_FROM_UINT32(mac, mac_field);
    755 }
    756 
    757 /*
    758  * Function:      soc_mem_fieldinfo_get
    759  * Purpose:       Get a memory field's fieldinfo reference.
    760  * Parameters:    unit - device
    761  *                mem - table
    762  *                field - which field to get
    763  * NB:
    764  *    This function is designed for cases where many entries of the
    765  *    same table and fields are processed in a batch, such as
    766  *    for traverse functions and tables of counter values.  It provides
    767  *    the necessary info structure for using
    768  *    soc_mem_fieldinfo_field_get below.
    769  */
    770 soc_field_info_t *
    771 soc_mem_fieldinfo_get(int unit, soc_mem_t mem, soc_field_t field)
    772 {
    773     soc_mem_info_t  *meminfo;
    774     soc_field_info_t       *finfop; /* Field information structure. */
    775 
    776     /* Verify that memory is present on the device. */
    777     if (!SOC_MEM_IS_VALID(unit, mem))  {
    778         return NULL;
    779     }
    780 
    781     meminfo = &SOC_MEM_INFO(unit, mem);
    782     SOC_FIND_FIELD(field,
    783                    meminfo->fields,
    784                    meminfo->nFields,
    785                    finfop);
    786 
    787     return finfop;
    788 }
    789 
    790 /*
    791  * Function:      soc_meminfo_fieldinfo_field_get
    792  * Purpose:       Get a memory field without reference to chip.
    793  * Parameters:    meminfo   --  direct reference to memory description
    794  *                fieldinfo   --  direct reference to field description
    795  * NB:
    796  *    Callee must verify that the requested memory and
    797  *    field specification are valid on the device from which the
    798  *    entry was read.
    799  *    This function is designed for cases where many entries of the
    800  *    same table and fields are processed in a batch, such as
    801  *    for traverse functions and tables of counter values.
    802  */
    803 uint32 *
    804 soc_meminfo_fieldinfo_field_get(const uint32 *entbuf,
    805                                 soc_mem_info_t *meminfo,
    806                                 soc_field_info_t *fieldinfo,
    807                                 uint32 *fldbuf)
    808 {
    809     int                 i, wp, bp, len;
    810 
    811     bp = fieldinfo->bp;
    812     len = fieldinfo->len;
    813 
    814     if (len == 1) {     /* special case single bits */
    815         wp = bp / 32;
    816         bp = bp & (32 - 1);
    817         if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) {
    818             fldbuf[0] = 1;
    819         } else {
    820             fldbuf[0] = 0;
    821         }
    822         return fldbuf;
    823     }
    824 
    825     if (fieldinfo->flags & SOCF_LE) {
    826         wp = bp / 32;
    827         bp = bp & (32 - 1);
    828         i = 0;
    829 
    830         for (; len > 0; len -= 32) {
    831             if (bp) {
    832                 fldbuf[i] =
    833                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp &
    834                     ((1 << (32 - bp)) - 1);
    835                 if ( len > (32 - bp) ) {
    836                     fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] <<
    837                         (32 - bp);
    838                 }
    839             } else {
    840                 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)];
    841             }
    842 
    843             if (len < 32) {
    844                 fldbuf[i] &= ((1 << len) - 1);
    845             }
    846 
    847             i++;
    848         }
    849     } else {
    850         i = (len - 1) / 32;
    851 
    852         while (len > 0) {
    853             assert(i >= 0);
    854 
    855             fldbuf[i] = 0;
    856 
    857             do {
    858                 fldbuf[i] =
    859                     (fldbuf[i] << 1) |
    860                     ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >>
    861                       (bp & (32 - 1))) & 1);
    862                 len--;
    863                 bp++;
    864             } while (len & (32 - 1));
    865 
    866             i--;
    867         }
    868     }
    869 
    870     return fldbuf;
    871 }
    872 
    873 /*
    874  * Function:    soc_meminfo_fieldinfo_field32_get
    875  * Purpose:      Get a <=32 bit field out of a memory entry
    876  * Returns:      The value of the field
    877  */
    878 uint32
    879 soc_meminfo_fieldinfo_field32_get(soc_mem_info_t *meminfo,
    880                                   void *entry,
    881                                   soc_field_info_t *fieldinfo) 
    882 {
    883     uint32              value;
    884 
    885     /*
    886      * COVERITY
    887      *
    888      * We do this intentionally to use the generic function
    889      * soc_meminfo_fieldinfo_field_get() which does the necessary handling.
    890  */
    891     /* coverity[address_of] */
    892     /* coverity[callee_ptr_arith] */
    893     soc_meminfo_fieldinfo_field_get(entry, meminfo, fieldinfo, &value);
    894 
    895     return value;
    896 }
    897 
    898 /*
    899  * Function:    
    900  *     soc_meminfo_fieldinfo_field64_get
    901  * Purpose:  
    902  *     Get a field in a memory for a uint64 type
    903  * Parameters: 
    904  *     unit  - (IN) BCM device number. 
    905  *     meminfo - (IN) direct reference to memory description
    906  *     entry - (IN) HW entry buffer.
    907  *     fieldinfo - direct reference to field description - (IN)
    908  *     val64 - (OUT) SW uint64 field buffer.
    909  * Returns:      void
    910  */
    911 void
    912 soc_meminfo_fieldinfo_field64_get(soc_mem_info_t *meminfo,
    913                                   void *entry,
    914                                   soc_field_info_t *fieldinfo,
    915                                   uint64 *val64)
    916 {
    917     uint32              val64_field[2] = {0, 0};
    918 
    919     soc_meminfo_fieldinfo_field_get(entry, meminfo,
    920                                     fieldinfo, val64_field);
    921 
    922     COMPILER_64_SET(*val64, val64_field[1], val64_field[0]);
    923 }
    924 
    925 /*
    926  * Function:      soc_meminfo_field_get
    927  * Purpose:       Get a memory field without reference to chip.
    928  * Parameters:    meminfo   --  direct reference to memory description
    929  */
    930 uint32 *
    931 soc_meminfo_field_get(soc_mem_t mem, soc_mem_info_t *meminfo,
    932                       const uint32 *entbuf, soc_field_t field, uint32 *fldbuf,
    933                       uint32 fldbuf_size) /* The number of uint32s in fldbuf */
    934 {
    935     soc_field_info_t    *fieldinfo;
    936     int                 i, wp, bp, len;
    937 
    938     SOC_FIND_FIELD(field,
    939                    meminfo->fields,
    940                    meminfo->nFields,
    941                    fieldinfo);
    942     if (NULL == fieldinfo) {
    943 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    944         LOG_CLI((BSL_META("mem %s field %s is invalid\n"),
    945                  soc_mem_name[mem], soc_fieldnames[field]));
    946 #endif
    947         assert(fieldinfo);
    948     }
    949 
    950     /*
    951      * COVERITY
    952      *
    953      * assert validates the input for NULL
    954      */
    955     /* coverity[var_deref_op : FALSE] */
    956     bp = fieldinfo->bp;
    957     len = fieldinfo->len; 
    958     assert(len / 32 <= fldbuf_size); /* assert we do not write beyond the end of the output buffer */
    959 
    960     if (len == 1) {     /* special case single bits */
    961         wp = bp / 32;
    962         bp = bp & (32 - 1);
    963         if (entbuf[FIX_MEM_ORDER_E(wp, meminfo)] & (1<<bp)) {
    964             fldbuf[0] = 1;
    965         } else {
    966             fldbuf[0] = 0;
    967         }
    968         return fldbuf;
    969     }
    970 
    971     if (fieldinfo->flags & SOCF_LE) {
    972         wp = bp / 32;
    973         bp = bp & (32 - 1);
    974         i = 0;
    975 
    976         for (; len > 0; len -= 32) {
    977             if (bp) {
    978                 fldbuf[i] =
    979                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] >> bp &
    980                     ((1 << (32 - bp)) - 1);
    981                 if ( len > (32 - bp) ) {
    982                     fldbuf[i] |= entbuf[FIX_MEM_ORDER_E(wp, meminfo)] <<
    983                         (32 - bp);
    984                 }
    985             } else {
    986                 fldbuf[i] = entbuf[FIX_MEM_ORDER_E(wp++, meminfo)];
    987             }
    988 
    989             if (len < 32) {
    990                 fldbuf[i] &= ((1 << len) - 1);
    991             }
    992 
    993             i++;
    994         }
    995     } else {
    996         i = (len - 1) / 32;
    997 
    998         while (len > 0) {
    999             assert(i >= 0);
   1000 
   1001             fldbuf[i] = 0;
   1002 
   1003             do {
   1004                 fldbuf[i] =
   1005                     (fldbuf[i] << 1) |
   1006                     ((entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >>
   1007                       (bp & (32 - 1))) & 1);
   1008                 len--;
   1009                 bp++;
   1010             } while (len & (32 - 1));
   1011 
   1012             i--;
   1013         }
   1014     }
   1015 
   1016     return fldbuf;
   1017 }
   1018 
   1019 /*
   1020  * Function:      _soc_field_value_chop
   1021  * Purpose:       Chop field value so it will fit into a memory field. 
   1022  * Parameters:    fieldinfo --  (IN)Direct reference to field description.
   1023  *                value     --  (IN)Value to be checked.   
   1024  * Returns: 
   1025  *    SOC_E_XXX
   1026  */
   1027 STATIC int
   1028 _soc_field_value_chop(soc_field_info_t *fieldinfo, uint32 *value)
   1029 {
   1030     uint32      mask;    /* Value mask                      */
   1031     uint16      len;     /* Bits in field                   */
   1032     int         idx;     /* Iteration index.                */
   1033 
   1034     if ((NULL == fieldinfo) || (NULL == value)) {
   1035         return (SOC_E_PARAM);
   1036     }
   1037 
   1038     idx = (fieldinfo->len - 1) >> 5;
   1039     len = fieldinfo->len % 32;
   1040 
   1041     if (len) {
   1042         mask = (1 << len) - 1;
   1043         value[idx] &=  mask;
   1044     }
   1045     return (SOC_E_NONE);
   1046 }
   1047 
   1048 /*
   1049  * Function:
   1050  *      soc_mem_field_pbmp_fit
   1051  * Purpose:
   1052  *      Check if pbmp fits into a memory field.
   1053  * Parameters: 
   1054  *      unit    - (IN)SOC unit number.
   1055  *      mem     - (IN)Memory id.
   1056  *      field   - (IN)Field id.
   1057  *      value   - (IN)Value to be checked. 
   1058  * Return:     
   1059  *      SOC_E_PARAM -If value is too big for field, or some other error.
   1060  *      SOC_E_NONE  -Otherwise.
   1061  */
   1062 int 
   1063 soc_mem_field_pbmp_fit(int unit, soc_mem_t mem, 
   1064                        soc_field_t field, uint32 *value)
   1065 {
   1066     soc_mem_info_t      *meminfo;
   1067     soc_field_info_t    *fieldinfo;
   1068 
   1069     /* Get memory info. */
   1070     if (!SOC_MEM_IS_VALID(unit, mem)){
   1071        return SOC_E_PARAM;
   1072     }
   1073     meminfo = &SOC_MEM_INFO(unit, mem);
   1074 
   1075     /* Get field properties. */
   1076     SOC_FIND_FIELD(field,
   1077                    meminfo->fields,
   1078                    meminfo->nFields,
   1079                    fieldinfo);
   1080     if (!fieldinfo) {
   1081         return SOC_E_PARAM;
   1082     }
   1083 
   1084     return (_soc_field_value_fit(fieldinfo, value)) ? SOC_E_NONE : SOC_E_PARAM;
   1085 }
   1086 
   1087 /*
   1088  * Function:
   1089  *      soc_mem_field32_fit
   1090  * Purpose:
   1091  *      Check if uint32 value fits into a memory field.
   1092  * Parameters: 
   1093  *      unit    - (IN)SOC unit number.
   1094  *      mem     - (IN)Memory id.
   1095  *      field   - (IN)Field id.
   1096  *      value   - (IN)Value to be checked. 
   1097  * Return:     
   1098  *      SOC_E_PARAM -If value is too big for field, or some other error.
   1099  *      SOC_E_NONE  -Otherwise.
   1100  */
   1101 int 
   1102 soc_mem_field32_fit(int unit, soc_mem_t mem, 
   1103                        soc_field_t field, uint32 value)
   1104 {
   1105     soc_mem_info_t      *meminfo;
   1106     soc_field_info_t    *fieldinfo;
   1107 
   1108 #ifdef BCM_TRIDENT3_SUPPORT
   1109     if (soc_feature(unit, soc_feature_flex_flow)) {
   1110         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1111             return _soc_mem_view_field32_fit(unit, mem, field, value);
   1112         }
   1113     }
   1114 #endif
   1115 
   1116     /* Get memory info. */
   1117     if (!SOC_MEM_IS_VALID(unit, mem)){
   1118        return SOC_E_PARAM;
   1119     }
   1120     meminfo = &SOC_MEM_INFO(unit, mem);
   1121 
   1122     /* Get field properties. */
   1123     SOC_FIND_FIELD(field,
   1124                    meminfo->fields,
   1125                    meminfo->nFields,
   1126                    fieldinfo);
   1127     if (!fieldinfo) {
   1128         return (SOC_E_PARAM);
   1129     }
   1130 
   1131     /* coverity[callee_ptr_arith : FALSE] */
   1132     return (_soc_field_value_fit(fieldinfo, &value)) ?
   1133         SOC_E_NONE : SOC_E_PARAM;
   1134 }
   1135 
   1136 /*
   1137  * Function:     soc_memacc_field_set
   1138  * Purpose:      Set a <=32 bit field out of a memory entry
   1139  */
   1140 void
   1141 soc_memacc_field_set(soc_memacc_t *memacc, uint32 *entbuf, uint32 *fldbuf)
   1142 {
   1143     soc_mem_info_t *meminfo = memacc->minfo;
   1144     soc_field_info_t *fieldinfo = memacc->finfo;
   1145     uint32              mask;
   1146     int                 i, wp, bp, len;
   1147 
   1148     if (NULL == fieldinfo) {
   1149         assert(fieldinfo);
   1150     }
   1151 
   1152     /* Make sure value fits into the field. */
   1153     /*
   1154      * COVERITY
   1155      *
   1156      * assert validates the input for NULL
   1157      */
   1158     /* coverity[var_deref_model : FALSE] */
   1159     if (!_soc_field_value_fit(fieldinfo, fldbuf)) {
   1160         assert(_soc_field_value_fit(fieldinfo, fldbuf)); 
   1161     }
   1162 
   1163     bp = fieldinfo->bp;
   1164 
   1165     if (fieldinfo->flags & SOCF_LE) {
   1166         wp = bp / 32;
   1167         bp = bp & (32 - 1);
   1168         i = 0;
   1169 
   1170         for (len = fieldinfo->len; len > 0; len -= 32) {
   1171             if (bp) {
   1172                 if (len < 32) {
   1173                     mask = (1 << len) - 1;
   1174                 } else {
   1175                     mask = -1;
   1176                 }
   1177 
   1178                 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp);
   1179                 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   1180                 if (len > (32 - bp)) {
   1181                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &=
   1182                         ~(mask >> (32 - bp));
   1183                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |=
   1184                         fldbuf[i] >> (32 - bp) & ((1 << bp) - 1);
   1185                 }
   1186             } else {
   1187                 if (len < 32) {
   1188                     mask = (1 << len) - 1;
   1189                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask;
   1190                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |=
   1191                         fldbuf[i] << bp;
   1192                 } else {
   1193                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i];
   1194                 }
   1195             }
   1196 
   1197             i++;
   1198         }
   1199     } else {                           /* Big endian: swap bits */
   1200         len = fieldinfo->len;
   1201 
   1202         while (len > 0) {
   1203             len--;
   1204             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &=
   1205                 ~(1 << (bp & (32-1)));
   1206             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |=
   1207                 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1));
   1208             bp++;
   1209         }
   1210     }
   1211 }
   1212 /*
   1213  * Function:     soc_memacc_field32_set
   1214  * Purpose:      Set a <=32 bit field out of a memory entry
   1215  */
   1216 void
   1217 soc_memacc_field32_set(soc_memacc_t *memacc, void *entry, uint32 value)
   1218 {
   1219     /*
   1220      * COVERITY
   1221      *
   1222      * We do this intentionally to use the generic function
   1223      * soc_memacc_field_set() which does the necessary handling.
   1224  */
   1225     /* coverity[address_of] */
   1226     /* coverity[callee_ptr_arith] */
   1227     soc_memacc_field_set(memacc, entry, &value);
   1228 }
   1229 
   1230 /*
   1231  * Function:     soc_memacc_field64_set
   1232  * Purpose:      Set a <=64 bit field out of a memory entry
   1233  */
   1234 void
   1235 soc_memacc_field64_set(soc_memacc_t *memacc, void *entry, uint64 val64)
   1236 {
   1237     uint32              val64_field[2];
   1238 
   1239     val64_field[0] = COMPILER_64_LO(val64);
   1240     val64_field[1] = COMPILER_64_HI(val64);
   1241 
   1242     soc_memacc_field_set(memacc, entry, val64_field);
   1243 }
   1244 
   1245 /*
   1246  * Function:     soc_memacc_mac_addr_set
   1247  * Purpose:      Set a mac address field in a memory from a mac addr type
   1248  */
   1249 void
   1250 soc_memacc_mac_addr_set(soc_memacc_t *memacc, void *entry,
   1251                         const sal_mac_addr_t mac)
   1252 {
   1253     uint32              mac_field[2];
   1254 
   1255     SAL_MAC_ADDR_TO_UINT32(mac, mac_field);
   1256 
   1257     soc_memacc_field_set(memacc, entry, mac_field);
   1258 }
   1259 
   1260 /*
   1261  * Function:    soc_meminfo_fieldinfo_field_set
   1262  * Purpose:      Set a <=32 bit field out of a memory entry
   1263  */
   1264 void
   1265 soc_meminfo_fieldinfo_field_set(uint32 *entbuf,
   1266                                   soc_mem_info_t *meminfo,
   1267                                   soc_field_info_t *fieldinfo, 
   1268                                   uint32 *fldbuf)
   1269 {
   1270     uint32              mask;
   1271     int                 i, wp, bp, len;
   1272 
   1273     if (NULL == fieldinfo) {
   1274         assert(fieldinfo);
   1275     }
   1276 
   1277     /* Make sure value fits into the field. */
   1278     /*
   1279      * COVERITY
   1280      *
   1281      * assert validates the input for NULL
   1282      */
   1283     /* coverity[var_deref_model : FALSE] */
   1284     if (!_soc_field_value_fit(fieldinfo, fldbuf)) {
   1285         assert(_soc_field_value_fit(fieldinfo, fldbuf)); 
   1286     }
   1287 
   1288     bp = fieldinfo->bp;
   1289 
   1290     if (fieldinfo->flags & SOCF_LE) {
   1291         wp = bp / 32;
   1292         bp = bp & (32 - 1);
   1293         i = 0;
   1294 
   1295         for (len = fieldinfo->len; len > 0; len -= 32) {
   1296             if (bp) {
   1297                 if (len < 32) {
   1298                     mask = (1 << len) - 1;
   1299                 } else {
   1300                     mask = -1;
   1301                 }
   1302 
   1303                 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp);
   1304                 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   1305                 if (len > (32 - bp)) {
   1306                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp));
   1307                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |=
   1308                         fldbuf[i] >> (32 - bp) & ((1 << bp) - 1);
   1309                 }
   1310             } else {
   1311                 if (len < 32) {
   1312                     mask = (1 << len) - 1;
   1313                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask;
   1314                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   1315                 } else {
   1316                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i];
   1317                 }
   1318             }
   1319 
   1320             i++;
   1321         }
   1322     } else {                           /* Big endian: swap bits */
   1323         len = fieldinfo->len;
   1324 
   1325         while (len > 0) {
   1326             len--;
   1327             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1)));
   1328             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |=
   1329                 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1));
   1330             bp++;
   1331         }
   1332     }
   1333 }
   1334 /*
   1335  * Function:    soc_meminfo_fieldinfo_field32_set
   1336  * Purpose:      Set a <=32 bit field out of a memory entry
   1337  */
   1338 void
   1339 soc_meminfo_fieldinfo_field32_set(soc_mem_info_t *meminfo,
   1340                                   void *entry,
   1341                                   soc_field_info_t *fieldinfo, 
   1342                                   uint32 value)
   1343 {
   1344     /*
   1345      * COVERITY
   1346      *
   1347      * We do this intentionally to use the generic function
   1348      * soc_meminfo_fieldinfo_field_set() which does the necessary handling.
   1349  */
   1350     /* coverity[address_of] */
   1351     /* coverity[callee_ptr_arith] */
   1352     soc_meminfo_fieldinfo_field_set(entry, meminfo, fieldinfo, &value);
   1353 }
   1354 
   1355 /*
   1356  * Function:    soc_meminfo_fieldinfo_field64_get
   1357  * Purpose:      Get a <=64 bit field out of a memory entry
   1358  */
   1359 void
   1360 soc_meminfo_fieldinfo_field64_set(soc_mem_info_t *meminfo,
   1361                                   void *entry,
   1362                                   soc_field_info_t *fieldinfo,
   1363                                   uint64 val64)
   1364 {
   1365     uint32              val64_field[2];
   1366 
   1367     val64_field[0] = COMPILER_64_LO(val64);
   1368     val64_field[1] = COMPILER_64_HI(val64);
   1369 
   1370     soc_meminfo_fieldinfo_field_set(entry, meminfo,
   1371                                     fieldinfo, val64_field);
   1372 }
   1373 
   1374 /*
   1375  * Function:      soc_meminfo_field_set
   1376  * Purpose:       Set a memory field without reference to chip.
   1377  * Parameters:    meminfo   --  direct reference to memory description
   1378  */
   1379 void
   1380 soc_meminfo_field_set(soc_mem_t mem, soc_mem_info_t *meminfo, uint32 *entbuf,
   1381                       soc_field_t field, uint32 *fldbuf)
   1382 {
   1383     soc_field_info_t    *fieldinfo;
   1384     uint32              mask;
   1385     int                 i, wp, bp, len;
   1386 
   1387     SOC_FIND_FIELD(field,
   1388                    meminfo->fields,
   1389                    meminfo->nFields,
   1390                    fieldinfo);
   1391     if (NULL == fieldinfo) {
   1392 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1393         LOG_CLI((BSL_META("mem %s field %s is invalid\n"),
   1394                  soc_mem_name[mem], soc_fieldnames[field]));
   1395 #endif
   1396         assert(fieldinfo);
   1397     }
   1398 
   1399     /* Make sure value fits into the field. */
   1400     /*
   1401      * COVERITY
   1402      *
   1403      * assert validates the input for NULL
   1404      */
   1405     /* coverity[var_deref_model : FALSE] */
   1406     if (!_soc_field_value_fit(fieldinfo, fldbuf)) {
   1407 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1408         LOG_CLI((BSL_META("mem %s field %s value does not fit\n"),
   1409                  soc_mem_name[mem], soc_fieldnames[field]));
   1410 #endif
   1411         assert(_soc_field_value_fit(fieldinfo, fldbuf)); 
   1412     }
   1413 
   1414     bp = fieldinfo->bp;
   1415 
   1416     if (fieldinfo->flags & SOCF_LE) {
   1417         wp = bp / 32;
   1418         bp = bp & (32 - 1);
   1419         i = 0;
   1420 
   1421         for (len = fieldinfo->len; len > 0; len -= 32) {
   1422             if (bp) {
   1423                 if (len < 32) {
   1424                     mask = (1 << len) - 1;
   1425                 } else {
   1426                     mask = -1;
   1427                 }
   1428 
   1429                 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp);
   1430                 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   1431                 if (len > (32 - bp)) {
   1432                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp));
   1433                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |=
   1434                         fldbuf[i] >> (32 - bp) & ((1 << bp) - 1);
   1435                 }
   1436             } else {
   1437                 if (len < 32) {
   1438                     mask = (1 << len) - 1;
   1439                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask;
   1440                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   1441                 } else {
   1442                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i];
   1443                 }
   1444             }
   1445 
   1446             i++;
   1447         }
   1448     } else {                           /* Big endian: swap bits */
   1449         len = fieldinfo->len;
   1450 
   1451         while (len > 0) {
   1452             len--;
   1453             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1)));
   1454             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |=
   1455                 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1));
   1456             bp++;
   1457         }
   1458     }
   1459 }
   1460 /*
   1461  * Function:
   1462  *      soc_mem_field_valid
   1463  * Purpose:
   1464  *      Verify if field is valid & present in memory
   1465  * Parameters:
   1466  *      mem     - (IN)Memory id.
   1467  *      field   - (IN)Field id.
   1468  * Return:
   1469  *      TRUE  -If field is present & valid.
   1470  *      FALSE -Otherwise.
   1471  */
   1472 int
   1473 soc_mem_field_valid(int unit, soc_mem_t mem, soc_field_t field)
   1474 {
   1475     soc_mem_info_t  *meminfo;
   1476     soc_field_info_t    *finfop; /* Field information structure. */
   1477 
   1478 #ifdef BCM_TRIDENT3_SUPPORT
   1479     if (soc_feature(unit, soc_feature_flex_flow)) {
   1480         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1481             return _soc_mem_view_field_valid(unit, mem, field);
   1482         }
   1483     }
   1484 #endif
   1485 
   1486     /* Verify that memory is present on the device. */
   1487     if (!SOC_MEM_IS_VALID(unit, mem))  {
   1488         return FALSE;
   1489     }
   1490 
   1491     meminfo = &SOC_MEM_INFO(unit, mem);
   1492     SOC_FIND_FIELD(field,
   1493                    meminfo->fields,
   1494                    meminfo->nFields,
   1495                    finfop);
   1496     return (finfop != NULL) ? TRUE : FALSE;
   1497 }
   1498 
   1499 /*
   1500  * Function:    soc_mem_field_get
   1501  * Purpose:     Get a memory field
   1502  * Parameters:  unit - device
   1503  *              mem - table
   1504  *              entbuf - table entry buffer
   1505  *              field - which field to get
   1506  *              fldbuf - field buffer
   1507  */
   1508 uint32 *
   1509 soc_mem_field_get(int unit, soc_mem_t mem, const uint32 *entbuf,
   1510                   soc_field_t field, uint32 *fldbuf)
   1511 {
   1512     soc_mem_info_t *meminfo;
   1513 
   1514 #ifdef BCM_TRIDENT3_SUPPORT
   1515     if (soc_feature(unit, soc_feature_flex_flow)) {
   1516         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1517             return _soc_mem_view_field_get(unit, mem, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS);
   1518         }
   1519     }
   1520 #endif
   1521 
   1522     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1523 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1524         LOG_CLI((BSL_META_U(unit,
   1525                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1526 #endif
   1527         assert(SOC_MEM_IS_VALID(unit, mem));
   1528     }
   1529 
   1530     meminfo = &SOC_MEM_INFO(unit, mem);
   1531 
   1532     return soc_meminfo_field_get(mem, meminfo, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS);
   1533 }
   1534 
   1535 /*
   1536  * Function:    soc_mem_field_set
   1537  * Purpose:     Set a memory field
   1538  * Parameters:  unit - device
   1539  *              mem - table
   1540  *              entbuf - table entry buffer
   1541  *              field - which field to set
   1542  *              fldbuf - field buffer
   1543  */
   1544 void
   1545 soc_mem_field_set(int unit, soc_mem_t mem, uint32 *entbuf, soc_field_t field,
   1546                   uint32 *fldbuf)
   1547 {
   1548     soc_mem_info_t *meminfo;
   1549 
   1550 #ifdef BCM_TRIDENT3_SUPPORT
   1551     if (soc_feature(unit, soc_feature_flex_flow)) {
   1552         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1553             _soc_mem_view_field_set(unit, mem, entbuf, field, fldbuf);
   1554             return;
   1555         }
   1556     }
   1557 #endif
   1558 
   1559     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1560 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1561         LOG_CLI((BSL_META_U(unit,
   1562                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1563 #endif
   1564         assert(SOC_MEM_IS_VALID(unit, mem));
   1565     }
   1566 
   1567     meminfo = &SOC_MEM_INFO(unit, mem);
   1568 
   1569     soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf);
   1570 }
   1571 
   1572 
   1573 /*
   1574  * Function:    soc_mem_field_width_fit_set
   1575  * Purpose:     Set a memory field
   1576  *              Chop the value if fld_buf doesn't fit into the entry.
   1577  * Parameters:  unit - device
   1578  *              mem - table
   1579  *              entbuf - table entry buffer
   1580  *              field - which field to set
   1581  *              fldbuf - field buffer
   1582  */
   1583 void
   1584 soc_mem_field_width_fit_set(int unit, soc_mem_t mem, uint32 *entbuf, 
   1585                             soc_field_t field, uint32 *fldbuf)
   1586 {
   1587     soc_mem_info_t *meminfo;
   1588     soc_field_info_t    *fieldinfo;
   1589 
   1590     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1591 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1592         LOG_CLI((BSL_META_U(unit,
   1593                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1594 #endif
   1595         assert(SOC_MEM_IS_VALID(unit, mem));
   1596     }
   1597 
   1598     meminfo = &SOC_MEM_INFO(unit, mem);
   1599 
   1600     SOC_FIND_FIELD(field,
   1601                    meminfo->fields,
   1602                    meminfo->nFields,
   1603                    fieldinfo);
   1604     if (NULL == fieldinfo) {
   1605 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1606         LOG_CLI((BSL_META_U(unit,
   1607                             "mem %s field %s is invalid\n"),
   1608                  soc_mem_name[mem], soc_fieldnames[field]));
   1609 #endif
   1610         assert(fieldinfo);
   1611     }
   1612 
   1613     /* Chop the value so it fits into the field. */
   1614     _soc_field_value_chop(fieldinfo, fldbuf);
   1615 
   1616     soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf);
   1617 }
   1618 
   1619 /*
   1620  * Function:     soc_mem_field32_get
   1621  * Purpose:      Get a <=32 bit field out of a memory entry
   1622  * Returns:      The value of the field
   1623  */
   1624 uint32
   1625 soc_mem_field32_get(int unit, soc_mem_t mem, const void *entbuf,
   1626                     soc_field_t field)
   1627 {
   1628     uint32              value;
   1629 
   1630 #ifdef BCM_TRIDENT3_SUPPORT
   1631     if (soc_feature(unit, soc_feature_flex_flow)) {
   1632         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1633             _soc_mem_view_field_get(unit, mem, entbuf, field, &value, 1);
   1634             return value;
   1635         }
   1636     }
   1637 #endif
   1638 
   1639     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1640 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1641         LOG_CLI((BSL_META_U(unit, "mem %s is invalid\n"), soc_mem_name[mem]));
   1642 #endif
   1643         assert(SOC_MEM_IS_VALID(unit, mem));
   1644     }
   1645     soc_meminfo_field_get(mem, &SOC_MEM_INFO(unit, mem), entbuf, field, &value, 1);
   1646 
   1647     return value;
   1648 }
   1649 
   1650 /*
   1651  * Function:     soc_mem_field32_get_def
   1652  * Purpose:      Get a <=32 bit field out of a memory entry,
   1653  *               or a default value if the memory or field does not exist
   1654  * Returns:      The value of the field, or the given default value
   1655  */
   1656 uint32
   1657 soc_mem_field32_get_def(int         unit,
   1658             soc_mem_t   mem,
   1659             const void  *entbuf,
   1660             soc_field_t field,
   1661             uint32      def
   1662             )
   1663 {
   1664     if (soc_mem_field_valid(unit, mem, field)) {
   1665     uint32 value;
   1666 
   1667     soc_mem_field_get(unit, mem, entbuf, field, &value);
   1668     
   1669     return value;
   1670     }
   1671 
   1672     return (def);
   1673 }
   1674 
   1675 /*
   1676  * Function:     soc_mem_field32_set
   1677  * Purpose:      Set a <=32 bit field out of a memory entry
   1678  * Returns:      void
   1679  */
   1680 void
   1681 soc_mem_field32_set(int unit, soc_mem_t mem, void *entbuf,
   1682                     soc_field_t field, uint32 value)
   1683 {
   1684     soc_mem_field_set(unit, mem, entbuf, field, &value);
   1685 }
   1686 
   1687 /*
   1688  * Function:     soc_mem_field32_force
   1689  * Purpose:      Set a <=32 bit field out of a memory entry
   1690  *               without checking for field width.  Lower
   1691  *               bits of value are taken.
   1692  * Returns:      void
   1693  */
   1694 void
   1695 soc_mem_field32_force(int unit, soc_mem_t mem, void *entry,
   1696                       soc_field_t field, uint32 value)
   1697 {
   1698     soc_mem_info_t      *meminfo;
   1699 
   1700     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1701 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1702         LOG_CLI((BSL_META_U(unit,
   1703                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1704 #endif
   1705         assert(SOC_MEM_IS_VALID(unit, mem));
   1706     }
   1707 
   1708     meminfo = &SOC_MEM_INFO(unit, mem);
   1709 
   1710     soc_meminfo_field32_force(mem, meminfo, entry, field, value);
   1711 }
   1712 
   1713 /*
   1714  * Function:     soc_meminfo_field32_force
   1715  * Purpose:      Set a <=32 bit field out of a memory entry
   1716  *               without checking for field width.  Lower
   1717  *               bits of value are taken.
   1718  * Returns:      Value put in field.
   1719  */
   1720 void
   1721 soc_meminfo_field32_force(soc_mem_t mem, soc_mem_info_t *meminfo, void *entry,
   1722                           soc_field_t field, uint32 value)
   1723 {
   1724     soc_field_info_t    *fieldinfo;
   1725     int                 len;
   1726 
   1727     SOC_FIND_FIELD(field,
   1728                    meminfo->fields,
   1729                    meminfo->nFields,
   1730                    fieldinfo);
   1731     if (NULL == fieldinfo) {
   1732 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1733         LOG_CLI((BSL_META("mem %s field %s is invalid\n"),
   1734                  soc_mem_name[mem], soc_fieldnames[field]));
   1735 #endif
   1736         assert(fieldinfo);
   1737     }
   1738 
   1739     /*
   1740      * COVERITY
   1741      *
   1742      * assert validates the input for NULL
   1743      */
   1744     /* coverity[var_deref_opl : FALSE] */
   1745     len = fieldinfo->len;
   1746 
   1747     assert(len <= 32);
   1748 
   1749     if (len < 32) {                    /* Force value to fit in field width */
   1750         value &= (1 << len) - 1;
   1751     }
   1752 
   1753     /*
   1754      * COVERITY
   1755      *
   1756      * We do this intentionally to use the generic function
   1757      * soc_meminfo_field_set() which does the necessary handling.
   1758  */
   1759     /* coverity[address_of] */
   1760     /* coverity[callee_ptr_arith] */
   1761     soc_meminfo_field_set(mem, meminfo, entry, field, &value);
   1762 }
   1763 
   1764 /*
   1765  * Function:    soc_mem_mask_field_get
   1766  * Purpose:     Get a memory mask field
   1767  * Parameters:  unit - device
   1768  *              mem - table
   1769  *              entbuf - table entry buffer
   1770  *              field - which field to get
   1771  *              fldbuf - field buffer
   1772  */
   1773 uint32 *
   1774 soc_mem_mask_field_get(int unit, soc_mem_t mem, const uint32 *entbuf,
   1775                        soc_field_t field, uint32 *fldbuf)
   1776 {
   1777     soc_mem_info_t *meminfo;
   1778     uint32 *rfldbuf;
   1779 #if defined(BCM_ESW_SUPPORT)
   1780     int dc_val, len, i;
   1781 #endif
   1782 
   1783     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1784 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1785         LOG_CLI((BSL_META_U(unit,
   1786                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1787 #endif
   1788         assert(SOC_MEM_IS_VALID(unit, mem));
   1789     }
   1790 
   1791     meminfo = &SOC_MEM_INFO(unit, mem);
   1792 
   1793     rfldbuf = soc_meminfo_field_get(mem, meminfo, entbuf, field, fldbuf, SOC_MAX_MEM_WORDS);
   1794 
   1795 #if defined(BCM_ESW_SUPPORT)
   1796     soc_tcam_get_info(unit, NULL, NULL, &dc_val, NULL);
   1797     if (dc_val) {
   1798         /* TCAM mask polarity is different than software representation */
   1799         i = 0;
   1800         len = soc_mem_field_length(unit, mem, field);
   1801         for (; len > 0; len -= 32) {
   1802             rfldbuf[i++] ^= 0xffffffff;
   1803         }
   1804         if (len & 0x1f) {
   1805             rfldbuf[i - 1] &= (1 << (len & 0x1f)) - 1;
   1806         }
   1807     }
   1808 #endif
   1809 
   1810     return rfldbuf;
   1811 }
   1812 
   1813 /*
   1814  * Function:    soc_mem_mask_field_set
   1815  * Purpose:     Set a memory mask field
   1816  * Parameters:  unit - device
   1817  *              mem - table
   1818  *              entbuf - table entry buffer
   1819  *              field - which field to set
   1820  *              fldbuf - field buffer
   1821  */
   1822 void
   1823 soc_mem_mask_field_set(int unit, soc_mem_t mem, uint32 *entbuf,
   1824                        soc_field_t field, uint32 *fldbuf)
   1825 {
   1826     soc_mem_info_t *meminfo;
   1827 #if defined(BCM_ESW_SUPPORT)
   1828     uint32 buf[SOC_MAX_MEM_FIELD_WORDS];
   1829     int dc_val, len, i, rv;
   1830 #endif
   1831 
   1832     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1833 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   1834         LOG_CLI((BSL_META_U(unit,
   1835                             "mem %s is invalid\n"), soc_mem_name[mem]));
   1836 #endif
   1837         assert(SOC_MEM_IS_VALID(unit, mem));
   1838     }
   1839 
   1840     meminfo = &SOC_MEM_INFO(unit, mem);
   1841 
   1842 #if defined(BCM_ESW_SUPPORT)
   1843     rv = soc_tcam_get_info(unit, NULL, NULL, &dc_val, NULL);
   1844     if (SOC_SUCCESS(rv) && dc_val) {
   1845         /* TCAM mask polarity is different than software representation */
   1846         i = 0;
   1847         len = soc_mem_field_length(unit, mem, field);
   1848         for (; len > 0; len -= 32) {
   1849             buf[i] = fldbuf[i] ^ 0xffffffff;
   1850             i++;
   1851         }
   1852         if (len & 0x1f) {
   1853             buf[i - 1] &= (1 << (len & 0x1f)) - 1;
   1854         }
   1855         soc_meminfo_field_set(mem, meminfo, entbuf, field, buf);
   1856     }
   1857     else 
   1858 #endif
   1859     {
   1860         soc_meminfo_field_set(mem, meminfo, entbuf, field, fldbuf);
   1861     }
   1862 
   1863 }
   1864 
   1865 /*
   1866  * Function:    soc_mem_mask_field32_get
   1867  * Purpose:     Get a <= 32 bit mask field out of a memory entry
   1868  * Returns:     The value of the mask field
   1869  */
   1870 uint32
   1871 soc_mem_mask_field32_get(int unit, soc_mem_t mem, const void *entbuf,
   1872                          soc_field_t field)
   1873 {
   1874     uint32 value;
   1875     
   1876     /* coverity[callee_ptr_arith : FALSE] */
   1877     soc_mem_mask_field_get(unit, mem, entbuf, field, &value);
   1878 
   1879     return value;
   1880 }
   1881 
   1882 /*
   1883  * Function:    soc_mem_mask_field32_set
   1884  * Purpose:     Set a <= 32 bit mask field of a memory entry
   1885  * Returns:     void
   1886  */
   1887 void
   1888 soc_mem_mask_field32_set(int unit, soc_mem_t mem, void *entbuf,
   1889                          soc_field_t field, uint32 value)
   1890 {   /* coverity[callee_ptr_arith : FALSE] */ 
   1891     soc_mem_mask_field_set(unit, mem, entbuf, field, &value);
   1892 }
   1893 
   1894 
   1895 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT)
   1896 /*
   1897  * Function:   soc_mem_fields32_modify
   1898  * Purpose:    Modify the value of a fields in a memory.
   1899  * Parameters:
   1900  *       unit         - (IN) SOC unit number.
   1901  *       mem          - (IN) Memory.
   1902  *       index        - (IN) Memory entry index.
   1903  *       field_count  - (IN) Number of fields to modify.
   1904  *       fields       - (IN) Modified fields array.
   1905  *       values       - (IN) New value for each member of fields array.
   1906  * Returns:
   1907  *       SOC_E_XXX
   1908  */
   1909 int
   1910 soc_mem_fields32_modify(int unit, soc_mem_t mem, int index,
   1911                         int field_count, soc_field_t *fields, uint32 *values)
   1912 {
   1913     uint32 buf[SOC_MAX_MEM_WORDS];       /* Buffer to read memory entry. */
   1914     int idx;                             /* Iteration index.             */
   1915     int rv;                              /* Operation return status.     */
   1916     int value_changed = 0;               /* Flag of value changed comparing
   1917                                             between input and current reading*/
   1918 
   1919     /* Field count check before continue. */
   1920     if (field_count == 0) {
   1921         return (SOC_E_NONE);
   1922     }
   1923 
   1924     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
   1925 
   1926 #ifdef BCM_TRIDENT3_SUPPORT
   1927     if (soc_feature(unit, soc_feature_flex_flow)) {
   1928         if (SOC_MEM_IS_VIEW(unit, mem)) {
   1929             return _soc_mem_view_fields32_modify(unit, mem, index, field_count, fields, values);
   1930         }
   1931     }
   1932 #endif
   1933 
   1934     /* Check that memory is a valid one for this unit. */
   1935     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1936         return (SOC_E_UNAVAIL);
   1937     }
   1938 
   1939     /* Check entry index range. */
   1940     if ((index > soc_mem_index_max(unit, mem)) ||
   1941         (index < soc_mem_index_min(unit, mem))) {
   1942         return (SOC_E_PARAM);
   1943     }
   1944 
   1945     /*  Fields & values sanity check. */
   1946     for (idx = 0; idx < field_count; idx++) {
   1947         if ((NULL == fields + idx) || (NULL == values + idx)) {
   1948            /*
   1949             * COVERITY
   1950             * This is kept intentional for future use
   1951             * or as defensive statement.
   1952             */
   1953             /* coverity[dead_error_line] */
   1954             return (SOC_E_PARAM);
   1955         }
   1956 
   1957         /* Make sure value fits into memory field. */
   1958         SOC_IF_ERROR_RETURN
   1959             (soc_mem_field32_fit(unit, mem, fields[idx], values[idx]));
   1960     }
   1961 
   1962     /* Lock the memory. */
   1963     soc_mem_lock(unit, mem);
   1964     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, buf);
   1965     if (SOC_FAILURE(rv)) {
   1966         soc_mem_unlock(unit, mem);
   1967         return (rv);
   1968     }
   1969 
   1970     /* Set updated values in the buffer. */
   1971     for (idx = 0; idx < field_count; idx ++) {
   1972         if(values[idx] != soc_mem_field32_get(unit, mem, buf, fields[idx])) {
   1973             value_changed = 1;
   1974             soc_mem_field32_set(unit, mem, buf, fields[idx], values[idx]);
   1975         }
   1976     }
   1977 
   1978     /* Write buffer back to memory. */
   1979     if(value_changed) {
   1980         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, buf);
   1981     }
   1982 
   1983     soc_mem_unlock(unit, mem);
   1984     return (rv);
   1985 }
   1986 
   1987 /*
   1988  * Function:   soc_mem_field32_modify
   1989  * Purpose:    Modify the value of a field in a memory entry.
   1990  * Parameters:
   1991  *       unit      - (IN) SOC unit number.
   1992  *       mem       - (IN) Memory.
   1993  *       index     - (IN) Memory entry index number.
   1994  *       field     - (IN) Modified field.
   1995  *       value     - (IN) New field value.
   1996  * Returns:
   1997  *       SOC_E_XXX
   1998  */
   1999 int
   2000 soc_mem_field32_modify(int unit, soc_mem_t mem, int index,
   2001                        soc_field_t field, uint32 value)
   2002 {
   2003 
   2004     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
   2005     return soc_mem_fields32_modify(unit, mem, index, 1, &field, &value);
   2006 }
   2007 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT) */
   2008 
   2009 /*
   2010  * Function:    
   2011  *     soc_mem_field64_set
   2012  * Purpose:  
   2013  *     Set a field in a memory from a uint64 type
   2014  * Parameters: 
   2015  *     unit  - (IN) BCM device number. 
   2016  *     mem   - (IN) Memory id.
   2017  *     entry - (IN) HW entry buffer.
   2018  *     field - (IN) Memory field id. 
   2019  *     val64 - (IN) SW uint64 field buffer.
   2020  * Returns:      void
   2021  */
   2022 void
   2023 soc_mem_field64_set(int unit, soc_mem_t mem, void *entry,
   2024                     soc_field_t field, const uint64 val64)
   2025 {
   2026     uint32              val64_field[2];
   2027 
   2028     val64_field[0] = COMPILER_64_LO(val64);
   2029     val64_field[1] = COMPILER_64_HI(val64);
   2030 
   2031     soc_mem_field_set(unit, mem, entry, field, val64_field);
   2032 }
   2033 
   2034 /*
   2035  * Function:    
   2036  *     soc_mem_field64_get
   2037  * Purpose:  
   2038  *     Get a field in a memory for a uint64 type
   2039  * Parameters: 
   2040  *     unit  - (IN) BCM device number. 
   2041  *     mem   - (IN) Memory id.
   2042  *     entry - (IN) HW entry buffer.
   2043  *     field - (IN) Memory field id. 
   2044  *     val64 - (OUT) SW uint64 field buffer.
   2045  * Returns:      void
   2046  */
   2047 void
   2048 soc_mem_field64_get(int unit, soc_mem_t mem, void *entry,
   2049                     soc_field_t field, uint64 *val64)
   2050 {
   2051     uint32              val64_field[2] = {0, 0};
   2052 
   2053     soc_mem_field_get(unit, mem, entry, field, val64_field);
   2054 
   2055     COMPILER_64_SET(*val64, val64_field[1], val64_field[0]);
   2056 }
   2057 
   2058 /*
   2059  * Function:     soc_mem_mac_addr_set
   2060  * Purpose:      Set a mac address field in a memory from a mac addr type
   2061  * Returns:      void
   2062  */
   2063 void
   2064 soc_mem_mac_addr_set(int unit, soc_mem_t mem, void *entry,
   2065                      soc_field_t field, const sal_mac_addr_t mac)
   2066 {
   2067     uint32              mac_field[2];
   2068 
   2069     SAL_MAC_ADDR_TO_UINT32(mac, mac_field);
   2070 
   2071     soc_mem_field_set(unit, mem, entry, field, mac_field);
   2072 }
   2073 
   2074 /*
   2075  * Function:     soc_mem_mac_addr_get
   2076  * Purpose:      Get a mac address field in a memory from a mac addr type
   2077  * Returns:      SOC_E_xxx
   2078  */
   2079 void
   2080 soc_mem_mac_addr_get(int unit, soc_mem_t mem, const void *entry,
   2081                      soc_field_t field, sal_mac_addr_t mac)
   2082 {
   2083     uint32              mac_field[2];
   2084 
   2085     soc_mem_field_get(unit, mem, entry, field, mac_field);
   2086 
   2087     SAL_MAC_ADDR_FROM_UINT32(mac, mac_field);
   2088 }
   2089 
   2090 /*
   2091  * Function:     soc_mem_mac_address_set
   2092  * Purpose:      Set a MAC address field in a memory from a macaddr type
   2093  *               Use SOC_MEM_MAC_UPPER_ONLY to set upper 24 bits
   2094  *               or SOC_MEM_MAC_LOWER_ONLY to set lower 24 bits
   2095  *               Default to set 48 bits.
   2096  * Returns:      void
   2097  */
   2098 void
   2099 soc_mem_mac_address_set(int unit, soc_mem_t mem, void *entry,
   2100                         soc_field_t field, const sal_mac_addr_t mac, int flags)
   2101 {
   2102     uint32              mac_addr;
   2103 
   2104     if (flags == SOC_MEM_MAC_UPPER_ONLY) {
   2105         mac_addr = ((mac[0] << 16) | (mac[1] << 8)  | (mac[2] << 0));
   2106         soc_mem_field_set(unit, mem, entry, field, &mac_addr);
   2107     } else if (flags == SOC_MEM_MAC_LOWER_ONLY) {
   2108         mac_addr = ((mac[3] << 16) | (mac[4] << 8)  | (mac[5] << 0));
   2109         soc_mem_field_set(unit, mem, entry, field, &mac_addr);
   2110     } else {
   2111         soc_mem_mac_addr_set(unit, mem, entry, field, mac);
   2112     }
   2113 }
   2114 
   2115 /*
   2116  * Function:     soc_mem_mac_address_get
   2117  * Purpose:      Get a MAC address field in a memory from a mac addr type
   2118  *               Use SOC_MEM_MAC_UPPER_ONLY to get upper 64 bits
   2119  *               or SOC_MEM_MAC_LOWER_ONLY to get lower 64 bits
   2120  *               Default to get 48 bits.
   2121  * Returns:      void
   2122  */
   2123 void
   2124 soc_mem_mac_address_get(int unit, soc_mem_t mem, const void *entry,
   2125                         soc_field_t field, sal_mac_addr_t mac, int flags)
   2126 {
   2127     uint32              mac_field;
   2128 
   2129     if (flags == SOC_MEM_MAC_UPPER_ONLY) {
   2130         soc_mem_field_get(unit, mem, entry, field, &mac_field);
   2131         mac[0] = (uint8) (mac_field >> 16 & 0xff);
   2132         mac[1] = (uint8) (mac_field >> 8 & 0xff);
   2133         mac[2] = (uint8) (mac_field & 0xff);
   2134     } else if (flags == SOC_MEM_MAC_LOWER_ONLY) {
   2135         soc_mem_field_get(unit, mem, entry, field, &mac_field);
   2136         mac[3] = (uint8) (mac_field >> 16 & 0xff);
   2137         mac[4] = (uint8) (mac_field >> 8 & 0xff);
   2138         mac[5] = (uint8) (mac_field & 0xff);
   2139     } else {
   2140         soc_mem_mac_addr_get(unit, mem, entry, field, mac);
   2141     }
   2142 }
   2143 
   2144 /*
   2145  * Function:     soc_meminfo_mac_addr_set
   2146  * Purpose:      Set a mac address field in a memory from a mac addr type
   2147  * Returns:      void
   2148  */
   2149 void
   2150 soc_meminfo_mac_addr_set(soc_mem_t mem, soc_mem_info_t *meminfo, void *entry,
   2151                          soc_field_t field, const sal_mac_addr_t mac)
   2152 {
   2153     uint32              mac_field[2];
   2154 
   2155     SAL_MAC_ADDR_TO_UINT32(mac, mac_field);
   2156 
   2157     soc_meminfo_field_set(mem, meminfo, entry, field, mac_field);
   2158 }
   2159 
   2160 /*
   2161  * Function:    
   2162  *     soc_mem_ip6_addr_set
   2163  * Purpose:  
   2164  *     Set an IP6 address field in a memory from a ip6 addr type
   2165  * Parameters: 
   2166  *     unit  - (IN) BCM device number. 
   2167  *     mem   - (IN) Memory id.
   2168  *     entry - (IN) HW entry buffer.
   2169  *     field - (IN) Memory field id. 
   2170  *     ip6   - (IN) SW ip6 address buffer.
   2171  *     flags - (IN) SOC_MEM_IP6_UPPER_ONLY to set upper 64 bits
   2172  *                  SOC_MEM_IP6_LOWER_ONLY to set lower 64 bits
   2173  *                  SOC_MEM_IP6_UPPER_96BIT to set upper 96 bits
   2174  *                  0  - set all 128 bits.
   2175  * Returns:      void
   2176  */
   2177 void
   2178 soc_mem_ip6_addr_set(int unit, soc_mem_t mem, void *entry,
   2179                      soc_field_t field, const ip6_addr_t ip6, int flags)
   2180 {
   2181     uint32              ip6_field[4];
   2182 
   2183     
   2184 
   2185     if (flags == SOC_MEM_IP6_UPPER_ONLY) {
   2186         ip6_field[1] = ((ip6[0] << 24) | (ip6[1] << 16) |
   2187                         (ip6[2] << 8)  | (ip6[3] << 0));
   2188         ip6_field[0] = ((ip6[4] << 24) | (ip6[5] << 16) |
   2189                         (ip6[6] << 8)  | (ip6[7] << 0));
   2190         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2191     } else if (flags == SOC_MEM_IP6_LOWER_ONLY) {
   2192         ip6_field[3] = ((ip6[8] << 24) | (ip6[9] << 16) |
   2193                         (ip6[10] << 8) | (ip6[11] << 0));
   2194         ip6_field[2] = ((ip6[12] << 24)| (ip6[13] << 16) |
   2195                         (ip6[14] << 8) | (ip6[15] << 0));
   2196         soc_mem_field_set(unit, mem, entry, field, (uint32 *)&ip6_field[2]);
   2197     } else if (flags == SOC_MEM_IP6_UPPER_96BIT) {
   2198         ip6_field[2] = ((ip6[0] << 24) | (ip6[1] << 16) |
   2199                         (ip6[2] << 8)  | (ip6[3] << 0));
   2200         ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
   2201                         (ip6[6] << 8)  | (ip6[7] << 0));
   2202         ip6_field[0] = ((ip6[8] << 24) | (ip6[9] << 16) |
   2203                         (ip6[10] << 8) | (ip6[11] << 0));
   2204         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2205     } else if (flags == SOC_MEM_IP6_LOWER_96BIT) {
   2206         ip6_field[2] = ((ip6[4] << 24) | (ip6[5] << 16) |
   2207                         (ip6[6] << 8)  | (ip6[7] << 0));
   2208         ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) |
   2209                         (ip6[10] << 8) | (ip6[11] << 0));
   2210         ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) |
   2211                         (ip6[14] << 8) | (ip6[15] << 0));
   2212         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2213     } else if (flags == SOC_MEM_IP6_BITS_119_96) {
   2214         ip6_field[0] = ((ip6[1] << 16) | (ip6[2] << 8)  |
   2215                         (ip6[3] << 0));
   2216         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2217     } else if (flags == SOC_MEM_IP6_BITS_63_32) {
   2218         ip6_field[0] = ((ip6[8] << 24) | (ip6[9] << 16) |
   2219                         (ip6[10] << 8) | (ip6[11] << 0));
   2220         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2221     } else if (flags == SOC_MEM_IP6_BITS_31_0) {
   2222         ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) |
   2223                         (ip6[14] << 8) | (ip6[15] << 0));
   2224         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2225     } else {
   2226         ip6_field[3] = ((ip6[0] << 24) | (ip6[1] << 16) |
   2227                         (ip6[2] << 8)  | (ip6[3] << 0));
   2228         ip6_field[2] = ((ip6[4] << 24) | (ip6[5] << 16) |
   2229                         (ip6[6] << 8)  | (ip6[7] << 0));
   2230         ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) |
   2231                         (ip6[10] << 8) | (ip6[11] << 0));
   2232         ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) |
   2233                         (ip6[14] << 8) | (ip6[15] << 0));
   2234         soc_mem_field_set(unit, mem, entry, field, ip6_field);
   2235     }
   2236 }
   2237 
   2238 /*
   2239  * Function:    
   2240  *     soc_mem_ip6_addr_get
   2241  * Purpose:  
   2242  *     Read IP6 address field from memory field to ip6_addr_t buffer. 
   2243  * Parameters: 
   2244  *     unit  - (IN) BCM device number. 
   2245  *     mem   - (IN) Memory id.
   2246  *     entry - (IN) HW entry buffer.
   2247  *     field - (IN) Memory field id. 
   2248  *     ip6   - (OUT) SW ip6 address buffer.
   2249  *     flags - (IN) SOC_MEM_IP6_UPPER_ONLY to get upper 64 bits
   2250  *                  SOC_MEM_IP6_LOWER_ONLY to get lower 64 bits
   2251  *                  SOC_MEM_IP6_UPPER_96BIT to get upper 96 bits
   2252  *                  0  - get all 128 bits.
   2253  * Returns:      void
   2254  */
   2255 void
   2256 soc_mem_ip6_addr_get(int unit, soc_mem_t mem, const void *entry,
   2257                      soc_field_t field, ip6_addr_t ip6, int flags)
   2258 {
   2259     uint32              ip6_field[4];
   2260 
   2261     
   2262 
   2263     if (flags == SOC_MEM_IP6_UPPER_ONLY) {
   2264         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2265         ip6[0] = (uint8) (ip6_field[1] >> 24);
   2266         ip6[1] = (uint8) (ip6_field[1] >> 16 & 0xff);
   2267         ip6[2] = (uint8) (ip6_field[1] >> 8 & 0xff);
   2268         ip6[3] = (uint8) (ip6_field[1] & 0xff);
   2269         ip6[4] = (uint8) (ip6_field[0] >> 24);
   2270         ip6[5] = (uint8) (ip6_field[0] >> 16 & 0xff);
   2271         ip6[6] = (uint8) (ip6_field[0] >> 8 & 0xff);
   2272         ip6[7] = (uint8) (ip6_field[0] & 0xff);
   2273     } else if (flags == SOC_MEM_IP6_LOWER_ONLY) {
   2274         soc_mem_field_get(unit, mem, entry, field, (uint32 *)&ip6_field[2]);
   2275         ip6[8] = (uint8) (ip6_field[3] >> 24);
   2276         ip6[9] = (uint8) (ip6_field[3] >> 16 & 0xff);
   2277         ip6[10] =(uint8) (ip6_field[3] >> 8 & 0xff);
   2278         ip6[11] =(uint8) (ip6_field[3] & 0xff);
   2279         ip6[12] =(uint8) (ip6_field[2] >> 24);
   2280         ip6[13] =(uint8) (ip6_field[2] >> 16 & 0xff);
   2281         ip6[14] =(uint8) (ip6_field[2] >> 8 & 0xff);
   2282         ip6[15] =(uint8) (ip6_field[2] & 0xff);
   2283     } else if (flags == SOC_MEM_IP6_UPPER_96BIT) {
   2284         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2285         ip6[0] = (uint8) (ip6_field[2] >> 24);
   2286         ip6[1] = (uint8) (ip6_field[2] >> 16 & 0xff);
   2287         ip6[2] = (uint8) (ip6_field[2] >> 8 & 0xff);
   2288         ip6[3] = (uint8) (ip6_field[2] & 0xff);
   2289         ip6[4] = (uint8) (ip6_field[1] >> 24);
   2290         ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
   2291         ip6[6] = (uint8) (ip6_field[1] >> 8 & 0xff);
   2292         ip6[7] = (uint8) (ip6_field[1] & 0xff);
   2293         ip6[8] = (uint8) (ip6_field[0] >> 24);
   2294         ip6[9] = (uint8) (ip6_field[0] >> 16 & 0xff);
   2295         ip6[10] =(uint8) (ip6_field[0] >> 8 & 0xff);
   2296         ip6[11] =(uint8) (ip6_field[0] & 0xff);
   2297     } else if (flags == SOC_MEM_IP6_BITS_119_96) {
   2298         soc_mem_field_get(unit, mem, entry, field, (uint32 *)&ip6_field[3]);
   2299         ip6[1] = (uint8) (ip6_field[3] >> 16 & 0xff);
   2300         ip6[2] = (uint8) (ip6_field[3] >> 8 & 0xff);
   2301         ip6[3] = (uint8) (ip6_field[3] & 0xff);
   2302     } else if (flags == SOC_MEM_IP6_BITS_63_32) {
   2303         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2304         ip6[8] = (uint8) (ip6_field[0] >> 24);
   2305         ip6[9] = (uint8) (ip6_field[0] >> 16 & 0xff);
   2306         ip6[10] =(uint8) (ip6_field[0] >> 8 & 0xff);
   2307         ip6[11] =(uint8) (ip6_field[0] & 0xff);
   2308     } else if (flags == SOC_MEM_IP6_BITS_31_0) {
   2309         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2310         ip6[12] =(uint8) (ip6_field[0] >> 24);
   2311         ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff);
   2312         ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff);
   2313         ip6[15] =(uint8) (ip6_field[0] & 0xff);
   2314     } else if (flags == SOC_MEM_IP6_LOWER_96BIT) {
   2315         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2316         ip6[4] = (uint8) (ip6_field[2] >> 24);
   2317         ip6[5] = (uint8) (ip6_field[2] >> 16 & 0xff);
   2318         ip6[6] = (uint8) (ip6_field[2] >> 8 & 0xff);
   2319         ip6[7] = (uint8) (ip6_field[2] & 0xff);
   2320         ip6[8] = (uint8) (ip6_field[1] >> 24);
   2321         ip6[9] = (uint8) (ip6_field[1] >> 16 & 0xff);
   2322         ip6[10] =(uint8) (ip6_field[1] >> 8 & 0xff);
   2323         ip6[11] =(uint8) (ip6_field[1] & 0xff);
   2324         ip6[12] =(uint8) (ip6_field[0] >> 24);
   2325         ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff);
   2326         ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff);
   2327         ip6[15] =(uint8) (ip6_field[0] & 0xff);
   2328     } else {
   2329         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2330         ip6[0] = (uint8) (ip6_field[3] >> 24);
   2331         ip6[1] = (uint8) (ip6_field[3] >> 16 & 0xff);
   2332         ip6[2] = (uint8) (ip6_field[3] >> 8 & 0xff);
   2333         ip6[3] = (uint8) (ip6_field[3] & 0xff);
   2334         ip6[4] = (uint8) (ip6_field[2] >> 24);
   2335         ip6[5] = (uint8) (ip6_field[2] >> 16 & 0xff);
   2336         ip6[6] = (uint8) (ip6_field[2] >> 8 & 0xff);
   2337         ip6[7] = (uint8) (ip6_field[2] & 0xff);
   2338         ip6[8] = (uint8) (ip6_field[1] >> 24);
   2339         ip6[9] = (uint8) (ip6_field[1] >> 16 & 0xff);
   2340         ip6[10] =(uint8) (ip6_field[1] >> 8 & 0xff);
   2341         ip6[11] =(uint8) (ip6_field[1] & 0xff);
   2342         ip6[12] =(uint8) (ip6_field[0] >> 24);
   2343         ip6[13] =(uint8) (ip6_field[0] >> 16 & 0xff);
   2344         ip6[14] =(uint8) (ip6_field[0] >> 8 & 0xff);
   2345         ip6[15] =(uint8) (ip6_field[0] & 0xff);
   2346     }
   2347 }
   2348 
   2349 void
   2350 soc_mem_ip6_addr_mask_set(int unit, soc_mem_t mem, void *entry,
   2351                           soc_field_t field, const ip6_addr_t ip6, int flags)
   2352 {
   2353     uint32 ip6_field[4];
   2354 
   2355     if (flags == SOC_MEM_IP6_UPPER_ONLY) {
   2356         SAL_IP6_ADDR_HALF_TO_UINT32(ip6, ip6_field);
   2357         soc_mem_mask_field_set(unit, mem, entry, field, ip6_field);
   2358     } else if (flags == SOC_MEM_IP6_LOWER_ONLY) {
   2359         SAL_IP6_ADDR_HALF_TO_UINT32(&ip6[8], &ip6_field[2]);
   2360         soc_mem_mask_field_set(unit, mem, entry, field, &ip6_field[2]);
   2361     } else {
   2362         SAL_IP6_ADDR_TO_UINT32(ip6, ip6_field);
   2363         soc_mem_mask_field_set(unit, mem, entry, field, ip6_field);
   2364     }
   2365 }
   2366 
   2367 void
   2368 soc_mem_ip6_addr_mask_get(int unit, soc_mem_t mem, const void *entry,
   2369                           soc_field_t field, ip6_addr_t ip6, int flags)
   2370 {
   2371     uint32 ip6_field[4];
   2372 
   2373     if (flags == SOC_MEM_IP6_UPPER_ONLY) {
   2374         soc_mem_mask_field_get(unit, mem, entry, field, ip6_field);
   2375         SAL_IP6_ADDR_HALF_FROM_UINT32(ip6, ip6_field);
   2376     } else if (flags == SOC_MEM_IP6_LOWER_ONLY) {
   2377         soc_mem_mask_field_get(unit, mem, entry, field, &ip6_field[2]);
   2378         SAL_IP6_ADDR_HALF_FROM_UINT32(&ip6[8], &ip6_field[2]);
   2379     } else {
   2380         soc_mem_field_get(unit, mem, entry, field, ip6_field);
   2381         SAL_IP6_ADDR_FROM_UINT32(ip6, ip6_field);
   2382     }
   2383 }
   2384 
   2385 void
   2386 soc_mem_pbmp_field_set(int unit, soc_mem_t mem, void *entbuf,
   2387                        soc_field_t field, soc_pbmp_t *pbmp)
   2388 {
   2389     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   2390     int i;
   2391 
   2392     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   2393         fldbuf[i] = SOC_PBMP_WORD_GET(*pbmp, i);
   2394     }
   2395 
   2396     soc_mem_field_set(unit, mem, entbuf, field, fldbuf);
   2397 }
   2398 
   2399 void
   2400 soc_mem_pbmp_field_get(int unit, soc_mem_t mem, const void *entbuf,
   2401                        soc_field_t field, soc_pbmp_t *pbmp)
   2402 {
   2403     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   2404     int i;
   2405 
   2406     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   2407     soc_mem_field_get(unit, mem, entbuf, field, fldbuf);
   2408 
   2409     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   2410         SOC_PBMP_WORD_SET(*pbmp, i, fldbuf[i]);
   2411     }
   2412 }
   2413 
   2414 /*
   2415  * Function:     soc_mem_datamask_get
   2416  * Purpose:      Get a bit mask for a particular field in a memory entry
   2417  */
   2418 void
   2419 soc_mem_datamask_get(int unit, soc_mem_t mem, uint32 *buf)
   2420 {
   2421     int                 f, b, start, end;
   2422     soc_field_info_t    *fieldp;
   2423     soc_mem_info_t      *memp;
   2424     uint32              tmp;
   2425     uint32              field_ignore = 0;        
   2426     
   2427     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2428 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   2429         LOG_CLI((BSL_META_U(unit,
   2430                             "mem %s is invalid\n"), soc_mem_name[mem]));
   2431 #endif
   2432         assert(SOC_MEM_IS_VALID(unit, mem));
   2433     }
   2434 
   2435     memp = &SOC_MEM_INFO(unit, mem);
   2436     sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes));
   2437 
   2438     for (f = 0; f < memp->nFields; f++) {
   2439         fieldp = &(memp->fields[f]);
   2440         field_ignore = 0;
   2441 #ifdef BCM_TRIUMPH_SUPPORT
   2442         /*global field overlay with view reserved filed and cause mask error. */
   2443         if (SOC_IS_TRIUMPH3(unit) &&
   2444             (mem == MPLS_ENTRY_EXTDm) &&
   2445             (fieldp->field == ENTRY_2_FROM_ENTRY_1_PART1f)) {
   2446             field_ignore = 1;
   2447         }
   2448 #endif
   2449 
   2450         if ((!(fieldp->flags & SOCF_RES)) && /* not reserved */
   2451             (!field_ignore)) {
   2452             start = fieldp->bp;
   2453             end = fieldp->bp + fieldp->len - 1;
   2454             for (b = start / 32; b <= end / 32; b++) {
   2455                 tmp = -1;
   2456 
   2457                 if (b == start / 32) {
   2458                     tmp &= -1 << (start % 32);
   2459                 }
   2460 
   2461                 if (b == end / 32) {
   2462                     tmp &= (1 << (end % 32) << 1) - 1;
   2463                 }
   2464 
   2465                 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2466             }
   2467         }
   2468     }
   2469 
   2470 #ifdef BCM_TRIDENT_SUPPORT
   2471     if (SOC_IS_TD_TT(unit)) {
   2472         if (mem == FP_GLOBAL_MASK_TCAM_Xm) {
   2473             soc_mem_pbmp_field_set(unit, mem, buf, IPBMf, &PBMP_XPIPE(unit));
   2474             soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf,
   2475                                    &PBMP_XPIPE(unit));
   2476         } else if (mem == FP_GLOBAL_MASK_TCAM_Ym) {
   2477             soc_mem_pbmp_field_set(unit, mem, buf, IPBMf, &PBMP_YPIPE(unit));
   2478             soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf,
   2479                                    &PBMP_YPIPE(unit));
   2480         } else if (mem == EGR_VLANm) {
   2481             if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) {
   2482                 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf,
   2483                                        &PBMP_ALL(unit));
   2484             }
   2485             if (soc_mem_field_valid(unit, mem, UT_PORT_BITMAPf)) {
   2486                 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf,
   2487                                         &PBMP_ALL(unit));
   2488             }
   2489         } else if (mem == EGR_VLAN_Xm) {
   2490             if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) {
   2491                 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf,
   2492                                        &PBMP_XPIPE(unit));
   2493             }
   2494             soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf,
   2495                                    &PBMP_XPIPE(unit));
   2496         } else if (mem == EGR_VLAN_Ym) {
   2497             if (soc_mem_field_valid(unit, mem, PORT_BITMAPf)) {
   2498                 soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf,
   2499                                        &PBMP_YPIPE(unit));
   2500             }
   2501             soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf,
   2502                                    &PBMP_YPIPE(unit));
   2503         } else if (mem == EGR_VLAN_VFI_MEMBERSHIPm) {
   2504             soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf,
   2505                                    &PBMP_ALL(unit));
   2506         } else if (mem == SRC_MODID_INGRESS_BLOCKm) {
   2507             soc_mem_pbmp_field_set(unit, mem, buf, PORT_BITMAPf,
   2508                                    &PBMP_ALL(unit));
   2509         } else if (mem == L3_TUNNELm) {
   2510             if (soc_mem_field_valid (unit, mem, ALLOWED_PORT_BITMAPf)) {
   2511                 soc_mem_pbmp_field_set(unit, mem, buf, ALLOWED_PORT_BITMAPf,
   2512                                         &PBMP_ALL(unit));
   2513             }
   2514         } else if (mem == L3_TUNNEL_DATA_ONLYm) {
   2515             if (soc_mem_field_valid (unit, mem, ALLOWED_PORT_BITMAPf)) {
   2516                 soc_mem_pbmp_field_set(unit, mem, buf, ALLOWED_PORT_BITMAPf,
   2517                                         &PBMP_ALL(unit));
   2518             }
   2519         } else if (mem == EGR_VLAN_VFI_UNTAGm) {
   2520             if (soc_mem_field_valid(unit, mem, UT_PORT_BITMAPf)) {
   2521                 soc_mem_pbmp_field_set(unit, mem, buf, UT_PORT_BITMAPf,
   2522                                         &PBMP_ALL(unit));
   2523             }
   2524         }
   2525     }
   2526 #endif /* BCM_TRIDENT_SUPPORT */
   2527 }
   2528 
   2529 /*
   2530  * Function:     soc_mem_datamask_rw_get
   2531  * Purpose:      Get a bit mask for a particular field in a memory entry
   2532  */
   2533 void
   2534 soc_mem_datamask_rw_get(int unit, soc_mem_t mem, uint32 *buf)
   2535 {
   2536     int                 f, b, start, end;
   2537     soc_field_info_t    *fieldp;
   2538     soc_mem_info_t      *memp;
   2539     uint32              tmp;
   2540     uint16              access_flag;
   2541     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2542         assert(SOC_MEM_IS_VALID(unit, mem));
   2543     }
   2544 
   2545     memp = &SOC_MEM_INFO(unit, mem);
   2546     sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes));
   2547 
   2548     for (f = 0; f < memp->nFields; f++) {
   2549         fieldp = &(memp->fields[f]);
   2550         access_flag =  fieldp->flags & (SOCF_RES | SOCF_RO | SOCF_SIG | SOCF_WO);
   2551        /* if ((!(fieldp->flags & SOCF_RES)) && (!(fieldp->flags & SOCF_RO)) && (!(fieldp->flags & SOCF_SIG))) {    */  /* not reserved */
   2552         if (access_flag == 0) {    /* Get field mask just in case if the field is not read only, is not write only, not a signal and not reserved*/
   2553             start = fieldp->bp;
   2554             end = fieldp->bp + fieldp->len - 1;
   2555             for (b = start / 32; b <= end / 32; b++) {
   2556                 tmp = -1;
   2557 
   2558                 if (b == start / 32) {
   2559                     tmp &= -1 << (start % 32);
   2560                 }
   2561 
   2562                 if (b == end / 32) {
   2563                     tmp &= (1 << (end % 32) << 1) - 1;
   2564                 }
   2565 
   2566                 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2567             }
   2568         }
   2569     }
   2570 }
   2571 
   2572 /*
   2573  * Function:     soc_mem_tcammask_get
   2574  * Purpose:      Get a bit mask for TCAM mask field in a memory entry
   2575  */
   2576 void
   2577 soc_mem_tcammask_get(int unit, soc_mem_t mem, uint32 *buf)
   2578 {
   2579     soc_mem_info_t      *memp;
   2580 
   2581     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2582 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   2583         LOG_CLI((BSL_META_U(unit,
   2584                             "mem %s is invalid\n"), soc_mem_name[mem]));
   2585 #endif
   2586         assert(SOC_MEM_IS_VALID(unit, mem));
   2587     }
   2588 
   2589     memp = &SOC_MEM_INFO(unit, mem);
   2590     sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes));
   2591 
   2592 #if defined(BCM_TRIUMPH_SUPPORT)
   2593     if (soc_feature(unit, soc_feature_esm_support)) {
   2594         int               f, b, start, end;
   2595         soc_field_info_t  *fieldp;
   2596         uint32            tmp;
   2597 
   2598         for (f = 0; f < memp->nFields; f++) {
   2599             fieldp = &(memp->fields[f]);
   2600 
   2601             if (fieldp->flags & SOCF_RES) {
   2602                 continue;
   2603             }
   2604 
   2605             switch (fieldp->field) {
   2606             case TMW0f:
   2607             case TMW1f:
   2608             case TMW2f:
   2609             case TMW3f:
   2610             case TMW4f:
   2611             case TMW5f:
   2612                 break;
   2613             default:
   2614                 continue;
   2615             }
   2616 
   2617             start = fieldp->bp;
   2618             end = fieldp->bp + fieldp->len - 1;
   2619 
   2620             for (b = start / 32; b <= end / 32; b++) {
   2621                 tmp = -1;
   2622 
   2623                 if (b == start / 32) {
   2624                     tmp &= -1 << (start % 32);
   2625                 }
   2626 
   2627                 if (b == end / 32) {
   2628                     tmp &= (1 << (end % 32) << 1) - 1;
   2629                 }
   2630 
   2631                 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2632             }
   2633         }
   2634     }
   2635 #endif /* BCM_TRIUMPH_SUPPORT */
   2636 #if defined(BCM_SHADOW_SUPPORT)
   2637     if (SOC_IS_SHADOW(unit)) {
   2638         int               f, b, start, end;
   2639         soc_field_info_t  *fieldp;
   2640         uint32            tmp;
   2641 
   2642         if (memp->flags & SOC_MEM_FLAG_CAM) {
   2643             for (f = 0; f < memp->nFields; f++) {
   2644                 fieldp = &(memp->fields[f]);
   2645 
   2646                 if (fieldp->flags & SOCF_RES) {
   2647                     continue;
   2648                 }
   2649 
   2650                 switch (fieldp->field) {
   2651                 case MASKf:
   2652                 case MASK0f:
   2653                 case MASK1f:
   2654                 case FULL_MASKf:
   2655                     break;
   2656                 default:
   2657                     continue;
   2658                 }
   2659 
   2660                 start = fieldp->bp;
   2661                 end = fieldp->bp + fieldp->len - 1;
   2662 
   2663                 for (b = start / 32; b <= end / 32; b++) {
   2664                     tmp = -1;
   2665 
   2666                     if (b == start / 32) {
   2667                         tmp &= -1 << (start % 32);
   2668                     }
   2669 
   2670                     if (b == end / 32) {
   2671                         tmp &= (1 << (end % 32) << 1) - 1;
   2672                     }
   2673 
   2674                     buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2675                 }
   2676             }
   2677         }
   2678     }
   2679 #endif /* BCM_SHADOW_SUPPORT */
   2680 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
   2681     if (soc_feature(unit, soc_feature_xy_tcam)) {
   2682         int               f, b, start, end;
   2683         soc_field_info_t  *fieldp;
   2684         uint32            tmp;
   2685 
   2686         if (memp->flags & SOC_MEM_FLAG_CAM) {
   2687             for (f = 0; f < memp->nFields; f++) {
   2688                 fieldp = &(memp->fields[f]);
   2689 
   2690                 if (fieldp->flags & SOCF_RES) {
   2691                     continue;
   2692                 }
   2693 
   2694                 switch (fieldp->field) {
   2695                 case MASKf:
   2696                 case MASK0f:
   2697                 case MASK1f:
   2698                 case MASK0_UPRf:
   2699                 case MASK1_UPRf:
   2700                 case MASK0_LWRf:
   2701                 case MASK1_LWRf:
   2702                 case DATA_MASKf:
   2703                 case FULL_MASKf:
   2704                     break;
   2705                 default:
   2706                     continue;
   2707                 }
   2708 
   2709                 start = fieldp->bp;
   2710                 end = fieldp->bp + fieldp->len - 1;
   2711                 for (b = start / 32; b <= end / 32; b++) {
   2712                     tmp = -1;
   2713 
   2714                     if (b == start / 32) {
   2715                         tmp &= -1 << (start % 32);
   2716                     }
   2717 
   2718                     if (b == end / 32) {
   2719                         tmp &= (1 << (end % 32) << 1) - 1;
   2720                     }
   2721 
   2722                     buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2723                 }
   2724             }
   2725             if (SOC_IS_TD_TT(unit)) {
   2726                 if (mem == FP_GLOBAL_MASK_TCAM_Xm) {
   2727                     soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf,
   2728                                            &PBMP_XPIPE(unit));
   2729                 } else if (mem == FP_GLOBAL_MASK_TCAM_Ym) {
   2730                     soc_mem_pbmp_field_set(unit, mem, buf, IPBM_MASKf,
   2731                                            &PBMP_YPIPE(unit));
   2732                 }
   2733             }
   2734         }
   2735     }
   2736 #endif /* BCM_TRIDENT_SUPPORT */
   2737 }
   2738 
   2739 /*
   2740  * Function:     soc_mem_eccmask_get
   2741  * Purpose:      Get a bit mask for ECC mask field in a memory entry
   2742  */
   2743 void
   2744 soc_mem_eccmask_get(int unit, soc_mem_t mem, uint32 *buf)
   2745 {
   2746     soc_mem_info_t      *memp;
   2747 
   2748     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2749 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   2750         LOG_CLI((BSL_META_U(unit,
   2751                             "mem %s is invalid\n"), soc_mem_name[mem]));
   2752 #endif
   2753         assert(SOC_MEM_IS_VALID(unit, mem));
   2754     }
   2755 
   2756     memp = &SOC_MEM_INFO(unit, mem);
   2757     sal_memset(buf, 0, sizeof(*buf) * BYTES2WORDS(memp->bytes));
   2758 
   2759 #if defined(BCM_TRIUMPH_SUPPORT)
   2760     if (soc_feature(unit, soc_feature_esm_support)) {
   2761         int               f, b, start, end;
   2762         soc_field_info_t  *fieldp;
   2763         uint32            tmp;
   2764 
   2765         for (f = 0; f < memp->nFields; f++) {
   2766             fieldp = &(memp->fields[f]);
   2767 
   2768             if (fieldp->flags & SOCF_RES) {
   2769                 continue;
   2770             }
   2771 
   2772             switch (fieldp->field) {
   2773             case ECC_ALLf:
   2774             case ECC0_ALLf:
   2775             case ECC1_ALLf:
   2776             case ECC2_ALLf:
   2777             case ECC3_ALLf:
   2778             case ECC4_ALLf:
   2779             case ECC5_ALLf:
   2780             case ECC6_ALLf:
   2781             case ECC7_ALLf:
   2782                 break;
   2783             default:
   2784                 continue;
   2785             }
   2786 
   2787             start = fieldp->bp;
   2788             end = fieldp->bp + fieldp->len - 1;
   2789 
   2790             for (b = start / 32; b <= end / 32; b++) {
   2791                 tmp = -1;
   2792 
   2793                 if (b == start / 32) {
   2794                     tmp &= -1 << (start % 32);
   2795                 }
   2796 
   2797                 if (b == end / 32) {
   2798                     tmp &= (1 << (end % 32) << 1) - 1;
   2799                 }
   2800 
   2801                 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2802             }
   2803         }
   2804     }
   2805 #endif /* BCM_TRIUMPH_SUPPORT */
   2806 
   2807     if (soc_feature(unit, soc_feature_mem_parity_eccmask)) {
   2808 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) || \
   2809     defined(BCM_ESW_SUPPORT)
   2810 
   2811         int               f, b, start, end;
   2812         soc_field_info_t  *fieldp;
   2813         uint32            tmp;
   2814 
   2815         for (f = 0; f < memp->nFields; f++) {
   2816             fieldp = &(memp->fields[f]);
   2817 
   2818             if (fieldp->flags & SOCF_RES) {
   2819                 continue;
   2820             }
   2821 
   2822             switch (fieldp->field) {
   2823             case ECCPf:
   2824             case ECCf:
   2825             case PARITYf:
   2826             case ECCP0f:
   2827             case ECCP1f:
   2828             case ECCP2f:
   2829             case ECCP3f:
   2830             case ECC0f:
   2831             case ECC1f:
   2832             case ECC2f:
   2833             case ECC3f:
   2834             case PARITY0f:
   2835             case PARITY1f:
   2836             case PARITY2f:
   2837             case PARITY3f:
   2838             case EVEN_PARITYf:
   2839             case ECCP_0f:
   2840             case ECCP_1f:
   2841             case ECCP_2f:
   2842             case ECCP_3f:
   2843             case ECC_0f:
   2844             case ECC_1f:
   2845             case ECC_2f:
   2846             case ECC_3f:
   2847             case PARITY_0f:
   2848             case PARITY_1f:
   2849             case PARITY_2f:
   2850             case PARITY_3f:
   2851             case ECCP_P0f:
   2852             case ECCP_P1f:
   2853             case ECCP_P2f:
   2854             case ECCP_P3f:
   2855             case ECC_P0f:
   2856             case ECC_P1f:
   2857             case ECC_P2f:
   2858             case ECC_P3f:
   2859             case PARITY_P0f:
   2860             case PARITY_P1f:
   2861             case PARITY_P2f:
   2862             case PARITY_P3f:
   2863             case EVEN_PARITY_P0f:
   2864             case EVEN_PARITY_P1f:
   2865             case EVEN_PARITY_P2f:
   2866             case EVEN_PARITY_P3f:               
   2867             case ECCP_PBM_0f:
   2868             case ECCP_PBM_1f:
   2869             case ECCP_PBM_2f:
   2870             case ECCP_PBM_3f:
   2871             case ECC_PBM_0f:
   2872             case ECC_PBM_1f:
   2873             case ECC_PBM_2f:
   2874             case ECC_PBM_3f:
   2875             case PARITY_PBM_0f:
   2876             case PARITY_PBM_1f:
   2877             case PARITY_PBM_2f:
   2878             case PARITY_PBM_3f:
   2879             case TCAM_PARITY_MASKf:
   2880             case TCAM_PARITY_KEYf:
   2881                 break;
   2882             default:
   2883                 continue;
   2884             }
   2885 
   2886             start = fieldp->bp;
   2887             end = fieldp->bp + fieldp->len - 1;
   2888 
   2889             for (b = start / 32; b <= end / 32; b++) {
   2890                 tmp = -1;
   2891 
   2892                 if (b == start / 32) {
   2893                     tmp &= -1 << (start % 32);
   2894                 }
   2895 
   2896                 if (b == end / 32) {
   2897                     tmp &= (1 << (end % 32) << 1) - 1;
   2898                 }
   2899 
   2900                 buf[FIX_MEM_ORDER_E(b, memp)] |= tmp;
   2901             }
   2902         }
   2903 #endif /* BCM_KATANA2_SUPPORT || BCM_GREYHOUND_SUPPORT || BCM_ESW_SUPPORT */
   2904     }
   2905 }
   2906 
   2907 /*
   2908  * Function:     soc_mem_forcedata_get
   2909  * Purpose:      Get a bit mask and value for non-zero sticky fields in a
   2910  *               memory entry
   2911  */
   2912 void
   2913 soc_mem_forcedata_get(int unit, soc_mem_t mem, uint32 *maskbuf,
   2914                       uint32 *databuf)
   2915 {
   2916     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2917 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   2918         LOG_CLI((BSL_META_U(unit,
   2919                             "mem %s is invalid\n"), soc_mem_name[mem]));
   2920 #endif
   2921         assert(SOC_MEM_IS_VALID(unit, mem));
   2922     }
   2923 
   2924     sal_memset(maskbuf, 0, sizeof(*maskbuf) * soc_mem_entry_words(unit, mem));
   2925     sal_memset(databuf, 0, sizeof(*databuf) * soc_mem_entry_words(unit, mem));
   2926 
   2927 #if defined(BCM_TRIDENT_SUPPORT)
   2928     if (mem == HG_TRUNK_GROUPm &&
   2929         soc_feature(unit, soc_feature_hg_trunk_16_members)) {
   2930         int field_len;
   2931         field_len = soc_mem_field_length(unit, mem, TG_SIZEf);
   2932         soc_mem_field32_set(unit, mem, maskbuf, TG_SIZEf,
   2933                             (1 << field_len) - 1);
   2934         soc_mem_field32_set(unit, mem, databuf, TG_SIZEf, 0xf);
   2935     }
   2936 #endif /* BCM_TRIDENT_SUPPORT */
   2937 #ifdef BCM_GREYHOUND2_SUPPORT
   2938     if (SOC_IS_GREYHOUND2(unit) && (
   2939         mem == SR_SN_HISTORY_0m || mem == SR_SN_HISTORY_1m || mem == SR_SN_HISTORY_2m ||
   2940         mem == SR_SN_HISTORY_3m || mem == SR_SN_HISTORY_4m || mem == SR_SN_HISTORY_5m ||
   2941         mem == SR_SN_HISTORY_6m || mem == SR_SN_HISTORY_7m || mem == SR_SN_HISTORY_8m ||
   2942         mem == SR_SN_HISTORY_9m || mem == SR_SN_HISTORY_10m || mem == SR_SN_HISTORY_11m ||
   2943         mem == SR_SN_HISTORY_12m || mem == SR_SN_HISTORY_13m || mem == SR_SN_HISTORY_14m ||
   2944         mem == SR_SN_HISTORY_15m )) {
   2945         soc_mem_field32_set(unit, mem, databuf, BLOCK_SELECTf,
   2946                             ((1 << soc_mem_field_length(unit, mem, BLOCK_SELECTf)) - 1));
   2947         soc_mem_field32_set(unit, mem, maskbuf, BLOCK_SELECTf,
   2948                             ((1 << soc_mem_field_length(unit, mem, BLOCK_SELECTf)) - 1));
   2949     }
   2950 #endif /* BCM_GREYHOUND2_SUPPORT */
   2951 
   2952 }
   2953 
   2954 #if defined(BCM_ESW_SUPPORT)
   2955 void
   2956 soc_mem_base_to_wide_entry_conv(int unit, soc_mem_t dest_mem, soc_mem_t src_mem, 
   2957                                 uint32 *dest, uint32 *src[4], uint8 conv_type)
   2958 {
   2959     uint32 field[SOC_MAX_MEM_FIELD_WORDS];
   2960     switch (conv_type) {
   2961     case TYPE_1_TO_TYPE_2:        
   2962         soc_mem_field_set(unit, dest_mem, dest, ENTRY_2_FROM_ENTRY_1_PART0f,
   2963                           soc_mem_field_get(unit, src_mem, src[0], 
   2964                                             WIDE_ENTRY_BITSf, field));
   2965         soc_mem_field_set(unit, dest_mem, dest, ENTRY_2_FROM_ENTRY_1_PART1f,
   2966                           soc_mem_field_get(unit, src_mem, src[1], 
   2967                                             WIDE_ENTRY_BITSf, field));
   2968         soc_mem_field32_set(unit, dest_mem, dest, HIT_BITSf,
   2969                           soc_mem_field32_get(unit, src_mem, src[0], 
   2970                                               HIT_BITSf));
   2971         return;
   2972     case TYPE_1_TO_TYPE_4:
   2973         soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART0f,
   2974                           soc_mem_field_get(unit, src_mem, src[0], 
   2975                                             WIDE_ENTRY_BITSf, field));
   2976         soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART1f,
   2977                           soc_mem_field_get(unit, src_mem, src[1], 
   2978                                             WIDE_ENTRY_BITSf, field));
   2979         soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART2f,
   2980                           soc_mem_field_get(unit, src_mem, src[2], 
   2981                                             WIDE_ENTRY_BITSf, field));
   2982         soc_mem_field_set(unit, dest_mem, dest, ENTRY_4_FROM_ENTRY_1_PART3f,
   2983                           soc_mem_field_get(unit, src_mem, src[3], 
   2984                                             WIDE_ENTRY_BITSf, field));
   2985         soc_mem_field32_set(unit, dest_mem, dest, HIT_BITSf,
   2986                             soc_mem_field32_get(unit, src_mem, src[0], 
   2987                                                 HIT_BITSf));
   2988         return;
   2989     default:
   2990         LOG_CLI((BSL_META_U(unit,
   2991                             "Unimplemented convertion type: %d\n"), conv_type));
   2992         assert(0);
   2993     }
   2994 }
   2995 #endif
   2996 
   2997 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT)
   2998 
   2999 /*
   3000  * Function:    soc_mem_addr
   3001  * Purpose:     Turn a memory, block, and index into a memory address
   3002  * Returns:     address to send off in an schannel message
   3003  */
   3004 /*
   3005  * Regular:      | Table(8) | Block(4) | Region(4) | Index(16) |
   3006  * Monolithic:   | Table(8) | Index(24)                        |
   3007  */
   3008 uint32
   3009 soc_mem_addr(int unit, soc_mem_t mem, unsigned array_index, int blk, int index)
   3010 {
   3011     uint32              blkoff;
   3012     soc_mem_info_t      *mip;
   3013     soc_mem_array_info_t *maip;
   3014     uint32              base;
   3015 
   3016     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3017 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   3018         LOG_CLI((BSL_META_U(unit,
   3019                             "mem %s is invalid\n"), soc_mem_name[mem]));
   3020 #endif
   3021         assert(SOC_MEM_IS_VALID(unit, mem));
   3022     }
   3023 
   3024     assert(blk >= 0 && blk < SOC_MAX_NUM_BLKS);
   3025     assert(index >= 0);
   3026 
   3027 #if defined(BCM_TRIUMPH_SUPPORT)
   3028     if (soc_feature(unit, soc_feature_esm_support)) {
   3029         if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ESM) || 
   3030            (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ETU)) {
   3031             SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit,
   3032                                                                 mem,
   3033                                                                 index,
   3034                                                                 &mem,
   3035                                                                 &index));
   3036         }
   3037     }
   3038 #endif
   3039 
   3040     mip = &SOC_MEM_INFO(unit, mem);
   3041 
   3042 #if defined(BCM_TRIUMPH3_SUPPORT) 
   3043     if (soc_feature(unit, soc_feature_etu_support)) {
   3044         if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_ISM) {
   3045             if (mip->flags & (SOC_MEM_FLAG_CAM | SOC_MEM_FLAG_EXT_CAM)) {
   3046                 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit,
   3047                                                                 mem,
   3048                                                                 index,
   3049                                                                 &mem,
   3050                                                                 &index));
   3051             }
   3052         } 
   3053         /* do it again if returned mem is different */
   3054         mip = &SOC_MEM_INFO(unit, mem);
   3055     }
   3056 #endif
   3057     if ((blk>=32)?(mip->blocks_hi & (1 << (blk&0x1F))):(mip->blocks & (1 << blk))) {
   3058         blkoff = ((SOC_BLOCK2OFFSET(unit, blk) & 0xf) << SOC_BLOCK_BP) |
   3059                  (((SOC_BLOCK2OFFSET(unit, blk) >> 4) & 0x3) << SOC_BLOCK_MSB_BP);
   3060     } else {
   3061         blkoff = 0;
   3062     }
   3063 
   3064     base = mip->base;
   3065 
   3066 #ifdef BCM_DFE_SUPPORT
   3067     if(SOC_IS_FE1600(unit)) {
   3068         base = (((mip->base >> 20) & 0x3F) << 24) | (mip->base & 0xFFFFF);
   3069     }
   3070 #endif
   3071 
   3072     if (array_index) {
   3073         /* non zero array index, implying this is a memory array */
   3074         assert (mip->flags & SOC_MEM_FLAG_IS_ARRAY); /* verify this is really a memory array */
   3075         maip = SOC_MEM_ARRAY_INFOP(unit, mem);
   3076         assert(maip);                       /* verify this is memory array information exists */
   3077         assert(array_index >= maip->first_array_index && array_index < maip->numels + maip->first_array_index); /* verify that the array index is in range */
   3078         LOG_INFO(BSL_LS_SOC_MEM,
   3079                  (BSL_META_U(unit,
   3080                              "addr: %x, mip->base: %x, blkoff: %x, "
   3081                              "index = %d, mip->gran: %d, * = %x, arr_in = %u, skip = %u\n"), 
   3082                   base+blkoff+(index * mip->gran) + (array_index * maip->element_skip),
   3083                   mip->base,blkoff, index, mip->gran,
   3084                   (index * mip->gran), array_index, maip->element_skip));
   3085         return base + blkoff + (index * mip->gran) + (array_index * maip->element_skip);
   3086     }
   3087 
   3088     LOG_INFO(BSL_LS_SOC_MEM,
   3089              (BSL_META_U(unit,
   3090                          "addr: %x, mip->base: %x, blkoff: %x, "
   3091                          "index = %d, mip->gran: %d, * = %x\n"), 
   3092               base+blkoff+(index * mip->gran),
   3093               mip->base,blkoff, index, mip->gran,
   3094               (index * mip->gran)));
   3095     return base + blkoff + (index * mip->gran);
   3096 }
   3097 
   3098 /*
   3099  * Function:    soc_mem_addr_get
   3100  * Purpose:     Turn a memory, block, and index into a memory address
   3101  * Returns:     address to send off in an schannel message
   3102  */
   3103 /*
   3104  * Regular:      | Table(8) | Block(4) | Region(4) | Index(16) |
   3105  * Monolithic:   | Table(8) | Index(24)                        |
   3106  */
   3107 uint32
   3108 soc_mem_addr_get(int unit, soc_mem_t mem, unsigned array_index, soc_block_t block, 
   3109                  int index, uint8 *acc_type)
   3110 {
   3111     soc_mem_info_t       *mip;
   3112     soc_mem_array_info_t *maip;
   3113 
   3114     if (!soc_feature(unit, soc_feature_new_sbus_format)) {
   3115         return soc_mem_addr(unit, mem, array_index, block, index);
   3116     }
   3117     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3118 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   3119         LOG_CLI((BSL_META_U(unit,
   3120                             "mem %s is invalid\n"), soc_mem_name[mem]));
   3121 #endif
   3122         assert(SOC_MEM_IS_VALID(unit, mem));
   3123     }
   3124 
   3125     assert(block >= 0 && block < SOC_MAX_NUM_BLKS);
   3126     assert(index >= 0);
   3127     
   3128     *acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   3129 #if defined(BCM_TRIUMPH_SUPPORT)
   3130     if (soc_feature(unit, soc_feature_esm_support)) {
   3131         if ((SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ESM) ||
   3132            (SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ETU)) {
   3133             SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit,
   3134                                                                 mem,
   3135                                                                 index,
   3136                                                                 &mem,
   3137                                                                 &index));
   3138         }
   3139     }
   3140 #endif
   3141 
   3142     mip = &SOC_MEM_INFO(unit, mem);
   3143 
   3144 #if defined(BCM_TRIUMPH3_SUPPORT) 
   3145     if (soc_feature(unit, soc_feature_etu_support)) {
   3146         if (SOC_BLOCK_TYPE(unit, block) == SOC_BLK_ISM) {
   3147             if (mip->flags & (SOC_MEM_FLAG_CAM | SOC_MEM_FLAG_EXT_CAM)) {
   3148                 SOC_IF_ERROR_RETURN(soc_tcam_mem_index_to_raw_index(unit,
   3149                                                                 mem,
   3150                                                                 index,
   3151                                                                 &mem,
   3152                                                                 &index));
   3153             }
   3154         } 
   3155         /* do it again if returned mem is different */
   3156         mip = &SOC_MEM_INFO(unit, mem);
   3157     }
   3158 #endif
   3159     if (array_index) {
   3160         /* non zero array index, implying this is a memory array */
   3161         assert (mip->flags & SOC_MEM_FLAG_IS_ARRAY); /* verify this is really a memory array */
   3162         maip = SOC_MEM_ARRAY_INFOP(unit, mem);
   3163         assert(maip);                       /* verify this is memory array information exists */
   3164         assert(array_index >= maip->first_array_index && array_index < maip->numels + maip->first_array_index); /* verify that the array index is in range */
   3165         if (array_index > maip->first_array_index) {
   3166             LOG_INFO(BSL_LS_SOC_MEM,
   3167                  (BSL_META_U(unit,
   3168                              "addr: %x, mip->base: %x, block: %x, "
   3169                              "index = %d, mip->gran: %d, * = %x, arr_in = %u, skip = %u\n"), 
   3170                   mip->base + (index * mip->gran) + ((array_index - maip->first_array_index) * maip->element_skip), mip->base,
   3171                   SOC_BLOCK2OFFSET(unit, block), index, 
   3172                   mip->gran, (index * mip->gran), array_index, maip->element_skip));
   3173             return mip->base + (index * mip->gran) + ((array_index - maip->first_array_index) * maip->element_skip);
   3174         } else {
   3175         LOG_INFO(BSL_LS_SOC_MEM,
   3176                  (BSL_META_U(unit,
   3177                              "addr: %x, mip->base: %x, block: %x, "
   3178                              "index = %d, mip->gran: %d, * = %x\n"), 
   3179                   mip->base+(index * mip->gran), mip->base,
   3180                   SOC_BLOCK2OFFSET(unit, block), index, 
   3181                   mip->gran, (index * mip->gran)));
   3182             return mip->base + (index * mip->gran);
   3183         }
   3184     } else {
   3185         /* non memory array acces, works also with index 0 of a memory array */
   3186         LOG_INFO(BSL_LS_SOC_MEM,
   3187                  (BSL_META_U(unit,
   3188                              "addr: %x, mip->base: %x, block: %x, "
   3189                              "index = %d, mip->gran: %d, * = %x\n"), 
   3190                   mip->base+(index * mip->gran), mip->base,
   3191                   SOC_BLOCK2OFFSET(unit, block), index, 
   3192                   mip->gran, (index * mip->gran)));
   3193         return mip->base + (index * mip->gran);
   3194     }
   3195 }
   3196 
   3197 
   3198 #define ACC_TYPE_MASK 0xE0000
   3199 /* Translate a memory address to the memory using it
   3200  * If array_index is not NULL and the found memory is a memory array,
   3201  * then the array index is returned in array_index .
   3202  */
   3203 soc_mem_t
   3204 soc_addr_to_mem(int unit, uint32 address, uint32 *mem_block)
   3205 {
   3206     soc_mem_t       mem;
   3207     uint32          offset, min_addr, max_addr, block = 0;
   3208 
   3209     offset = address & ~0xC0f00000; /* strip block id */
   3210     if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
   3211         offset &= ~ACC_TYPE_MASK; /* strip memAcc*/
   3212     }
   3213 #ifdef BCM_DFE_SUPPORT
   3214     if(SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_A0 || 
   3215        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_B0 ||
   3216        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88754_A0 ||
   3217        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88755_B0) {
   3218         offset = (offset & 0x000fffff) | (((offset >> 24 ) & 0x3F) << 20);
   3219     }
   3220 #endif
   3221     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3222         if (soc_mem_is_valid(unit, mem) &&
   3223             ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) {
   3224 
   3225             min_addr = max_addr = SOC_MEM_INFO(unit, mem).base;
   3226             if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
   3227                 min_addr = max_addr = max_addr & ~ACC_TYPE_MASK; /* strip memAcc*/
   3228             }
   3229             min_addr += SOC_MEM_INFO(unit, mem).index_min;
   3230             max_addr += SOC_MEM_INFO(unit, mem).index_max;
   3231             if (SOC_MEM_IS_ARRAY(unit, mem)) {
   3232                 if (offset < min_addr || offset > max_addr +
   3233                       (SOC_MEM_NUMELS(unit, mem) - 1 + SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * SOC_MEM_ELEM_SKIP(unit, mem)) {
   3234                     continue;
   3235                 }
   3236                 /* now make sure that the address is legal for the memory array */
   3237                 offset = (offset - min_addr) % SOC_MEM_ELEM_SKIP(unit, mem); /* calculate the array index and check it is in range */
   3238                 if (offset >= SOC_MEM_NUMELS(unit, mem)) {
   3239                     continue;
   3240                 }
   3241                 offset += SOC_MEM_FIRST_ARRAY_INDEX(unit, mem);
   3242             } else if (offset < min_addr || offset > max_addr) {
   3243                 continue;
   3244             }
   3245 
   3246             if (SOC_IS_XGS3_SWITCH(unit)) {
   3247                 /* Match block */
   3248                 block = ((address >> SOC_BLOCK_BP) & 0xf) | 
   3249                         (((address >> SOC_BLOCK_MSB_BP) & 0x3) << 4);
   3250                 if (block != SOC_BLOCK2OFFSET(unit, SOC_MEM_BLOCK_ANY(unit, mem))) {
   3251                     continue;
   3252                 }
   3253             }
   3254             if (mem_block) {
   3255                 *mem_block = block;
   3256             }
   3257             return mem;
   3258         }
   3259     }
   3260     return INVALIDm;
   3261 }
   3262 int
   3263 soc_addr_is_mem(int unit, int acc_type, uint32 block, int blk, uint32 offset, soc_mem_t mem)
   3264 {
   3265     uint32          min_addr, max_addr;
   3266     int copyno;
   3267 #ifdef BCM_TOMAHAWK3_SUPPORT
   3268     uint32 block_tmp = block;
   3269     int rv;
   3270 #endif
   3271 
   3272     if (soc_mem_is_valid(unit, mem) &&
   3273         ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) {
   3274 #ifdef BCM_TOMAHAWK3_SUPPORT
   3275         if (SOC_IS_TOMAHAWK3(unit)) {
   3276             rv = soc_th3_mmu_mem_blk_remap(mem, &block);
   3277             if (rv == SOC_E_NOT_FOUND) {
   3278                 block = block_tmp;
   3279             }
   3280         }
   3281 #endif
   3282 
   3283         min_addr = max_addr = SOC_MEM_INFO(unit, mem).base;
   3284         min_addr += SOC_MEM_INFO(unit, mem).index_min;
   3285         max_addr += SOC_MEM_INFO(unit, mem).index_max;
   3286         if (SOC_MEM_IS_ARRAY(unit, mem)) {
   3287             if (offset < min_addr || offset > max_addr +
   3288                   (SOC_MEM_NUMELS(unit, mem) - 1) * SOC_MEM_ELEM_SKIP(unit, mem)) {
   3289                 return FALSE;
   3290             }
   3291             /* now make sure that the address is legal for the memory array */
   3292             if ( (offset - min_addr) % SOC_MEM_ELEM_SKIP(unit, mem) /* in this line (index - index_min) is computed */
   3293                  > max_addr - min_addr ) { /* Is the index too big */
   3294                 return FALSE;
   3295             }
   3296         } else if (offset < min_addr || offset > max_addr) {
   3297             return FALSE;
   3298         }
   3299         if (SOC_IS_XGS3_SWITCH(unit)) {
   3300 
   3301             /* Match block */
   3302             SOC_MEM_BLOCK_ITER2(unit, mem, copyno) {
   3303                 if (block == SOC_BLOCK2OFFSET(unit, copyno)) {
   3304                     break;
   3305                 }
   3306             }
   3307             if (copyno > SOC_MEM_BLOCK_MAX(unit, mem)) {
   3308                 return FALSE;
   3309             }
   3310 
   3311             if ((acc_type >= 0) &&
   3312                 (acc_type != SOC_MEM_ACC_TYPE(unit, mem))) {
   3313                 return FALSE;
   3314             }
   3315         }
   3316         if (SOC_IS_SAND(unit) || SOC_IS_GREYHOUND(unit)
   3317             || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3318             /* check that the memory belongs to the correct block */
   3319             if (blk != SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem))) {
   3320                 return FALSE;
   3321             }
   3322         }
   3323         return TRUE;
   3324     }
   3325 
   3326     return FALSE;
   3327 }
   3328 /* Note: acc_type = -1 is used as don't care */
   3329 soc_mem_t
   3330 soc_addr_to_mem_extended(int unit, uint32 block, int acc_type, uint32 address)
   3331 {
   3332     soc_mem_t       mem;
   3333     uint32          offset;
   3334     int blk = -1;
   3335     offset = address;
   3336 #ifdef BCM_DFE_SUPPORT
   3337     if(SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_A0 || 
   3338        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88750_B0 ||
   3339        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88754_A0 ||
   3340        SOC_DRIVER(unit)->type == SOC_CHIP_BCM88755_B0) {
   3341         offset = (address & 0x000fffff) | (((address >>24 ) & 0x3F) << 20);
   3342     }
   3343 #endif
   3344     if (SOC_IS_SAND(unit) || SOC_IS_GREYHOUND(unit) ||
   3345         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3346         /* Find the block of the given block */
   3347         for (blk = 0; ; ++blk) {
   3348             if (SOC_BLOCK_TYPE(unit, blk) < 0) {
   3349                 return INVALIDm;
   3350             } else if (SOC_BLOCK2OFFSET(unit, blk) == block) {
   3351                 break;
   3352             }
   3353         }
   3354 #ifdef BCM_JERICHO_SUPPORT
   3355         if (SOC_IS_JERICHO(unit) && SOC_BLOCK_IS_BROADCAST(unit, blk)) {
   3356             blk = SOC_BLOCK_BROADCAST_MEMBER(unit, blk, 0); /* For broadcast blocks we want the type of the broadcast members */
   3357         }
   3358 #endif /* BCM_JERICHO_SUPPORT */
   3359         blk = SOC_BLOCK_TYPE(unit, blk); /* Get block type for later comparisons from block */
   3360     }
   3361 
   3362     /* first look in already used mems for optimization*/
   3363     if (soc_feature(unit, soc_feature_mem_direct_acc_last_used_first))
   3364     {
   3365 
   3366         soc_mem_t last_used_mem = drvmem_last_used_mem_direct_acc[unit];
   3367         if (soc_addr_is_mem(unit, acc_type, block, blk, offset, last_used_mem))
   3368         {
   3369             return last_used_mem;
   3370         }
   3371     }
   3372 
   3373     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3374         if (soc_addr_is_mem(unit, acc_type, block, blk, offset, mem))
   3375         {
   3376             if (soc_feature(unit, soc_feature_mem_direct_acc_last_used_first))
   3377             {
   3378                 drvmem_last_used_mem_direct_acc[unit] = mem;
   3379             }
   3380             return mem;
   3381         }
   3382     }
   3383 
   3384     return INVALIDm;
   3385 }
   3386 
   3387 /*
   3388  * Function:     soc_mem_addr_to_array_element_and_index     
   3389  * Purpose:      For the given memory and a given address of its entry, return
   3390  *               the entry index in index, and the array index in array_index.
   3391  *               If the memory is not an array the returned array index is 0.
   3392  * Returns:      SOC_E_NONE if adress is compatible to mem, otherwise - SOC_E_UNAVAIL       
   3393  */
   3394 int
   3395 soc_mem_addr_to_array_element_and_index(int unit, soc_mem_t mem, uint32 address, 
   3396                                         unsigned* array_index, int* index)
   3397 {
   3398     int array_size_base;
   3399 
   3400     if((NULL == array_index) || (NULL == index)){
   3401         return SOC_E_PARAM; 
   3402     }
   3403 
   3404     /* address includes the offest of the memory | the entry index */
   3405     if (soc_mem_is_valid(unit, mem) &&
   3406             ((SOC_MEM_INFO(unit, mem).blocks | SOC_MEM_INFO(unit, mem).blocks_hi) != 0) ) {
   3407         if (!SOC_MEM_IS_ARRAY(unit, mem)) {
   3408             if((address < (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_min)) ||
   3409                (address > (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_max))) {
   3410                 return SOC_E_UNAVAIL;
   3411             } else {
   3412                 *array_index = 0;
   3413                 *index = address - SOC_MEM_INFO(unit, mem).base;
   3414                 return SOC_E_NONE;
   3415             }
   3416         }  else {
   3417             /* for arrays */        
   3418             if ((address < SOC_MEM_INFO(unit, mem).base) || 
   3419                            (address > (SOC_MEM_INFO(unit, mem).base + SOC_MEM_INFO(unit, mem).index_max +
   3420                                        (SOC_MEM_NUMELS(unit, mem) - 1) * SOC_MEM_ELEM_SKIP(unit, mem)))) {
   3421                 return SOC_E_UNAVAIL;
   3422             } else {
   3423                 array_size_base = SOC_MEM_ELEM_SKIP(unit, mem);
   3424                 *array_index = ((address - SOC_MEM_INFO(unit, mem).base) / array_size_base + SOC_MEM_ARRAY_INFO(unit, mem).first_array_index);
   3425                 *index = (address - SOC_MEM_INFO(unit, mem).base) % array_size_base;
   3426                 return SOC_E_NONE;
   3427             }
   3428         }
   3429     }
   3430     else {
   3431         return SOC_E_UNAVAIL;
   3432     }
   3433 }
   3434 
   3435 /*
   3436  * Function:     soc_mem_entry_bits
   3437  * Purpose:      Get number of bits in entry
   3438  * Returns:      Number of bits in the entry
   3439  */
   3440 int
   3441 soc_mem_entry_bits(int unit, soc_mem_t mem)
   3442 {
   3443     int                 f, end;
   3444     soc_field_info_t    *fieldp;
   3445     soc_mem_info_t      *memp;
   3446     int                 numbits = 0;
   3447 
   3448     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3449 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   3450         LOG_CLI((BSL_META_U(unit,
   3451                             "mem %s is invalid\n"), soc_mem_name[mem]));
   3452 #endif
   3453         assert(SOC_MEM_IS_VALID(unit, mem));
   3454     }
   3455 
   3456     memp = &SOC_MEM_INFO(unit, mem);
   3457 
   3458     for (f = 0; f < memp->nFields; f++) {
   3459         fieldp = &(memp->fields[f]);
   3460         end = fieldp->bp + fieldp->len;
   3461         if (end > numbits) {
   3462             numbits = end;
   3463         }
   3464     }
   3465 
   3466     return numbits;
   3467 }
   3468 
   3469 /*
   3470  * Function:
   3471  *     soc_mem_snoop_register
   3472  * Purpose:
   3473  *      Registers a snooping call back for specific memory.
   3474  *      Call back will be called on Read or Write operations
   3475  *      on the memory according to specified flags
   3476  * Parameters:
   3477  *      unit         -  (IN) BCM device number.
   3478  *      mem          -  (IN) Memory to register a call back for.
   3479  *      flags        -  (IN) SOC_MEM_SNOOP_XXX flags.
   3480  *      snoop_cv     -  (IN) User provided call back, NULL for unregister
   3481  *      user_data    -  (IN) user provided data to be passed to call back function
   3482  * Returns:
   3483  *      None
   3484  */
   3485 void
   3486 soc_mem_snoop_register(int unit, soc_mem_t mem, uint32 flags,
   3487                        soc_mem_snoop_cb_t snoop_cb, void *user_data)
   3488 {
   3489     soc_mem_info_t      *mem_info_p;
   3490 
   3491     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3492 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   3493         LOG_CLI((BSL_META_U(unit,
   3494                             "mem %s is invalid\n"), soc_mem_name[mem]));
   3495 #endif
   3496         assert(SOC_MEM_IS_VALID(unit, mem));
   3497     }
   3498 
   3499     mem_info_p = &SOC_MEM_INFO(unit, mem);
   3500 
   3501     assert(NULL != snoop_cb);
   3502 
   3503     mem_info_p->snoop_cb = snoop_cb;
   3504     mem_info_p->snoop_user_data = user_data;
   3505     mem_info_p->snoop_flags |= flags;
   3506 
   3507     return;
   3508 }
   3509 
   3510 /*
   3511  * Function:
   3512  *     soc_mem_snoop_unregister
   3513  * Purpose:
   3514  *      Unregisters a snooping call back with specific flag for specific memory.
   3515  *      This function will not fail even if call back was not previously
   3516  *      registered.
   3517  * Parameters:
   3518  *      unit         -  (IN) BCM device number.
   3519  *      mem          -  (IN) Memory to register a call back for.
   3520  *      flags        -  (IN) SOC_MEM_SNOOP_XXX flags.
   3521  * Returns:
   3522  *      None
   3523  */
   3524 void
   3525 soc_mem_snoop_unregister(int unit, soc_mem_t mem, uint32 flags)
   3526 {
   3527     soc_mem_info_t      *mem_info_p;
   3528 
   3529     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3530 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
   3531         LOG_CLI((BSL_META_U(unit,
   3532                             "mem %s is invalid\n"), soc_mem_name[mem]));
   3533 #endif
   3534         assert(SOC_MEM_IS_VALID(unit, mem));
   3535     }
   3536 
   3537     mem_info_p = &SOC_MEM_INFO(unit, mem);
   3538 
   3539     if (SOC_MEM_SNOOP_UNREGISTER & flags) {
   3540         mem_info_p->snoop_cb = NULL;
   3541         mem_info_p->snoop_user_data = NULL;
   3542         mem_info_p->snoop_flags = 0;
   3543     } else {
   3544         mem_info_p->snoop_flags &= ~flags;
   3545         if (mem_info_p->snoop_flags == 0) {
   3546             mem_info_p->snoop_cb = NULL;
   3547             mem_info_p->snoop_user_data = NULL;
   3548         }
   3549     }
   3550 
   3551     return;
   3552 }
   3553 #endif /* BCM_ESW_SUPPORT || BCM_SAND_SUPPORT || defined(PORTMOD_SUPPORT)*/
   3554 
   3555 #ifdef BCM_ESW_SUPPORT
   3556 /* Resolve DESTINATIONf value to type and value
   3557  * dest_type - OUT
   3558  * value     - OUT
   3559  */
   3560 void _soc_mem_dest_value_resolve(int unit, uint32 dest_value, uint32 *enum_type,
   3561                                  uint32 *value)
   3562 {
   3563     uint32 dest_type;
   3564 
   3565     /* Decode application enum type and destination type */
   3566     *enum_type = SOC_MEM_FIF_DEST_INVALID;
   3567     *value = 0;
   3568 
   3569     if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE0f)) != 0) {
   3570         switch (dest_type) {
   3571             case 3:
   3572                 *enum_type = SOC_MEM_FIF_DEST_NEXTHOP;
   3573                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value,NEXT_HOP_INDEXf);
   3574                 break;
   3575             case 2:
   3576                 *enum_type = SOC_MEM_FIF_DEST_DGPP;
   3577                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DGPPf);
   3578                 break;
   3579             case 1:
   3580                 *enum_type = SOC_MEM_FIF_DEST_DVP;
   3581                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DVPf);
   3582                 break;
   3583             default:
   3584                 break;
   3585         }
   3586     } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE1f)) != 0) {
   3587         switch (dest_type) {
   3588             case 3:
   3589                 *enum_type = SOC_MEM_FIF_DEST_IPMC;
   3590                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, IPMC_GROUPf);
   3591                 break;
   3592             case 2:
   3593                 *enum_type = SOC_MEM_FIF_DEST_L2MC;
   3594                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, L2MC_GROUPf);
   3595                 break;
   3596             case 1:
   3597                 *enum_type = SOC_MEM_FIF_DEST_ECMP;
   3598                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, ECMP_GROUPf);
   3599                 break;
   3600             default:
   3601                 break;
   3602         }
   3603     } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE2f)) != 0) {
   3604         switch (dest_type) {
   3605             case 1:
   3606                 *enum_type = SOC_MEM_FIF_DEST_LAG;
   3607                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, LAGf);
   3608                 break;
   3609             default:
   3610                 break;
   3611        }
   3612     } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE3f)) != 0) {
   3613         switch (dest_type) {
   3614             case 3:
   3615                 *enum_type = SOC_MEM_FIF_DEST_MYSTA;
   3616                 *value = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, MY_STATION_PROFILE_IDXf);
   3617                 break;
   3618             default:
   3619                 break;
   3620         }
   3621     } else if ((dest_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt, &dest_value, DEST_TYPE5f)) !=0 ) {
   3622         switch (dest_type) {
   3623             case 3:
   3624                 *enum_type = SOC_MEM_FIF_DEST_DISC_CP2CPU;
   3625                 *value = 0;
   3626                 break;
   3627             case 2:
   3628                 *enum_type = SOC_MEM_FIF_DEST_DISC;
   3629                 *value = 0;
   3630                 break;
   3631             default:
   3632                 break;
   3633         }
   3634     }
   3635 
   3636     return ;
   3637 }
   3638 
   3639 /* Construct DESTINATIONf value with type and value
   3640  * return - DESTINATIONf value
   3641  */
   3642 uint32
   3643 _soc_mem_dest_value_construct(int unit, uint32 dest_type, uint32 value)
   3644 {
   3645     soc_field_t  format_type_field = INVALIDf;
   3646     uint32       format_type_field_value = 0;
   3647     soc_field_t  format_value_field = INVALIDf;
   3648     uint32       format_value_field_value = 0;
   3649     uint32       dest_value = 0;
   3650 
   3651     switch (dest_type) {
   3652         case SOC_MEM_FIF_DEST_NEXTHOP:
   3653             format_type_field            = DEST_TYPE0f;
   3654             format_type_field_value      = 3;
   3655             format_value_field           = NEXT_HOP_INDEXf;
   3656             format_value_field_value     = value;
   3657             break;
   3658         case SOC_MEM_FIF_DEST_DGPP:
   3659             format_type_field            = DEST_TYPE0f;
   3660             format_type_field_value      = 2;
   3661             format_value_field           = DGPPf;
   3662             format_value_field_value     = value;
   3663             break;
   3664         case SOC_MEM_FIF_DEST_DVP:
   3665             format_type_field            = DEST_TYPE0f;
   3666             format_type_field_value      = 1;
   3667             format_value_field           = DVPf;
   3668             format_value_field_value     = value;
   3669             break;
   3670         case SOC_MEM_FIF_DEST_IPMC:
   3671             format_type_field            = DEST_TYPE1f;
   3672             format_type_field_value      = 3;
   3673             format_value_field           = IPMC_GROUPf;
   3674             format_value_field_value     = value;
   3675             break;
   3676         case SOC_MEM_FIF_DEST_L2MC:
   3677             format_type_field            = DEST_TYPE1f;
   3678             format_type_field_value      = 2;
   3679             format_value_field           = L2MC_GROUPf;
   3680             format_value_field_value     = value;
   3681             break;
   3682         case SOC_MEM_FIF_DEST_ECMP:
   3683             format_type_field            = DEST_TYPE1f;
   3684             format_type_field_value      = 1;
   3685             format_value_field           = ECMP_GROUPf;
   3686             format_value_field_value     = value;
   3687             break;
   3688         case SOC_MEM_FIF_DEST_LAG:
   3689             format_type_field            = DEST_TYPE2f;
   3690             format_type_field_value      = 1;
   3691             format_value_field           = LAGf;
   3692             format_value_field_value     = value;
   3693             break;
   3694         case SOC_MEM_FIF_DEST_MYSTA:
   3695             format_type_field            = DEST_TYPE3f;
   3696             format_type_field_value      = 3;
   3697             format_value_field           = MY_STATION_PROFILE_IDXf;
   3698             format_value_field_value     = value;
   3699             break;
   3700         case SOC_MEM_FIF_DEST_DISC_CP2CPU:
   3701             format_type_field            = DEST_TYPE5f;
   3702             format_type_field_value      = 3;
   3703             break;
   3704         case SOC_MEM_FIF_DEST_DISC:
   3705             format_type_field            = DEST_TYPE5f;
   3706             format_type_field_value      = 2;
   3707             break;
   3708         default:
   3709             dest_value = 0;
   3710             break;
   3711     }
   3712 
   3713     /* Convert field data into format type */
   3714     if (format_type_field != INVALIDf) {
   3715         soc_format_field32_set(unit, DESTINATION_FORMATfmt, &dest_value,  format_type_field,  format_type_field_value);
   3716     }
   3717 
   3718     if (format_value_field != INVALIDf) {
   3719         soc_format_field32_set(unit, DESTINATION_FORMATfmt, &dest_value,  format_value_field,  format_value_field_value);
   3720     }
   3721 
   3722     return (dest_value);
   3723 }
   3724 
   3725 /*
   3726  * soc_mem_field32_dest_set
   3727  *
   3728  * Based on application enum type, covert configuration value
   3729  * to destination format and write it to hardware memory.
   3730  */
   3731 void
   3732 soc_mem_field32_dest_set(int unit, soc_mem_t mem, void *entbuf,
   3733                          soc_field_t fld, uint32 dest_type, uint32 value)
   3734 {
   3735     uint32       dest_value = 0;
   3736 
   3737     /* Convert value into destination format */
   3738     dest_value = _soc_mem_dest_value_construct(unit, dest_type, value);
   3739 
   3740     /* Write data (in format structure) to memory buffer */
   3741     soc_mem_field32_set(unit, mem, entbuf,  fld, dest_value);
   3742 
   3743     return;
   3744 }
   3745 
   3746 /*
   3747  * soc_mem_field32_dest_get
   3748  *
   3749  * Derive application enum type and destination value from hardware readout
   3750  * based on destination format.
   3751  */
   3752 uint32
   3753 soc_mem_field32_dest_get(int unit, soc_mem_t mem, const void *entbuf,
   3754                          soc_field_t fld, uint32 *enum_type)
   3755 {
   3756     uint32 dest_value;
   3757     uint32 value = 0;
   3758 
   3759     /* Hardware memory readout */
   3760     dest_value = soc_mem_field32_get(unit, mem, entbuf, fld);
   3761 
   3762     /* Decode readout from destination format */
   3763     _soc_mem_dest_value_resolve(unit, dest_value, enum_type, &value);
   3764 
   3765     return value;
   3766 }
   3767 #endif /* End of BCM_ESW_SUPPORT */