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
from_be16(uint16be_t v)45 from_be16(uint16be_t v)
46 {
47 return (BE_16(v.be_val));
48 }
49
50 static inline uint32_t
from_be24(uint24be_t v)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
from_be32(uint32be_t v)59 from_be32(uint32be_t v)
60 {
61 return (BE_32(v.be_val));
62 }
63
64 static inline uint64_t
from_be64(uint64be_t v)65 from_be64(uint64be_t v)
66 {
67 return (BE_64(v.be_val));
68 }
69
70 static inline uint16be_t
to_be16(uint16_t v)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
to_be24(uint32_t v)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
to_be32(uint32_t v)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
to_be64(uint64_t v)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
get_bits8(bits8_t v,bitdef_t d)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
set_bits8(bits8_t * v,bitdef_t d,uint8_t val)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
get_bit8(bits8_t v,uint8_t mask)123 get_bit8(bits8_t v, uint8_t mask)
124 {
125 return ((v.bit_val & mask) != 0);
126 }
127 static inline void
set_bit8(bits8_t * v,uint8_t mask)128 set_bit8(bits8_t *v, uint8_t mask)
129 {
130 v->bit_val |= mask;
131 }
132 static inline void
clear_bit8(bits8_t * v,uint8_t mask)133 clear_bit8(bits8_t *v, uint8_t mask)
134 {
135 v->bit_val &= ~mask;
136 }
137 static inline bits8_t
new_bits8(void)138 new_bits8(void)
139 {
140 /* CSTYLED */
141 return ((bits8_t){ .bit_val = 0 });
142 }
143 static inline uint8_t
from_bits8(bits8_t v)144 from_bits8(bits8_t v)
145 {
146 return (v.bit_val);
147 }
148
149 static inline uint16_t
get_bits16(bits16_t v,bitdef_t d)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
set_bits16(bits16_t * v,bitdef_t d,uint16_t val)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
get_bit16(bits16_t v,uint16_t mask)161 get_bit16(bits16_t v, uint16_t mask)
162 {
163 return ((BE_16(v.bit_val) & mask) != 0);
164 }
165 static inline void
set_bit16(bits16_t * v,uint16_t mask)166 set_bit16(bits16_t *v, uint16_t mask)
167 {
168 v->bit_val |= BE_16(mask);
169 }
170 static inline void
clear_bit16(bits16_t * v,uint16_t mask)171 clear_bit16(bits16_t *v, uint16_t mask)
172 {
173 v->bit_val &= BE_16(~mask);
174 }
175 static inline bits16_t
new_bits16(void)176 new_bits16(void)
177 {
178 /* CSTYLED */
179 return ((bits16_t){ .bit_val = 0 });
180 }
181 static inline uint16_t
from_bits16(bits16_t v)182 from_bits16(bits16_t v)
183 {
184 return (BE_16(v.bit_val));
185 }
186
187 static inline uint32_t
get_bits32(bits32_t v,bitdef_t d)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
set_bits32(bits32_t * v,bitdef_t d,uint32_t val)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
get_bit32(bits32_t v,uint32_t mask)199 get_bit32(bits32_t v, uint32_t mask)
200 {
201 return ((BE_32(v.bit_val) & mask) != 0);
202 }
203 static inline void
set_bit32(bits32_t * v,uint32_t mask)204 set_bit32(bits32_t *v, uint32_t mask)
205 {
206 v->bit_val |= BE_32(mask);
207 }
208 static inline void
clear_bit32(bits32_t * v,uint32_t mask)209 clear_bit32(bits32_t *v, uint32_t mask)
210 {
211 v->bit_val &= BE_32(~mask);
212 }
213 static inline bits32_t
new_bits32(void)214 new_bits32(void)
215 {
216 /* CSTYLED */
217 return ((bits32_t){ .bit_val = 0 });
218 }
219 static inline uint32_t
from_bits32(bits32_t v)220 from_bits32(bits32_t v)
221 {
222 return (BE_32(v.bit_val));
223 }
224
225 static inline uint32_t
get_bits24(bits24_t v,bitdef_t d)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
set_bits24(bits24_t * v,bitdef_t d,uint32_t val)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
get_bit24(bits24_t v,uint32_t mask)239 get_bit24(bits24_t v, uint32_t mask)
240 {
241 return ((from_be24(v.bit_val) & mask) != 0);
242 }
243 static inline void
set_bit24(bits24_t * v,uint32_t mask)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
clear_bit24(bits24_t * v,uint32_t mask)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
new_bits24(void)254 new_bits24(void)
255 {
256 /* CSTYLED */
257 return ((bits24_t){ .bit_val = to_be24(0) });
258 }
259 static inline uint32_t
from_bits24(bits24_t v)260 from_bits24(bits24_t v)
261 {
262 return (from_be24(v.bit_val));
263 }
264
265 static inline uint64_t
get_bits64(bits64_t v,bitdef_t d)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
set_bits64(bits64_t * v,bitdef_t d,uint64_t val)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
get_bit64(bits64_t v,uint64_t mask)277 get_bit64(bits64_t v, uint64_t mask)
278 {
279 return ((BE_64(v.bit_val) & mask) != 0);
280 }
281 static inline void
set_bit64(bits64_t * v,uint64_t mask)282 set_bit64(bits64_t *v, uint64_t mask)
283 {
284 v->bit_val |= BE_64(mask);
285 }
286 static inline void
clear_bit64(bits64_t * v,uint64_t mask)287 clear_bit64(bits64_t *v, uint64_t mask)
288 {
289 v->bit_val &= BE_64(~mask);
290 }
291 static inline bits64_t
new_bits64(void)292 new_bits64(void)
293 {
294 /* CSTYLED */
295 return ((bits64_t){ .bit_val = 0 });
296 }
297 static inline uint64_t
from_bits64(bits64_t v)298 from_bits64(bits64_t v)
299 {
300 return (BE_64(v.bit_val));
301 }
302
303 #endif /* _MLXCX_ENDINT_H */
304