blob: 69f7145bc50c6d9565b9a82386d52f8e49f848f7 [file] [log] [blame]
#ifndef DRBD_ENDIAN_H
#define DRBD_ENDIAN_H 1
/*
* we don't want additional dependencies on other packages,
* and we want to avoid to introduce incompatibilities by including kernel
* headers from user space.
*
* we need the uint32_t and uint64_t types,
* the hamming weight functions,
* and the cpu_to_le etc. endianness convert functions.
*/
#include <stdint.h>
#include <endian.h>
#ifndef BITS_PER_LONG
# if defined(__SIZEOF_LONG__)
# define BITS_PER_LONG (__SIZEOF_LONG__ * 8)
# elif defined(__WORDSIZE)
# define BITS_PER_LONG __WORDSIZE
# else /* wtf is wrong with your libc headers? */
# error "neither BITS_PER_LONG, __SIZEOF_LONG__, nor __WORDSIZE defined"
# endif
#endif
/* linux/byteorder/swab.h */
/* casts are necessary for constants, because we never know for sure
* how U/UL/ULL map to __u16, uint32_t, uint64_t. At least not in a portable way.
*/
/*
* __asm__("bswap %0" : "=r" (x) : "0" (x));
* oh, well...
*/
#define __swab16(x) \
({ \
__u16 __x = (x); \
((__u16)( \
(((__u16)(__x) & (__u16)0x00ffUL) << 8) | \
(((__u16)(__x) & (__u16)0xff00UL) >> 8) )); \
})
#define __swab32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define __swab64(x) \
({ \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
/*
* linux/byteorder/little_endian.h
* linux/byteorder/big_endian.h
*/
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define cpu_to_le64(x) ((uint64_t)(x))
#define le64_to_cpu(x) ((uint64_t)(x))
#define cpu_to_le32(x) ((uint32_t)(x))
#define le32_to_cpu(x) ((uint32_t)(x))
#define cpu_to_le16(x) ((__u16)(x))
#define le16_to_cpu(x) ((__u16)(x))
#define cpu_to_be64(x) __swab64((x))
#define be64_to_cpu(x) __swab64((x))
#define cpu_to_be32(x) __swab32((x))
#define be32_to_cpu(x) __swab32((x))
#define cpu_to_be16(x) __swab16((x))
#define be16_to_cpu(x) __swab16((x))
#elif __BYTE_ORDER == __BIG_ENDIAN
# define cpu_to_le64(x) __swab64((x))
# define le64_to_cpu(x) __swab64((x))
# define cpu_to_le32(x) __swab32((x))
# define le32_to_cpu(x) __swab32((x))
# define cpu_to_le16(x) __swab16((x))
# define le16_to_cpu(x) __swab16((x))
# define cpu_to_be64(x) ((uint64_t)(x))
# define be64_to_cpu(x) ((uint64_t)(x))
# define cpu_to_be32(x) ((uint32_t)(x))
# define be32_to_cpu(x) ((uint32_t)(x))
# define cpu_to_be16(x) ((__u16)(x))
# define be16_to_cpu(x) ((__u16)(x))
#else
# error "sorry, weird endianness on this box"
#endif
/* linux/bitops.h */
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
static inline unsigned int generic_hweight32(unsigned int w)
{
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
}
static inline unsigned long generic_hweight64(uint64_t w)
{
#if BITS_PER_LONG < 64
return generic_hweight32((unsigned int)(w >> 32)) +
generic_hweight32((unsigned int)w);
#else
uint64_t res;
res = (w & 0x5555555555555555) + ((w >> 1) & 0x5555555555555555);
res = (res & 0x3333333333333333) + ((res >> 2) & 0x3333333333333333);
res = (res & 0x0F0F0F0F0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F0F0F0F0F);
res = (res & 0x00FF00FF00FF00FF) + ((res >> 8) & 0x00FF00FF00FF00FF);
res = (res & 0x0000FFFF0000FFFF) + ((res >> 16) & 0x0000FFFF0000FFFF);
return (res & 0x00000000FFFFFFFF) + ((res >> 32) & 0x00000000FFFFFFFF);
#endif
}
static inline unsigned long hweight_long(unsigned long w)
{
return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
}
/*
* Format macros for printf()
*/
#if BITS_PER_LONG == 32
# define X32(a) "%"#a"X"
# define X64(a) "%"#a"llX"
# define D32 "%d"
# define D64 "%lld"
# define U32 "%u"
# define U64 "%llu"
#elif BITS_PER_LONG == 64
# define X32(a) "%"#a"X"
# define X64(a) "%"#a"lX"
# define D32 "%d"
# define D64 "%ld"
# define U32 "%u"
# define U64 "%lu"
#else
# error "sorry, unsupported word length on this box"
#endif
#if BITS_PER_LONG == 32
# define strto_u64 strtoull
#elif BITS_PER_LONG == 64
# define strto_u64 strtoul
#else
# error "sorry, unsupported word length on this box"
#endif
#endif