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 typedef struct { uint16_t be_val; } __packed uint16be_t; 40 typedef struct { uint8_t be_val[3]; } __packed uint24be_t; 41 typedef struct { uint32_t be_val; } __packed uint32be_t; 42 typedef struct { uint64_t be_val; } __packed uint64be_t; 43 44 static inline uint16_t 45 from_be16(uint16be_t v) 46 { 47 return (BE_16(v.be_val)); 48 } 49 50 static inline uint32_t 51 from_be24(uint24be_t v) 52 { 53 return (((uint32_t)v.be_val[0] << 16) | 54 ((uint32_t)v.be_val[1] << 8) | 55 ((uint32_t)v.be_val[2])); 56 } 57 58 static inline uint32_t 59 from_be32(uint32be_t v) 60 { 61 return (BE_32(v.be_val)); 62 } 63 64 static inline uint64_t 65 from_be64(uint64be_t v) 66 { 67 return (BE_64(v.be_val)); 68 } 69 70 static inline uint16be_t 71 to_be16(uint16_t v) 72 { 73 /* CSTYLED */ 74 return ((uint16be_t){ .be_val = BE_16(v) }); 75 } 76 77 static inline uint24be_t 78 to_be24(uint32_t v) 79 { 80 /* CSTYLED */ 81 return ((uint24be_t){ .be_val = { 82 (v & 0xFF0000) >> 16, 83 (v & 0x00FF00) >> 8, 84 (v & 0x0000FF) 85 }}); 86 } 87 88 static inline uint32be_t 89 to_be32(uint32_t v) 90 { 91 /* CSTYLED */ 92 return ((uint32be_t){ .be_val = BE_32(v) }); 93 } 94 95 static inline uint64be_t 96 to_be64(uint64_t v) 97 { 98 /* CSTYLED */ 99 return ((uint64be_t){ .be_val = BE_64(v) }); 100 } 101 102 #pragma pack(1) 103 typedef struct { uint8_t bit_val; } bits8_t; 104 typedef struct { uint16_t bit_val; } bits16_t; 105 typedef struct { uint32_t bit_val; } bits32_t; 106 typedef struct { uint24be_t bit_val; } bits24_t; 107 typedef struct { uint64_t bit_val; } bits64_t; 108 typedef struct { uint64_t bit_shift; uint64_t bit_mask; } bitdef_t; 109 #pragma pack() 110 111 static inline uint8_t 112 get_bits8(bits8_t v, bitdef_t d) 113 { 114 return ((v.bit_val & d.bit_mask) >> d.bit_shift); 115 } 116 static inline void 117 set_bits8(bits8_t *v, bitdef_t d, uint8_t val) 118 { 119 v->bit_val &= ~d.bit_mask; 120 v->bit_val |= (val << d.bit_shift) & d.bit_mask; 121 } 122 static inline uint8_t 123 get_bit8(bits8_t v, uint8_t mask) 124 { 125 return ((v.bit_val & mask) != 0); 126 } 127 static inline void 128 set_bit8(bits8_t *v, uint8_t mask) 129 { 130 v->bit_val |= mask; 131 } 132 static inline void 133 clear_bit8(bits8_t *v, uint8_t mask) 134 { 135 v->bit_val &= ~mask; 136 } 137 static inline bits8_t 138 new_bits8(void) 139 { 140 /* CSTYLED */ 141 return ((bits8_t){ .bit_val = 0 }); 142 } 143 static inline uint8_t 144 from_bits8(bits8_t v) 145 { 146 return (v.bit_val); 147 } 148 149 static inline uint16_t 150 get_bits16(bits16_t v, bitdef_t d) 151 { 152 return ((BE_16(v.bit_val) & d.bit_mask) >> d.bit_shift); 153 } 154 static inline void 155 set_bits16(bits16_t *v, bitdef_t d, uint16_t val) 156 { 157 v->bit_val &= BE_16(~d.bit_mask); 158 v->bit_val |= BE_16((val << d.bit_shift) & d.bit_mask); 159 } 160 static inline uint16_t 161 get_bit16(bits16_t v, uint16_t mask) 162 { 163 return ((BE_16(v.bit_val) & mask) != 0); 164 } 165 static inline void 166 set_bit16(bits16_t *v, uint16_t mask) 167 { 168 v->bit_val |= BE_16(mask); 169 } 170 static inline void 171 clear_bit16(bits16_t *v, uint16_t mask) 172 { 173 v->bit_val &= BE_16(~mask); 174 } 175 static inline bits16_t 176 new_bits16(void) 177 { 178 /* CSTYLED */ 179 return ((bits16_t){ .bit_val = 0 }); 180 } 181 static inline uint16_t 182 from_bits16(bits16_t v) 183 { 184 return (BE_16(v.bit_val)); 185 } 186 187 static inline uint32_t 188 get_bits32(bits32_t v, bitdef_t d) 189 { 190 return ((BE_32(v.bit_val) & d.bit_mask) >> d.bit_shift); 191 } 192 static inline void 193 set_bits32(bits32_t *v, bitdef_t d, uint32_t val) 194 { 195 v->bit_val &= BE_32(~d.bit_mask); 196 v->bit_val |= BE_32((val << d.bit_shift) & d.bit_mask); 197 } 198 static inline uint32_t 199 get_bit32(bits32_t v, uint32_t mask) 200 { 201 return ((BE_32(v.bit_val) & mask) != 0); 202 } 203 static inline void 204 set_bit32(bits32_t *v, uint32_t mask) 205 { 206 v->bit_val |= BE_32(mask); 207 } 208 static inline void 209 clear_bit32(bits32_t *v, uint32_t mask) 210 { 211 v->bit_val &= BE_32(~mask); 212 } 213 static inline bits32_t 214 new_bits32(void) 215 { 216 /* CSTYLED */ 217 return ((bits32_t){ .bit_val = 0 }); 218 } 219 static inline uint32_t 220 from_bits32(bits32_t v) 221 { 222 return (BE_32(v.bit_val)); 223 } 224 225 static inline uint32_t 226 get_bits24(bits24_t v, bitdef_t d) 227 { 228 return ((from_be24(v.bit_val) & d.bit_mask) >> d.bit_shift); 229 } 230 static inline void 231 set_bits24(bits24_t *v, bitdef_t d, uint32_t val) 232 { 233 uint32_t vv = from_be24(v->bit_val); 234 vv &= ~d.bit_mask; 235 vv |= (val << d.bit_shift) & d.bit_mask; 236 v->bit_val = to_be24(vv); 237 } 238 static inline uint32_t 239 get_bit24(bits24_t v, uint32_t mask) 240 { 241 return ((from_be24(v.bit_val) & mask) != 0); 242 } 243 static inline void 244 set_bit24(bits24_t *v, uint32_t mask) 245 { 246 v->bit_val = to_be24(from_be24(v->bit_val) | mask); 247 } 248 static inline void 249 clear_bit24(bits24_t *v, uint32_t mask) 250 { 251 v->bit_val = to_be24(from_be24(v->bit_val) & ~mask); 252 } 253 static inline bits24_t 254 new_bits24(void) 255 { 256 /* CSTYLED */ 257 return ((bits24_t){ .bit_val = to_be24(0) }); 258 } 259 static inline uint32_t 260 from_bits24(bits24_t v) 261 { 262 return (from_be24(v.bit_val)); 263 } 264 265 static inline uint64_t 266 get_bits64(bits64_t v, bitdef_t d) 267 { 268 return ((BE_64(v.bit_val) & d.bit_mask) >> d.bit_shift); 269 } 270 static inline void 271 set_bits64(bits64_t *v, bitdef_t d, uint64_t val) 272 { 273 v->bit_val &= BE_64(~d.bit_mask); 274 v->bit_val |= BE_64((val << d.bit_shift) & d.bit_mask); 275 } 276 static inline uint64_t 277 get_bit64(bits64_t v, uint64_t mask) 278 { 279 return ((BE_64(v.bit_val) & mask) != 0); 280 } 281 static inline void 282 set_bit64(bits64_t *v, uint64_t mask) 283 { 284 v->bit_val |= BE_64(mask); 285 } 286 static inline void 287 clear_bit64(bits64_t *v, uint64_t mask) 288 { 289 v->bit_val &= BE_64(~mask); 290 } 291 static inline bits64_t 292 new_bits64(void) 293 { 294 /* CSTYLED */ 295 return ((bits64_t){ .bit_val = 0 }); 296 } 297 static inline uint64_t 298 from_bits64(bits64_t v) 299 { 300 return (BE_64(v.bit_val)); 301 } 302 303 #endif /* _MLXCX_ENDINT_H */ 304