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