1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020, The University of Queensland 14 */ 15 16 #ifndef _MLXCX_ENDINT_H 17 #define _MLXCX_ENDINT_H 18 19 #include <sys/types.h> 20 #include <sys/byteorder.h> 21 22 /* 23 * The inlines and structs in this file are used by mlxcx to ensure endian 24 * safety when dealing with memory-mapped structures from the device, and 25 * also simpler use of 24-bit integers (which Mellanox loves). 26 * 27 * By declaring all of these values in the memory-mapped structures as structs 28 * (e.g. uint32be_t) rather than bare integers (uint32_t) we ensure that the 29 * compiler will not allow them to be silently converted to integers and used 30 * without doing the necessary byte-swapping work. 31 * 32 * The uintXbe_t structs are designed to be used inside a #pragma pack(1) 33 * context only and we don't try to fix up their alignment. 34 * 35 * Also present in here are a number of bitsX_t types which can be used to 36 * gain a little bit of type safety when dealing with endian-swapped bitfields. 37 */ 38 39 #pragma pack(1) 40 typedef struct { uint16_t be_val; } uint16be_t; 41 typedef struct { uint8_t be_val[3]; } uint24be_t; 42 typedef struct { uint32_t be_val; } uint32be_t; 43 typedef struct { uint64_t be_val; } uint64be_t; 44 #pragma pack() 45 46 static inline uint16_t 47 from_be16(uint16be_t v) 48 { 49 return (BE_16(v.be_val)); 50 } 51 52 static inline uint32_t 53 from_be24(uint24be_t v) 54 { 55 return (((uint32_t)v.be_val[0] << 16) | 56 ((uint32_t)v.be_val[1] << 8) | 57 ((uint32_t)v.be_val[2])); 58 } 59 60 static inline uint32_t 61 from_be32(uint32be_t v) 62 { 63 return (BE_32(v.be_val)); 64 } 65 66 static inline uint64_t 67 from_be64(uint64be_t v) 68 { 69 return (BE_64(v.be_val)); 70 } 71 72 static inline uint16be_t 73 to_be16(uint16_t v) 74 { 75 /* CSTYLED */ 76 return ((uint16be_t){ .be_val = BE_16(v) }); 77 } 78 79 static inline uint24be_t 80 to_be24(uint32_t v) 81 { 82 /* CSTYLED */ 83 return ((uint24be_t){ .be_val = { 84 (v & 0xFF0000) >> 16, 85 (v & 0x00FF00) >> 8, 86 (v & 0x0000FF) 87 }}); 88 } 89 90 static inline uint32be_t 91 to_be32(uint32_t v) 92 { 93 /* CSTYLED */ 94 return ((uint32be_t){ .be_val = BE_32(v) }); 95 } 96 97 static inline uint64be_t 98 to_be64(uint64_t v) 99 { 100 /* CSTYLED */ 101 return ((uint64be_t){ .be_val = BE_64(v) }); 102 } 103 104 #pragma pack(1) 105 typedef struct { uint8_t bit_val; } bits8_t; 106 typedef struct { uint16_t bit_val; } bits16_t; 107 typedef struct { uint32_t bit_val; } bits32_t; 108 typedef struct { uint24be_t bit_val; } bits24_t; 109 typedef struct { uint64_t bit_val; } bits64_t; 110 typedef struct { uint64_t bit_shift; uint64_t bit_mask; } bitdef_t; 111 #pragma pack() 112 113 static inline uint8_t 114 get_bits8(bits8_t v, bitdef_t d) 115 { 116 return ((v.bit_val & d.bit_mask) >> d.bit_shift); 117 } 118 static inline void 119 set_bits8(bits8_t *v, bitdef_t d, uint8_t val) 120 { 121 v->bit_val &= ~d.bit_mask; 122 v->bit_val |= (val << d.bit_shift) & d.bit_mask; 123 } 124 static inline uint8_t 125 get_bit8(bits8_t v, uint8_t mask) 126 { 127 return ((v.bit_val & mask) != 0); 128 } 129 static inline void 130 set_bit8(bits8_t *v, uint8_t mask) 131 { 132 v->bit_val |= mask; 133 } 134 static inline void 135 clear_bit8(bits8_t *v, uint8_t mask) 136 { 137 v->bit_val &= ~mask; 138 } 139 static inline bits8_t 140 new_bits8(void) 141 { 142 /* CSTYLED */ 143 return ((bits8_t){ .bit_val = 0 }); 144 } 145 static inline uint8_t 146 from_bits8(bits8_t v) 147 { 148 return (v.bit_val); 149 } 150 151 static inline uint16_t 152 get_bits16(bits16_t v, bitdef_t d) 153 { 154 return ((BE_16(v.bit_val) & d.bit_mask) >> d.bit_shift); 155 } 156 static inline void 157 set_bits16(bits16_t *v, bitdef_t d, uint16_t val) 158 { 159 v->bit_val &= BE_16(~d.bit_mask); 160 v->bit_val |= BE_16((val << d.bit_shift) & d.bit_mask); 161 } 162 static inline uint16_t 163 get_bit16(bits16_t v, uint16_t mask) 164 { 165 return ((BE_16(v.bit_val) & mask) != 0); 166 } 167 static inline void 168 set_bit16(bits16_t *v, uint16_t mask) 169 { 170 v->bit_val |= BE_16(mask); 171 } 172 static inline void 173 clear_bit16(bits16_t *v, uint16_t mask) 174 { 175 v->bit_val &= BE_16(~mask); 176 } 177 static inline bits16_t 178 new_bits16(void) 179 { 180 /* CSTYLED */ 181 return ((bits16_t){ .bit_val = 0 }); 182 } 183 static inline uint16_t 184 from_bits16(bits16_t v) 185 { 186 return (BE_16(v.bit_val)); 187 } 188 189 static inline uint32_t 190 get_bits32(bits32_t v, bitdef_t d) 191 { 192 return ((BE_32(v.bit_val) & d.bit_mask) >> d.bit_shift); 193 } 194 static inline void 195 set_bits32(bits32_t *v, bitdef_t d, uint32_t val) 196 { 197 v->bit_val &= BE_32(~d.bit_mask); 198 v->bit_val |= BE_32((val << d.bit_shift) & d.bit_mask); 199 } 200 static inline uint32_t 201 get_bit32(bits32_t v, uint32_t mask) 202 { 203 return ((BE_32(v.bit_val) & mask) != 0); 204 } 205 static inline void 206 set_bit32(bits32_t *v, uint32_t mask) 207 { 208 v->bit_val |= BE_32(mask); 209 } 210 static inline void 211 clear_bit32(bits32_t *v, uint32_t mask) 212 { 213 v->bit_val &= BE_32(~mask); 214 } 215 static inline bits32_t 216 new_bits32(void) 217 { 218 /* CSTYLED */ 219 return ((bits32_t){ .bit_val = 0 }); 220 } 221 static inline uint32_t 222 from_bits32(bits32_t v) 223 { 224 return (BE_32(v.bit_val)); 225 } 226 227 static inline uint32_t 228 get_bits24(bits24_t v, bitdef_t d) 229 { 230 return ((from_be24(v.bit_val) & d.bit_mask) >> d.bit_shift); 231 } 232 static inline void 233 set_bits24(bits24_t *v, bitdef_t d, uint32_t val) 234 { 235 uint32_t vv = from_be24(v->bit_val); 236 vv &= ~d.bit_mask; 237 vv |= (val << d.bit_shift) & d.bit_mask; 238 v->bit_val = to_be24(vv); 239 } 240 static inline uint32_t 241 get_bit24(bits24_t v, uint32_t mask) 242 { 243 return ((from_be24(v.bit_val) & mask) != 0); 244 } 245 static inline void 246 set_bit24(bits24_t *v, uint32_t mask) 247 { 248 v->bit_val = to_be24(from_be24(v->bit_val) | mask); 249 } 250 static inline void 251 clear_bit24(bits24_t *v, uint32_t mask) 252 { 253 v->bit_val = to_be24(from_be24(v->bit_val) & ~mask); 254 } 255 static inline bits24_t 256 new_bits24(void) 257 { 258 /* CSTYLED */ 259 return ((bits24_t){ .bit_val = to_be24(0) }); 260 } 261 static inline uint32_t 262 from_bits24(bits24_t v) 263 { 264 return (from_be24(v.bit_val)); 265 } 266 267 static inline uint64_t 268 get_bits64(bits64_t v, bitdef_t d) 269 { 270 return ((BE_64(v.bit_val) & d.bit_mask) >> d.bit_shift); 271 } 272 static inline void 273 set_bits64(bits64_t *v, bitdef_t d, uint64_t val) 274 { 275 v->bit_val &= BE_64(~d.bit_mask); 276 v->bit_val |= BE_64((val << d.bit_shift) & d.bit_mask); 277 } 278 static inline uint64_t 279 get_bit64(bits64_t v, uint64_t mask) 280 { 281 return ((BE_64(v.bit_val) & mask) != 0); 282 } 283 static inline void 284 set_bit64(bits64_t *v, uint64_t mask) 285 { 286 v->bit_val |= BE_64(mask); 287 } 288 static inline void 289 clear_bit64(bits64_t *v, uint64_t mask) 290 { 291 v->bit_val &= BE_64(~mask); 292 } 293 static inline bits64_t 294 new_bits64(void) 295 { 296 /* CSTYLED */ 297 return ((bits64_t){ .bit_val = 0 }); 298 } 299 static inline uint64_t 300 from_bits64(bits64_t v) 301 { 302 return (BE_64(v.bit_val)); 303 } 304 305 #endif /* _MLXCX_ENDINT_H */ 306