blob: 9971292260ce46d52b46f038633b1b841c867279 [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
/**
* bcmolt_bit_utils.h
* Created on: 03/10/2014
* Author: cpark1
*
* This bit vector implementation is used for the EPON encryption.
* There is a certain hardware restriction that the global encryption mode
* can not be changed when a link encryption is configured for a different
* encryption mode.
* Likewise, the link encryption mode can not be changed if the global
* encryption mode is set to other mode.
* Therefore, when the host tries to change any of them, the OLT needs to
* check either the global encryption mode or the link encryption mode
* before applying the change.
* In the old implementation (like Pioneer), the firmware iterates through
* every link records of each PON port and check the encryption mode of each.
* This is very inefficient and time consuming.
* The host may want to know how many links are enabled for the encryption,
* or which link is enabled, etc.
* I thought that a bit vector implementation is best satisfies.
* Also, this implementation exactly reflects the IC implementation, so we
* can use it to mirror the hardware status.
*
*/
#ifndef BCMOLT_BIT_UTILS_H
#define BCMOLT_BIT_UTILS_H
#include "bcmos_system.h"
/* the current (draft) design of the ASIC uses 32-bit bitmap data port */
typedef uint32_t bv_bits;
typedef struct
{
uint32_t nbits;
bv_bits *vector;
} bit_vector;
#define BITS_SZ (sizeof(bv_bits) * CHAR_BIT)
#define BITS_SET(val, mask) (((val) & (mask)) == (mask))
/** Test if all given bits are set in the given data word
* \param[in] word Given data word to test
* \param[in] mask Test mask
* \return TRUE if all the bits in the bitMask are set
*/
static inline bcmos_bool test_bits_set(uint32_t word, uint32_t mask)
{
return ((word & mask) == mask);
}
/** Test if all given bits are clear in the given data word
* \param word Given word to test
* \param mask Test mask
* \return TRUE if all the bits given by bitMask are clear
*/
static inline bcmos_bool test_bits_clear(uint32_t word, uint32_t mask)
{
return (word & mask) == 0;
}
/** Test whether any of the given bits are set in a value
* \param[in] val The value to test
* \param[in] bits The bits to test for
* \return TRUE if any of the bits are set in the value, FALSE otherwise
*/
static inline bcmos_bool test_bits_any(uint32_t val, uint32_t bits)
{
return (val & bits) != 0;
}
/** return true if only one bit is set for a given integer.
*/
static inline bcmos_bool is_one_bit_set(uint32_t number)
{
return (number & (number - 1)) == 0;
}
/** dynamically allocate space for an array of `nbits' bits and initalize
* the bits to all be zero.
*
* \param[out] bv pointer to a bit_vector struct.
* \param[in] nbits number of bits to allocate.
* \return FALSE if space was not available, otherwise TRUE.
*/
bcmos_bool bcmolt_bv_new(bit_vector *bv, const uint32_t nbits);
/** return the value of the `offset'th bit element of the bit vector.
*
* \param[in] bv pointer to a bit_vector struct.
* \param[in] offset offset of bit to test.
* \return FALSE if the bit offset is out of range, otherwise TRUE.
*/
bcmos_bool bcmolt_bv_get(const bit_vector *bv, const uint32_t offset);
/** set or clear the bit in position `offset' of the bit vector.
* bv->vector[bit_pos] is to be set (assigned to 1) if value is TRUE,
* otherwise it is to be cleared (assigned to 0).
*
* \param[in] bv pointer to a bit_vector struct.
* \param[in] offset offset of bit to set or clear.
* \param[in] value boolean value. TRUE for set, FALSE for clear.
* \return FALSE if the bit offset is out of range, otherwise TRUE.
*/
void bcmolt_bv_assign(bit_vector *bv, const uint32_t offset, const bcmos_bool value);
/** set or clear 'nbits' bits of given bit vector.
*
* \param[in] bv pointer to a bit_vector struct.
* \param[in] nbits number of bits to set or clear.
* \param[in] value boolean value. TRUE for set, FALSE for clear.
* \return FALSE if the bit offset is out of range, otherwise TRUE.
*/
void bv_assign_nbits(bit_vector *bv, const uint32_t nbits,
const bcmos_bool value);
/** toggle the bit in position `offset' of the bit vector.
* i.e. if it was 1 it is 0; if it was 0 it is 1.
*
* \param[in] bv pointer to a bit_vector struct.
* \param[in] offset offset of bit to toggle.
* \return FALSE if the bit offset is out of range, otherwise TRUE.
*/
void bcmolt_bv_toggle(bit_vector *bv, const uint32_t offset);
/** copy bit vector from 'src' to 'dst'.
*
* \param[out] dst pointer to a bit_vector struct to copy to.
* \param[in] src pointer to a bit_vector struct to copy from.
* \param[in] nbits number of bits to copy.
* \return none.
*/
void bcmolt_bv_copy(bit_vector *dst, const bit_vector *src, const uint32_t nbits);
/** Print bit pattern of word FORMATTED to string.
*
* \param[in] value value to transform to bit string.
* \param[in] bitcnt count of bits to be shown.
* \param[out] outstr pointer to a output buffer to store the string.
* \return none
* \warning this fn doesn't check the size of 'outstr'.
* the caller should ensure 'outstr' has enough room for the
* bit string, space characters and null terminator.
*/
void bcmolt_bit_string(const bv_bits value, const uint32_t bitcnt, char *outstr);
/** Print all bits in the bit vector.
*
* \param[in] bv pointer to a bit_vector struct.
* \return none.
*/
void bcmolt_bv_dump(const bit_vector *bv);
/** Count the number of bits set in a long integer.
*
* \param[in] num integer value.
* \return number of bits set.
*/
uint32_t bcmolt_bit_count(uint32_t num);
/** Count the number of bits set in the whole bit vector.
*
* \param[in] bv pointer to the bit vector struct.
* \return number of bits set.
*/
uint32_t bcmolt_bv_bit_count(const bit_vector *bv);
/** Copy bit range from a 32-bit word array to an arbitrary bit position of
* the destination 32-bit word array.
*
* \param[in] dst destination buffer
* \param[in] dst_bytes destination buffer size in bytes
* \param[in] dst_bit_pos least bit position to dest
* \param[in] src source buffer
* \param[in] src_bits many bits to copy from source
* \note src is in little endian and dst is in big endian.
*/
void bcmos_bit_range_set(uint32_t *dst, uint32_t dst_bytes, uint16_t dst_bit_pos,
uint32_t *src, uint16_t n_bits);
/** Get bit range at an arbitrary bit position of a 32-bit word array
*
* \param[in] src source buffer (e.g. dataport)
* \param[in] src_bytes source buffer size in bytes
* \param[in] src_bit_pos least bit position of the source
* \param[in] dst destination buffer to store the bit value
* \param[in] n_bits how many bits to copy from srouce
* \note src is in big endian and dst is in little endian.
*/
void bcmos_bit_range_get(const uint32_t *src, uint32_t src_bytes,
uint16_t src_bit_pos, uint32_t *dst, uint16_t n_bits);
#endif /* BCMOLT_BIT_UTILS_H */