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