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

drvformat.c (16064B)


      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  * format 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/drv.h>
     17 
     18 #include <soc/mem.h>
     19 #include <soc/memory.h>
     20 #include <soc/format.h>
     21 
     22 #include <soc/error.h>
     23 
     24 #if defined(BCM_ESW_SUPPORT)
     25 
     26 /*
     27  * Macro used by memory accessor functions to fix order
     28  */
     29 #define FIX_FORMAT_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \
     30                                 BITS2WORDS((m)->bits)-1-(v) : \
     31                                 (v))
     32 
     33 /*************************************************************
     34  * Function:     soc_format_field_length
     35  * Purpose:      Return the length of a format field in bits.
     36  *               Value is 0 if field is not found.
     37  * Returns:      bits in field
     38  */
     39 int
     40 soc_format_field_length(int unit, soc_format_t format, soc_field_t field)
     41 {
     42     soc_field_info_t    *fld;
     43 
     44     SOC_FIND_FIELD(field,
     45                    SOC_FORMAT_INFO(unit, format).fields,
     46                    SOC_FORMAT_INFO(unit, format).nFields,
     47                    fld);
     48     if (fld == NULL) {
     49         return 0;
     50     }
     51     return fld->len;
     52 }
     53 
     54 /********************************************************************
     55  * Function:      _soc_formatinfo_field_get
     56  * Purpose:       Get a format field without reference to chip.
     57  * Parameters:    formatinfo   --  direct reference to format
     58  */
     59 STATIC uint32 *
     60 _soc_formatinfo_field_get(soc_format_t format, soc_format_info_t *formatinfo,
     61                       const uint32 *entbuf, soc_field_t field, uint32 *fldbuf,
     62                       uint32 fldbuf_size) /* The number of uint32s in fldbuf */
     63 {
     64     soc_field_info_t    *fieldinfo;
     65     int                 i, wp, bp, len;
     66 
     67     SOC_FIND_FIELD(field,
     68                    formatinfo->fields,
     69                    formatinfo->nFields,
     70                    fieldinfo);
     71     if (NULL == fieldinfo) {
     72 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
     73         LOG_CLI((BSL_META("format %s field %s is invalid\n"),
     74                  soc_format_name[format], soc_fieldnames[field]));
     75 #endif
     76         assert(fieldinfo);
     77     }
     78 
     79     /*
     80      * COVERITY
     81      *
     82      * assert validates the input for NULL
     83      */
     84     /* coverity[var_deref_op : FALSE] */
     85     bp = fieldinfo->bp;
     86     len = fieldinfo->len;
     87     assert(len / 32 <= fldbuf_size); /* assert we do not write beyond
     88                                       * the end of the output buffer */
     89 
     90     if (len == 1) {     /* special case single bits */
     91         wp = bp / 32;
     92         bp = bp & (32 - 1);
     93         if (entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] & (1<<bp)) {
     94             fldbuf[0] = 1;
     95         } else {
     96             fldbuf[0] = 0;
     97         }
     98         return fldbuf;
     99     }
    100 
    101     if (fieldinfo->flags & SOCF_LE) {
    102         wp = bp / 32;
    103         bp = bp & (32 - 1);
    104         i = 0;
    105 
    106         for (; len > 0; len -= 32) {
    107             if (bp) {
    108                 fldbuf[i] =
    109                     entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] >> bp &
    110                     ((1 << (32 - bp)) - 1);
    111                 if ( len > (32 - bp) ) {
    112                     fldbuf[i] |= entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] <<
    113                         (32 - bp);
    114                 }
    115             } else {
    116                 fldbuf[i] = entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)];
    117             }
    118 
    119             if (len < 32) {
    120                 fldbuf[i] &= ((1 << len) - 1);
    121             }
    122 
    123             i++;
    124         }
    125     } else {
    126         i = (len - 1) / 32;
    127 
    128         while (len > 0) {
    129             assert(i >= 0);
    130 
    131             fldbuf[i] = 0;
    132 
    133             do {
    134                 fldbuf[i] =
    135                     (fldbuf[i] << 1) |
    136                     ((entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] >>
    137                       (bp & (32 - 1))) & 1);
    138                 len--;
    139                 bp++;
    140             } while (len & (32 - 1));
    141 
    142             i--;
    143         }
    144     }
    145 
    146     return fldbuf;
    147 }
    148 
    149 /********************************************************************
    150  * Function:      _soc_format_field_value_fit
    151  * Purpose:       Check if value will fit into a format field.
    152  * Parameters:    fieldinfo --  (IN)Direct reference to field description.
    153  *                value     --  (IN)Value to be checked.
    154  * Returns:
    155  *      TRUE  - buffer fits into the field.
    156  *      FALSE - Otherwise.
    157  */
    158 STATIC int
    159 _soc_format_field_value_fit(soc_field_info_t *fieldinfo, uint32 *value)
    160 {
    161     uint32      mask;    /* Value mask                      */
    162     uint16      len;     /* Bits in field                   */
    163     int         idx;     /* Iteration index.                */
    164 
    165     idx = (fieldinfo->len - 1) >> 5;
    166     len = fieldinfo->len % 32;
    167 
    168     if (!len) {
    169        return TRUE;
    170     }
    171 
    172     mask = (1 << len) - 1;
    173     if((value[idx] & ~mask) != 0) {
    174         return (FALSE);
    175     }
    176     return (TRUE);
    177 }
    178 
    179 /************************************************************************
    180  * Function:      _soc_formatinfo_field_set
    181  * Purpose:       Set a format field without reference to chip.
    182  * Parameters:    formatinfo   --  direct reference format
    183  */
    184 STATIC void
    185 _soc_formatinfo_field_set(soc_format_t format, soc_format_info_t *formatinfo,
    186                     uint32 *entbuf, soc_field_t field, uint32 *fldbuf)
    187 {
    188     soc_field_info_t    *fieldinfo;
    189     uint32              mask;
    190     int                 i, wp, bp, len;
    191 
    192     SOC_FIND_FIELD(field,
    193                    formatinfo->fields,
    194                    formatinfo->nFields,
    195                    fieldinfo);
    196     if (NULL == fieldinfo) {
    197 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    198         LOG_CLI((BSL_META("format %s field %s is invalid\n"),
    199                  soc_format_name[format], soc_fieldnames[field]));
    200 #endif
    201         assert(fieldinfo);
    202     }
    203 
    204     /* Make sure value fits into the field. */
    205     /*
    206      * COVERITY
    207      *
    208      * assert validates the input for NULL
    209      */
    210     /* coverity[var_deref_model : FALSE] */
    211     if (!_soc_format_field_value_fit(fieldinfo, fldbuf)) {
    212 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    213         LOG_CLI((BSL_META("format %s field %s value does not fit\n"),
    214                  soc_format_name[format], soc_fieldnames[field]));
    215 #endif
    216         assert(_soc_format_field_value_fit(fieldinfo, fldbuf));
    217     }
    218 
    219     bp = fieldinfo->bp;
    220 
    221     if (fieldinfo->flags & SOCF_LE) {
    222         wp = bp / 32;
    223         bp = bp & (32 - 1);
    224         i = 0;
    225 
    226         for (len = fieldinfo->len; len > 0; len -= 32) {
    227             if (bp) {
    228                 if (len < 32) {
    229                     mask = (1 << len) - 1;
    230                 } else {
    231                     mask = -1;
    232                 }
    233 
    234                 entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &= ~(mask << bp);
    235                 entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] |= fldbuf[i] << bp;
    236                 if (len > (32 - bp)) {
    237                     entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &=
    238                                                   ~(mask >> (32 - bp));
    239                     entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] |=
    240                         fldbuf[i] >> (32 - bp) & ((1 << bp) - 1);
    241                 }
    242             } else {
    243                 if (len < 32) {
    244                     mask = (1 << len) - 1;
    245                     entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &= ~mask;
    246                     entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] |=
    247                                                          fldbuf[i] << bp;
    248                 } else {
    249                     entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] = fldbuf[i];
    250                 }
    251             }
    252 
    253             i++;
    254         }
    255     } else {                           /* Big endian: swap bits */
    256         len = fieldinfo->len;
    257 
    258         while (len > 0) {
    259             len--;
    260             entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] &=
    261                                                    ~(1 << (bp & (32-1)));
    262             entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] |=
    263                 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1));
    264             bp++;
    265         }
    266     }
    267 }
    268 /***************************************************************
    269  * Function:
    270  *      soc_format_field_valid
    271  * Purpose:
    272  *      Verify if field is valid & present in format
    273  * Parameters:
    274  *      format     - (IN)Format id.
    275  *      field   - (IN)Field id.
    276  * Return:
    277  *      TRUE  -If field is present & valid.
    278  *      FALSE -Otherwise.
    279  */
    280 int
    281 soc_format_field_valid(int unit, soc_format_t format, soc_field_t field)
    282 {
    283     soc_format_info_t  *formatinfo;
    284     soc_field_info_t    *finfop; /* Field information structure. */
    285 
    286     /* Verify that memory is present on the device. */
    287     if (!SOC_FORMAT_IS_VALID(unit, format))  {
    288         return FALSE;
    289     }
    290 
    291     formatinfo = &SOC_FORMAT_INFO(unit, format);
    292     SOC_FIND_FIELD(field,
    293                    formatinfo->fields,
    294                    formatinfo->nFields,
    295                    finfop);
    296     return (finfop != NULL) ? TRUE : FALSE;
    297 }
    298 
    299 /****************************************************
    300  * Function:    soc_format_field_get
    301  * Purpose:     Get a format field
    302  * Parameters:  unit - device
    303  *              format
    304  *              entbuf - format entry buffer
    305  *              field - which field to get
    306  *              fldbuf - field buffer
    307  */
    308 uint32 *
    309 soc_format_field_get(int unit, soc_format_t format, const uint32 *entbuf,
    310                   soc_field_t field, uint32 *fldbuf)
    311 {
    312     soc_format_info_t *formatinfo;
    313 
    314     if (!SOC_FORMAT_IS_VALID(unit, format)) {
    315 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    316         LOG_CLI((BSL_META_U(unit,
    317                             "format %s is invalid\n"), soc_format_name[format]));
    318 #endif
    319         assert(SOC_FORMAT_IS_VALID(unit, format));
    320     }
    321 
    322     formatinfo = &SOC_FORMAT_INFO(unit, format);
    323 
    324     return _soc_formatinfo_field_get(format, formatinfo, entbuf,
    325                                    field, fldbuf, SOC_MAX_FORMAT_WORDS);
    326 }
    327 
    328 /********************************************************
    329  * Function:    soc_format_field_set
    330  * Purpose:     Set a format field
    331  * Parameters:  unit - device
    332  *              format
    333  *              entbuf - format entry buffer
    334  *              field - which field to set
    335  *              fldbuf - field buffer
    336  */
    337 void
    338 soc_format_field_set(int unit, soc_format_t format, uint32 *entbuf,
    339                       soc_field_t field, uint32 *fldbuf)
    340 {
    341     soc_format_info_t *formatinfo;
    342 
    343     if (!SOC_FORMAT_IS_VALID(unit, format)) {
    344 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    345         LOG_CLI((BSL_META_U(unit,
    346                             "format %s is invalid\n"),
    347                                     soc_format_name[format]));
    348 #endif
    349         assert(SOC_FORMAT_IS_VALID(unit, format));
    350     }
    351 
    352     formatinfo = &SOC_FORMAT_INFO(unit, format);
    353 
    354     _soc_formatinfo_field_set(format, formatinfo, entbuf, field, fldbuf);
    355 }
    356 
    357 /***********************************************************
    358  * Function:     soc_format_field32_get
    359  * Purpose:      Get a <=32 bit field out of a format entry
    360  * Returns:      The value of the field
    361  */
    362 uint32
    363 soc_format_field32_get(int unit, soc_format_t format, const void *entbuf,
    364                     soc_field_t field)
    365 {
    366     uint32              value;
    367 
    368     if (!SOC_FORMAT_IS_VALID(unit, format)) {
    369 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    370         LOG_CLI((BSL_META_U(unit, "format %s is invalid\n"),
    371                                   soc_format_name[format]));
    372 #endif
    373         assert(SOC_FORMAT_IS_VALID(unit, format));
    374     }
    375     _soc_formatinfo_field_get(format, &SOC_FORMAT_INFO(unit, format),
    376                              entbuf, field, &value, 1);
    377 
    378     return value;
    379 }
    380 
    381 /***********************************************************
    382  * Function:     soc_format_field32_set
    383  * Purpose:      Set a <=32 bit field out of a format entry
    384  * Returns:      void
    385  */
    386 void
    387 soc_format_field32_set(int unit, soc_format_t format, void *entbuf,
    388                     soc_field_t field, uint32 value)
    389 {
    390     /*
    391      * COVERITY
    392      *
    393      * We do this intentionally to use the generic function
    394      * soc_format_field_set() which does the necessary handling.
    395  */
    396     /* coverity[callee_ptr_arith : FALSE] */
    397     soc_format_field_set(unit, format, entbuf, field, &value);
    398 }
    399 
    400 /***********************************************************
    401  * Function:     soc_dop_format_get
    402  * Purpose:      get the format corresponding to a dop_id
    403  * Inputs:       unit - device
    404  *               dop_id - 16 bit dop_id
    405  *               dop_block - block
    406  * Outputs:      format
    407  *               n_data_phase entry from the corresponding Format
    408  * Returns:      SOC_E_NONE if found
    409  *               SOC_E_NOT_FOUND if given DOP is not found
    410  *               SOC_E_UNAVAIL if DOP functionality is not available
    411  */
    412 int
    413 soc_dop_format_get(int unit, uint16 dop_id, uint16 dop_block, uint16 *n_data_phases, soc_format_t *format)
    414 {
    415     uint32 dop_id_blk = 0;
    416     int i=0;
    417     soc_dop_t *myDop = SOC_DOP_INFO(unit);
    418 
    419     if (NULL == myDop) {
    420         return SOC_E_UNAVAIL;
    421     }
    422 
    423     dop_id_blk = dop_id | (dop_block << 16);
    424 
    425     while (myDop[i].dop_id != 0)
    426     {
    427         if (myDop[i].dop_id == dop_id_blk)
    428         {
    429             *n_data_phases = myDop[i].n_data_phases;
    430             *format = myDop[i].dop_fmt;
    431             return SOC_E_NONE;
    432         }
    433         i++;
    434     }
    435     return SOC_E_NOT_FOUND;
    436 }
    437 
    438 /********************************************************************
    439  * Function:      _soc_format_fieldinfo_get
    440  * Purpose:       Get a format field info without reference to chip.
    441  * Parameters:    unit - device
    442  *                fmt  - format
    443  *                field - Field in format
    444  * Returns        Reference to field info format               
    445  */
    446 soc_field_info_t *
    447 soc_format_fieldinfo_get(int unit, soc_format_t fmt, soc_field_t field)
    448 {
    449     soc_field_info_t    *fieldinfo;
    450     soc_format_info_t   *formatinfo;
    451 
    452     if (!SOC_FORMAT_IS_VALID(unit, fmt)) {
    453 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    454         LOG_CLI((BSL_META_U(unit,
    455                             "format %s is invalid\n"), soc_format_name[fmt]));
    456 #endif
    457         assert(SOC_FORMAT_IS_VALID(unit, fmt));
    458     }
    459 
    460     formatinfo = &SOC_FORMAT_INFO(unit, fmt);
    461 
    462     SOC_FIND_FIELD(field,
    463                    formatinfo->fields,
    464                    formatinfo->nFields,
    465                    fieldinfo);
    466     if (NULL == fieldinfo) {
    467 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    468         LOG_CLI((BSL_META("format %s field %s is invalid\n"),
    469                  soc_format_name[fmt], soc_fieldnames[field]));
    470 #endif
    471         assert(fieldinfo);
    472     }
    473 
    474     return fieldinfo;
    475 }
    476 
    477 /********************************************************************
    478  * Function:      soc_format_entry_dump
    479  * Purpose:       Dump the format entry.
    480  * Parameters:    unit - device
    481  *                fmt  - format
    482  *                entbuf - format entry buffer
    483  * Returns:       voiod
    484  */
    485 void
    486 soc_format_entry_dump(int unit, soc_format_t format, const uint32 *entbuf)
    487 {
    488     soc_format_info_t *formatinfo;
    489     soc_field_info_t *finfo;
    490     int f_idx;
    491     uint32 fbuf[SOC_MAX_MEM_FIELD_WORDS];
    492     char   tmp[512];
    493 
    494     if (!SOC_FORMAT_IS_VALID(unit, format)) {
    495         assert(SOC_FORMAT_IS_VALID(unit, format));
    496     }
    497 
    498     formatinfo = &SOC_FORMAT_INFO(unit, format);
    499 
    500     BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit,
    501                         "%s"), "<"));
    502     for (f_idx = 0;
    503          f_idx < formatinfo->nFields;
    504          f_idx++) {
    505         finfo = &formatinfo->fields[f_idx];
    506         soc_format_field_get(unit,
    507                    format,
    508                    entbuf,
    509                    finfo->field,
    510                    fbuf);
    511         sal_memset(tmp, 0, sizeof(tmp));
    512         _shr_format_long_integer(tmp, fbuf, BITS2BYTES(finfo->len));
    513 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES)
    514         BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit,
    515             "%s<%d:%d>=%s%s"), soc_fieldnames[finfo->field], finfo->bp, finfo->bp+finfo->len-1,
    516         tmp, ","));
    517 #endif
    518     }
    519     BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit,
    520                   "%s\n"), ">"));
    521 }
    522 #endif