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

bitop.c (25970B)


      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  * Bit Array routines
      8  */
      9 
     10 #include <shared/bitop.h>
     11 #include <sal/core/libc.h>
     12 
     13 /* Same as shr_bitop_range_null, but for a single SHR_BITDCL.
     14    The following constraints are kept:
     15    a. first < SHR_BITWID
     16    b. first + bit_count <= SHR_BITWID
     17 */
     18 STATIC INLINE int
     19 shr_bitop_range_null_one_bitdcl(CONST SHR_BITDCL bits,
     20                                 CONST int first,
     21                                 CONST int bit_count)
     22 {
     23     SHR_BITDCL mask = ~0;
     24 
     25     mask >>= (SHR_BITWID - bit_count);
     26     /* Move the mask to start from 'first' offset */
     27     mask <<= first;
     28     return (bits & mask) == 0;
     29 }
     30 
     31 /* returns 1 if the bit array is empty */
     32 int
     33 shr_bitop_range_null(CONST SHR_BITDCL *bits,
     34                      CONST int first,
     35                      int bit_count)
     36 {
     37     CONST SHR_BITDCL *ptr;
     38     int woff_first, wremain;
     39 
     40     if(bit_count <= 0) {
     41         return 1;
     42     }
     43 
     44     /* Pointer to first SHR_BITDCL in 'bits' that contains 'first' */
     45     ptr = bits + (first / SHR_BITWID);
     46     
     47     /* Offset of 'first' bit within this SDH_BITDCL */
     48     woff_first = first % SHR_BITWID;
     49 
     50     /* Check if 'first' is SHR_BITWID aligned */
     51     if (woff_first != 0) {
     52         /*  Get remaining bits in this SDH_BITDCL */
     53         wremain = SHR_BITWID - woff_first;
     54         if (bit_count <= wremain) {
     55             /* All the range is in one SHR_BITDCL */
     56             return shr_bitop_range_null_one_bitdcl(*ptr,
     57                                                    woff_first,
     58                                                    bit_count);
     59         }
     60         /* We should check the first SHR_BITDCL, and might also continue */
     61         if (!shr_bitop_range_null_one_bitdcl(*ptr, woff_first, wremain)) {
     62             return 0;
     63         }
     64         bit_count -= wremain;
     65         ++ptr;
     66     }
     67     while (bit_count >= SHR_BITWID) {
     68         /* We're testing a full SHR_BITDCL */
     69         if (*(ptr++)) {
     70             return 0;
     71         }
     72         bit_count -= SHR_BITWID;
     73     }
     74     /* This is the last SHR_BITDCL, and it is not SHR_BITWID */
     75     if(bit_count > 0) {
     76         return shr_bitop_range_null_one_bitdcl(*ptr, 0, bit_count);
     77     }
     78     return 1;
     79 }
     80 
     81 /* Same as shr_bitop_range_eq, but for a single SHR_BITDCL.
     82    The following constraints are kept:
     83    a. first < SHR_BITWID
     84    b. first + range <= SHR_BITWID
     85 */
     86 STATIC INLINE int
     87 shr_bitop_range_eq_one_bitdcl(CONST SHR_BITDCL bits1,
     88                               CONST SHR_BITDCL bits2,
     89                               CONST int first,
     90                               CONST int range)
     91 {
     92     SHR_BITDCL mask = ~0;
     93     mask >>= (SHR_BITWID - range);
     94     /* Move the mask to start from 'first' offset */
     95     mask <<= first;
     96     return (bits1 & mask) == (bits2 & mask);
     97 }
     98 
     99 /* returns 1 if the two bitmaps are equal */
    100 int
    101 shr_bitop_range_eq(CONST SHR_BITDCL *bits1,
    102                    CONST SHR_BITDCL *bits2,
    103                    CONST int first,
    104                    int range)
    105 {
    106     CONST SHR_BITDCL *ptr1;
    107     CONST SHR_BITDCL *ptr2;
    108     int woff_first, wremain;
    109 
    110     if(range <= 0) {
    111         return 1;
    112     }
    113 
    114     ptr1 = bits1 + (first / SHR_BITWID);
    115     ptr2 = bits2 + (first / SHR_BITWID);
    116     
    117     woff_first = first % SHR_BITWID;
    118     
    119     if (woff_first != 0) {
    120         wremain = SHR_BITWID - woff_first;
    121         if (range <= wremain) {
    122             return shr_bitop_range_eq_one_bitdcl(*ptr1,
    123                                                  *ptr2,
    124                                                  woff_first,
    125                                                  range);
    126         }
    127         if (!shr_bitop_range_eq_one_bitdcl(*ptr1,
    128                                           *ptr2,
    129                                           woff_first,
    130                                           wremain)) {
    131             return 0;
    132         }
    133         range -= wremain;
    134         ++ptr1, ++ptr2;
    135     }
    136     while (range >= SHR_BITWID) {
    137         if (*(ptr1++) != *(ptr2++)) {
    138             return 0;
    139         }
    140         range -= SHR_BITWID;
    141     }
    142     if(range > 0) {
    143         return shr_bitop_range_eq_one_bitdcl(*ptr1, *ptr2, 0, range);
    144     }
    145     return 1;
    146 }
    147 
    148 STATIC INLINE int
    149 shr_bitop_range_count_uchar(CONST uint8 bits)
    150 {
    151     uint8 tmp_res;
    152  
    153     /* Efficient algorithm to count bits */
    154     tmp_res = (bits & 0x55) + ((bits & 0xaa) >> 1);
    155     tmp_res = (tmp_res & 0x33) + ((tmp_res & 0xcc) >> 2);
    156     return (int) ((tmp_res & 0xf) + ((tmp_res & 0xf0) >> 4));
    157 } 
    158 
    159 STATIC INLINE int
    160 shr_bitop_range_count_bitdcl_all_bits(CONST SHR_BITDCL bits)
    161 {
    162     int count = 0, i;
    163     for(i = 0; i < sizeof(SHR_BITWID); ++i) {
    164         count += shr_bitop_range_count_uchar((bits >> (8*i)) & 0xff);
    165     }
    166     return count;
    167 }
    168 
    169 /* Same as shr_bitop_range_count, but for a single SHR_BITDCL.
    170    The following constraints are kept:
    171    a. first < SHR_BITWID
    172    b. first + range <= SHR_BITWID
    173 */
    174 STATIC INLINE int
    175 shr_bitop_range_count_one_bitdcl(CONST SHR_BITDCL bits,
    176                                  CONST int first,
    177                                  CONST int range)
    178 {
    179     SHR_BITDCL mask = ~0;
    180     mask >>= (SHR_BITWID - range);
    181     mask <<= first;
    182     return shr_bitop_range_count_bitdcl_all_bits(bits & mask);
    183 }
    184 
    185 /* returns the number of set bits is the specified range for the bitmap */
    186 void
    187 shr_bitop_range_count(CONST SHR_BITDCL *bits,
    188                       CONST int first,
    189                       int range,
    190                       int *count)
    191 {
    192     CONST SHR_BITDCL *ptr;
    193     int woff_first, wremain;
    194 
    195     ptr = bits + (first / SHR_BITWID);
    196     
    197     woff_first = first % SHR_BITWID;
    198     
    199     *count = 0;
    200 
    201     if(range <= 0) {
    202         return;
    203     }
    204 
    205     if (woff_first != 0) {
    206         wremain = SHR_BITWID - woff_first;
    207         if (range <= wremain) {
    208             *count = shr_bitop_range_count_one_bitdcl(*ptr, woff_first, range);
    209             return;
    210         }
    211         *count += shr_bitop_range_count_one_bitdcl(*ptr, woff_first, wremain);
    212         range -= wremain;
    213         ++ptr;
    214     }
    215     while (range >= SHR_BITWID) {
    216         *count += shr_bitop_range_count_bitdcl_all_bits(*(ptr++));
    217         range -= SHR_BITWID;
    218     }
    219     if(range > 0) {
    220         *count += shr_bitop_range_count_one_bitdcl(*ptr, 0, range);
    221     }
    222 }
    223 
    224 /* Same as shr_bitop_range_copy, but for a single SHR_BITDCL.
    225    The following constraints are kept:
    226    a. dst_first, src_first < SHR_BITWID
    227    b. dst_first + range, src_first + range <= SHR_BITWID
    228 */
    229 STATIC INLINE void
    230 shr_bitop_range_copy_one_bitdcl(SHR_BITDCL *dst_ptr,
    231                                 CONST int dst_first,
    232                                 CONST SHR_BITDCL src,
    233                                 CONST int src_first,
    234                                 CONST int range)
    235 {
    236     SHR_BITDCL data;
    237     SHR_BITDCL mask;
    238 
    239     /* no need to check that dst_first == 0 and src_first == 0,
    240        It must be becuse of the constrains */
    241     if ((range) == SHR_BITWID) {
    242         *(dst_ptr) = src;
    243         return;
    244     }
    245     /* get the data */
    246     data = src >> (src_first);
    247     /* align the data to the place it may be inserted */
    248     data <<= (dst_first);
    249 
    250     /* We might have bits in src_ptr above src_first + range
    251        that need to be cleared */
    252     mask = ~0;
    253     mask >>= SHR_BITWID - range;
    254     mask <<= dst_first;
    255     data &= mask;
    256     *(dst_ptr) &= ~mask;
    257     *(dst_ptr) |= data;
    258 }
    259 
    260 void
    261 shr_bitop_range_copy(SHR_BITDCL *dst_ptr,
    262                      CONST int dst_first,
    263                      CONST SHR_BITDCL *src_ptr,
    264                      CONST int src_first,
    265                      int range)
    266 {
    267     if(range <= 0) {
    268         return;
    269     }
    270 
    271     if ((((dst_first) % SHR_BITWID) == 0) &&
    272         (((src_first) % SHR_BITWID) == 0) &&
    273         (((range) % SHR_BITWID) == 0)) {
    274             sal_memcpy(&((dst_ptr)[(dst_first) / SHR_BITWID]),
    275                 &((src_ptr)[(src_first) / SHR_BITWID]),
    276                 SHR_BITALLOCSIZE(range));
    277     } else {
    278         SHR_BITDCL *cur_dst;
    279         CONST SHR_BITDCL *cur_src;
    280 
    281         int woff_src, woff_dst, wremain;
    282 
    283         cur_dst = (dst_ptr) + ((dst_first) / SHR_BITWID);
    284         cur_src = (src_ptr) + ((src_first) / SHR_BITWID);
    285 
    286         woff_src = src_first % SHR_BITWID;
    287         woff_dst = dst_first % SHR_BITWID;
    288 
    289         if (woff_dst >= woff_src) {
    290             wremain = SHR_BITWID - woff_dst;
    291         } else {
    292             wremain = SHR_BITWID - woff_src;
    293         }
    294         if (range <= wremain) {
    295             shr_bitop_range_copy_one_bitdcl(cur_dst,
    296                                             woff_dst,
    297                                             *cur_src,
    298                                             woff_src,
    299                                             range);
    300             return;
    301         }
    302         shr_bitop_range_copy_one_bitdcl(cur_dst,
    303                                         woff_dst,
    304                                         *cur_src,
    305                                         woff_src,
    306                                         wremain);
    307         range -= wremain;
    308         while (range >= SHR_BITWID) {
    309             if (woff_dst >= woff_src) {
    310                 ++cur_dst;
    311                 wremain = woff_dst - woff_src;
    312                 if(wremain > 0) {
    313                     shr_bitop_range_copy_one_bitdcl(cur_dst,
    314                                                     0,
    315                                                     *cur_src,
    316                                                     SHR_BITWID - wremain,
    317                                                     wremain);
    318                 }
    319             } else {
    320                 ++cur_src;
    321                 wremain = woff_src - woff_dst;
    322                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    323                                                 SHR_BITWID - wremain,
    324                                                 *cur_src,
    325                                                 0,
    326                                                 wremain);
    327             }
    328             range -= wremain;
    329             wremain = SHR_BITWID - wremain;
    330             if (woff_dst >= woff_src) {
    331                 ++cur_src;
    332                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    333                                                 SHR_BITWID - wremain,
    334                                                 *cur_src,
    335                                                 0,
    336                                                 wremain);
    337             } else {
    338                 ++cur_dst;
    339                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    340                                                 0,
    341                                                 *cur_src,
    342                                                 SHR_BITWID - wremain,
    343                                                 wremain);
    344             }
    345             range -= wremain;
    346         }
    347 
    348         if (woff_dst >= woff_src) {
    349             ++cur_dst;
    350             wremain = woff_dst - woff_src;
    351             if (range <= wremain) {
    352                 if(range > 0) {
    353                     shr_bitop_range_copy_one_bitdcl(cur_dst,
    354                                                     0,
    355                                                     *cur_src,
    356                                                     SHR_BITWID - wremain,
    357                                                     range);
    358                 }
    359                 return;
    360             }
    361             if(wremain > 0) {
    362                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    363                                                 0,
    364                                                 *cur_src,
    365                                                 SHR_BITWID - wremain,
    366                                                 wremain);
    367             }
    368         } else {
    369             ++cur_src;
    370             wremain = woff_src - woff_dst;
    371             if (range <= wremain) {
    372                 if(range > 0) {
    373                     shr_bitop_range_copy_one_bitdcl(cur_dst,
    374                                                     SHR_BITWID - wremain,
    375                                                     *cur_src,
    376                                                     0,
    377                                                     range);
    378                 }
    379                 return;
    380             }
    381             shr_bitop_range_copy_one_bitdcl(cur_dst,
    382                                             SHR_BITWID - wremain,
    383                                             *cur_src,
    384                                             0,
    385                                             wremain);
    386         }
    387         range -= wremain;
    388 
    389         if(range > 0) {
    390             wremain = SHR_BITWID - wremain;
    391             if (woff_dst >= woff_src) {
    392                 ++cur_src;
    393                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    394                                                 SHR_BITWID - wremain,
    395                                                 *cur_src,
    396                                                 0,
    397                                                 range);
    398             } else {
    399                 ++cur_dst;
    400                 shr_bitop_range_copy_one_bitdcl(cur_dst,
    401                                                 0,
    402                                                 *cur_src,
    403                                                 SHR_BITWID - wremain,
    404                                                 range);
    405             }
    406         }
    407     }
    408 }
    409 
    410 /* The same as _SHR_BITOP_RANGE, but for a single SHR_BITDCL.
    411    The following constraints are kept: 
    412  * a. _first < SHR_BITWID 
    413  * b. _first + _bit_count < SHR_BITWID.
    414  */
    415 #define _SHR_BITOP_RANGE_ONE_BITDCL(_bits1,     \
    416                                     _bits2,     \
    417                                     _first,     \
    418                                     _bit_count, \
    419                                     _dest,      \
    420                                     _op)        \
    421 {                                               \
    422     SHR_BITDCL _mask = ~0;                      \
    423     SHR_BITDCL _data;                           \
    424     _mask >>= (SHR_BITWID - (_bit_count));      \
    425     _mask <<=_first;                            \
    426     _data = ((_bits1) _op (_bits2)) & _mask;    \
    427     *(_dest) &= ~_mask;                         \
    428     *(_dest) |= _data;                          \
    429 }
    430 
    431 #define _SHR_BITOP_RANGE(_bits1, _bits2, _first, _bit_count, _dest, _op) \
    432 {                                               \
    433     CONST SHR_BITDCL *_ptr_bits1;               \
    434     CONST SHR_BITDCL *_ptr_bits2;               \
    435     SHR_BITDCL *_ptr_dest;                      \
    436     int _woff_first, _wremain;                  \
    437                                                 \
    438     _ptr_bits1 =                                \
    439         (_bits1) + ((_first) / SHR_BITWID);     \
    440     _ptr_bits2 =                                \
    441         (_bits2) + ((_first) / SHR_BITWID);     \
    442     _ptr_dest =                                 \
    443         (_dest) + ((_first) / SHR_BITWID);      \
    444     _woff_first = ((_first) % SHR_BITWID);      \
    445                                                 \
    446     _wremain = SHR_BITWID - _woff_first;        \
    447     if ((_bit_count) <= _wremain) {             \
    448         _SHR_BITOP_RANGE_ONE_BITDCL(*_ptr_bits1,\
    449             *_ptr_bits2,                        \
    450             _woff_first,                        \
    451             (_bit_count),                       \
    452             _ptr_dest, _op);                    \
    453         return;                                 \
    454     }                                           \
    455     _SHR_BITOP_RANGE_ONE_BITDCL(*_ptr_bits1,    \
    456         *_ptr_bits2, _woff_first, _wremain,     \
    457         _ptr_dest, _op);                        \
    458         (_bit_count) -= _wremain;               \
    459         ++_ptr_bits1; ++_ptr_bits2; ++_ptr_dest;\
    460     while ((_bit_count) >= SHR_BITWID) {        \
    461         *_ptr_dest =                            \
    462             (*_ptr_bits1) _op (*_ptr_bits2);    \
    463         (_bit_count) -= SHR_BITWID;             \
    464         ++_ptr_bits1; ++_ptr_bits2; ++_ptr_dest;\
    465     }                                           \
    466     if((_bit_count) > 0) {                      \
    467         _SHR_BITOP_RANGE_ONE_BITDCL(            \
    468             *_ptr_bits1,                        \
    469             *_ptr_bits2,                        \
    470             0,                                  \
    471             (_bit_count),                       \
    472             _ptr_dest,                          \
    473             _op);                               \
    474     }                                           \
    475 }
    476 
    477 void
    478 shr_bitop_range_and(CONST SHR_BITDCL *bits1,
    479                     CONST SHR_BITDCL *bits2,
    480                     CONST int first,
    481                     int bit_count,
    482                     SHR_BITDCL *dest)
    483 {
    484     if(bit_count > 0) {
    485         _SHR_BITOP_RANGE(bits1, bits2, first, bit_count, dest, &);
    486     }
    487 }
    488 
    489 void
    490 shr_bitop_range_or(CONST SHR_BITDCL *bits1,
    491                    CONST SHR_BITDCL *bits2,
    492                    CONST int first,
    493                    int bit_count,
    494                    SHR_BITDCL *dest)
    495 {
    496     if(bit_count > 0) {
    497         _SHR_BITOP_RANGE(bits1, bits2, first, bit_count, dest, |);
    498     }
    499 }
    500 
    501 void
    502 shr_bitop_range_xor(CONST SHR_BITDCL *bits1,
    503                     CONST SHR_BITDCL *bits2,
    504                     CONST int first,
    505                     int bit_count,
    506                     SHR_BITDCL *dest)
    507 {
    508     if(bit_count > 0) {
    509         _SHR_BITOP_RANGE(bits1, bits2, first, bit_count, dest, ^);
    510     }
    511 }
    512 
    513 void
    514 shr_bitop_range_remove(CONST SHR_BITDCL *bits1,
    515                        CONST SHR_BITDCL *bits2,
    516                        CONST int first,
    517                        int bit_count,
    518                        SHR_BITDCL *dest)
    519 {
    520     if(bit_count > 0) {
    521         _SHR_BITOP_RANGE(bits1, bits2, first, bit_count, dest, & ~);
    522     }
    523 }
    524 
    525 /* The same as _SHR_BITNEGATE_RANGE, but for a single SHR_BITDCL.
    526    The following constraints are kept:
    527  * a. _first < SHR_BITWID 
    528  * b. _first + _bit_count < SHR_BITWID.
    529  */
    530 #define _SHR_BITNEGATE_RANGE_ONE_BITDCL(_bits1, _first, _bit_count, _dest) \
    531 {                                               \
    532     SHR_BITDCL _mask = ~0;                      \
    533     SHR_BITDCL _data;                           \
    534     _mask >>= (SHR_BITWID - (_bit_count));      \
    535     _mask <<=_first;                            \
    536     _data =  ~(_bits1) & _mask;                 \
    537     *(_dest) &= ~_mask;                         \
    538     *(_dest) |= _data;                          \
    539 }
    540 
    541 #define _SHR_BITNEGATE_RANGE(_bits1, _first, _bit_count, _dest) \
    542 {                                               \
    543     CONST SHR_BITDCL *_ptr_bits1;               \
    544     SHR_BITDCL *_ptr_dest;                      \
    545     int _woff_first, _wremain;                  \
    546                                                 \
    547     _ptr_bits1 =                                \
    548         (_bits1) + ((_first) / SHR_BITWID);     \
    549     _ptr_dest =                                 \
    550         (_dest) + ((_first) / SHR_BITWID);      \
    551     _woff_first = ((_first) % SHR_BITWID);      \
    552                                                 \
    553     _wremain = SHR_BITWID - _woff_first;        \
    554     if ((_bit_count) <= _wremain) {             \
    555         _SHR_BITNEGATE_RANGE_ONE_BITDCL(        \
    556             *_ptr_bits1,                        \
    557             _woff_first,                        \
    558             (_bit_count),                       \
    559             _ptr_dest);                         \
    560         return;                                 \
    561     }                                           \
    562     _SHR_BITNEGATE_RANGE_ONE_BITDCL(*_ptr_bits1,\
    563         _woff_first, _wremain, _ptr_dest);      \
    564         (_bit_count) -= _wremain;               \
    565         ++_ptr_bits1; ++_ptr_dest;              \
    566     while ((_bit_count) >= SHR_BITWID) {        \
    567         *_ptr_dest = ~(*_ptr_bits1);            \
    568         (_bit_count) -= SHR_BITWID;             \
    569         ++_ptr_bits1; ++_ptr_dest;              \
    570     }                                           \
    571     if((_bit_count) > 0) {                      \
    572         _SHR_BITNEGATE_RANGE_ONE_BITDCL(        \
    573             *_ptr_bits1,                        \
    574             0,                                  \
    575             (_bit_count),                       \
    576             _ptr_dest);                         \
    577     }                                           \
    578 }
    579 
    580 void
    581 shr_bitop_range_negate(CONST SHR_BITDCL *bits1,
    582                        CONST int first,
    583                        int bit_count,
    584                        SHR_BITDCL *dest)
    585 {
    586     if(bit_count > 0) {
    587         _SHR_BITNEGATE_RANGE(bits1, first, bit_count, dest);
    588     }
    589 }
    590 
    591 /* The same as shr_bitop_range_clear, but for a single SHR_BITDCL.
    592    The following constraints are kept:
    593  * a. b < SHR_BITWID 
    594  * b. b + c < SHR_BITWID.
    595  */
    596 STATIC INLINE void
    597 shr_bitop_range_clear_one_bitdcl(SHR_BITDCL *a, CONST int b, CONST int c)
    598 {
    599     SHR_BITDCL mask = ~0;
    600     mask >>= (SHR_BITWID - c);
    601     mask <<= b;
    602     *a &= ~mask;
    603 }
    604 
    605 void
    606 shr_bitop_range_clear(SHR_BITDCL *a, CONST int b, int c)
    607 {
    608     SHR_BITDCL *ptr;
    609     int woff_first, wremain;
    610 
    611     if(c <= 0) {
    612         return;
    613     }
    614 
    615     ptr = a + (b / SHR_BITWID);
    616     
    617     woff_first = b % SHR_BITWID;
    618     
    619     if (woff_first != 0) {
    620         wremain = SHR_BITWID - woff_first;
    621         if (c <= wremain) {
    622             shr_bitop_range_clear_one_bitdcl(ptr, woff_first, c);
    623             return;
    624         }
    625         shr_bitop_range_clear_one_bitdcl(ptr, woff_first, wremain);
    626         c -= wremain;
    627         ++ptr;
    628     }
    629     while (c >= SHR_BITWID) {
    630         *(ptr++) = 0;
    631         c -= SHR_BITWID;
    632     }
    633 
    634     if(c > 0) {
    635         shr_bitop_range_clear_one_bitdcl(ptr, 0, c);
    636     }
    637 }
    638 
    639 /* The same as shr_bitop_range_set, but for a single SHR_BITDCL.
    640    The following constraints are kept:
    641  * a. b < SHR_BITWID 
    642  * b. b + c < SHR_BITWID.
    643  */
    644 STATIC INLINE void
    645 shr_bitop_range_set_one_bitdcl(SHR_BITDCL *a, CONST int b, CONST int c)
    646 {
    647     SHR_BITDCL mask = ~0;
    648     mask >>= (SHR_BITWID - c);
    649     mask <<= b;
    650     *a |= mask;
    651 }
    652 
    653 void
    654 shr_bitop_range_set(SHR_BITDCL *a, CONST int b, int c)
    655 {
    656     SHR_BITDCL *ptr;
    657     int woff_first, wremain;
    658 
    659     if(c <= 0) {
    660         return;
    661     }
    662 
    663     ptr = a + (b / SHR_BITWID);
    664     
    665     woff_first = b % SHR_BITWID;
    666     
    667     if (woff_first != 0) {
    668         wremain = SHR_BITWID - woff_first;
    669         if (c <= wremain) {
    670             shr_bitop_range_set_one_bitdcl(ptr, woff_first, c);
    671             return;
    672         }
    673         shr_bitop_range_set_one_bitdcl(ptr, woff_first, wremain);
    674         c -= wremain;
    675         ++ptr;
    676     }
    677     while (c >= SHR_BITWID) {
    678         *(ptr++) = ~0;
    679         c -= SHR_BITWID;
    680     }
    681     if(c > 0) {
    682         shr_bitop_range_set_one_bitdcl(ptr, 0, c);
    683     }
    684 }
    685 
    686 /* 
    687  * Function: shr_bitop_str_decode 
    688  *  
    689  * decode a string in hex format into a bitmap
    690  * returns 0 on success, -1 on error 
    691  *  
    692  * The string can be more than 32 bits worth of
    693  * data if it is in hex format (0x...).  If not
    694  * hex, it is treated as a single value and not 
    695  * as a bit map, meaning only a single bit will 
    696  * be set. 
    697  */
    698 
    699 int
    700 shr_bitop_str_decode(char *str_value, 
    701                      SHR_BITDCL *dst_ptr,
    702                      int max_words)
    703 {
    704     char    *e;
    705     uint32  v;
    706     int     bit;
    707 
    708     shr_bitop_range_clear(dst_ptr, 0,  SHR_BITWID * max_words);
    709 
    710     if (str_value[0] == '0' && (str_value[1] == 'x' || str_value[1] == 'X')) 
    711     {
    712         /* get end of string */
    713         str_value += 2;
    714         for (e = str_value; *e; e++) ;
    715 
    716         e -= 1;
    717         /* back up to beginning of string, setting ports as we go */
    718         bit = 0;
    719         while (e >= str_value) 
    720         {
    721             if (*e >= '0' && *e <= '9') {
    722                 v = *e - '0';
    723             } else if (*e >= 'a' && *e <= 'f') {
    724                 v = *e - 'a' + 10;
    725             } else if (*e >= 'A' && *e <= 'F') {
    726                 v = *e - 'A' + 10;
    727             } else {
    728                 /* error: invalid hex digits */
    729                 return -1;
    730             }
    731             e -= 1;
    732             /* now set a nibble's worth of ports */
    733             if ((v & 1) && bit < SHR_BITWID * max_words) {
    734                 SHR_BITSET(dst_ptr, bit);
    735             }
    736             bit += 1;
    737             if ((v & 2) && bit < SHR_BITWID * max_words) {
    738                 SHR_BITSET(dst_ptr, bit);
    739             }
    740             bit += 1;
    741             if ((v & 4) && bit < SHR_BITWID * max_words) {
    742                 SHR_BITSET(dst_ptr, bit);
    743             }
    744             bit += 1;
    745             if ((v & 8) && bit < SHR_BITWID * max_words) {
    746                 SHR_BITSET(dst_ptr, bit);
    747             }
    748             bit += 1;
    749         }
    750     } 
    751     else 
    752     {
    753         v = 0;
    754         /* get decimal nuber */
    755         while (*str_value >= '0' && *str_value <= '9') 
    756         {
    757             v = v * 10 + (*str_value++ - '0');
    758         }
    759 
    760         if (*str_value != '\0') 
    761         {
    762             /* error: invalid decimal digits */
    763             return -1;
    764         }
    765 
    766         /* set only recieved decimal value */
    767         if (v < SHR_BITWID * max_words) 
    768         {
    769             SHR_BITSET(dst_ptr, v); 
    770         }
    771     }
    772     return 0;
    773 }
    774 
    775 void
    776 shr_bitop_str_encode(SHR_BITDCL *source_bitmap,
    777                      int bit_count,
    778                      char *destination_str,
    779                      int destination_str_max_length)
    780 {
    781     char local_buffer[20];
    782     int bitmap_words = (bit_count / SHR_BITWID) + (bit_count % SHR_BITWID == 0 ? 0 : 1);
    783     int word;
    784 
    785     /** if the bitmap needed words is 0, set it to contain at least one word to print 0 properly without infinite loops */
    786     if(bitmap_words == 0)
    787     {
    788         bitmap_words = 1;
    789     }
    790 
    791     /* clear str */
    792     *destination_str = '\0';
    793 
    794     /* if bitmap can fit in str*/
    795     if(bitmap_words * SHR_BITWORD_HEX_STR_CHARS + 1 < destination_str_max_length)
    796     {
    797         /* populate str */
    798         sal_snprintf(local_buffer, sizeof(local_buffer) -1, "0x");
    799         sal_strncat(destination_str, local_buffer, sizeof(local_buffer) -1);
    800 
    801         for(word = 0; word < bitmap_words; ++word)
    802         {
    803             sal_snprintf(local_buffer, sizeof(local_buffer) -1, "%08x", source_bitmap[word]);
    804             sal_strncat(destination_str, local_buffer, sizeof(local_buffer) -1);
    805         }
    806     }
    807 }