xref: /illumos-gate/usr/src/uts/common/io/mlxcx/mlxcx_endint.h (revision ebb7c6fd4f966f94af3e235242b8a39b7a53664a)
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