• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _MLX_BITOPS_H
2 #define _MLX_BITOPS_H
3 
4 /*
5  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 FILE_LICENCE ( GPL2_OR_LATER );
23 
24 /**
25  * @file
26  *
27  * Mellanox bit operations
28  *
29  */
30 
31 /* Datatype used to represent a bit in the Mellanox autogenerated headers */
32 typedef unsigned char pseudo_bit_t;
33 
34 /**
35  * Wrapper structure for pseudo_bit_t structures
36  *
37  * This structure provides a wrapper around the autogenerated
38  * pseudo_bit_t structures.  It has the correct size, and also
39  * encapsulates type information about the underlying pseudo_bit_t
40  * structure, which allows the MLX_FILL etc. macros to work without
41  * requiring explicit type information.
42  */
43 #define MLX_DECLARE_STRUCT( _structure )				     \
44 	_structure {							     \
45 	    union {							     \
46 		uint8_t bytes[ sizeof ( struct _structure ## _st ) / 8 ];    \
47 		uint32_t dwords[ sizeof ( struct _structure ## _st ) / 32 ]; \
48 		struct _structure ## _st *dummy[0];			     \
49 	    } u;							     \
50 	}
51 
52 /** Get pseudo_bit_t structure type from wrapper structure pointer */
53 #define MLX_PSEUDO_STRUCT( _ptr )					     \
54 	typeof ( *((_ptr)->u.dummy[0]) )
55 
56 /** Bit offset of a field within a pseudo_bit_t structure */
57 #define MLX_BIT_OFFSET( _structure_st, _field )				     \
58 	offsetof ( _structure_st, _field )
59 
60 /** Dword offset of a field within a pseudo_bit_t structure */
61 #define MLX_DWORD_OFFSET( _structure_st, _field )			     \
62 	( MLX_BIT_OFFSET ( _structure_st, _field ) / 32 )
63 
64 /** Dword bit offset of a field within a pseudo_bit_t structure
65  *
66  * Yes, using mod-32 would work, but would lose the check for the
67  * error of specifying a mismatched field name and dword index.
68  */
69 #define MLX_DWORD_BIT_OFFSET( _structure_st, _index, _field )		     \
70 	( MLX_BIT_OFFSET ( _structure_st, _field ) - ( 32 * (_index) ) )
71 
72 /** Bit width of a field within a pseudo_bit_t structure */
73 #define MLX_BIT_WIDTH( _structure_st, _field )				     \
74 	sizeof ( ( ( _structure_st * ) NULL )->_field )
75 
76 /** Bit mask for a field within a pseudo_bit_t structure */
77 #define MLX_BIT_MASK( _structure_st, _field )				     \
78 	( ( ~( ( uint32_t ) 0 ) ) >>					     \
79 	  ( 32 - MLX_BIT_WIDTH ( _structure_st, _field ) ) )
80 
81 /*
82  * Assemble native-endian dword from named fields and values
83  *
84  */
85 
86 #define MLX_ASSEMBLE_1( _structure_st, _index, _field, _value )		     \
87 	( (_value) << MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
88 
89 #define MLX_ASSEMBLE_2( _structure_st, _index, _field, _value, ... )	     \
90 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
91 	  MLX_ASSEMBLE_1 ( _structure_st, _index, __VA_ARGS__ ) )
92 
93 #define MLX_ASSEMBLE_3( _structure_st, _index, _field, _value, ... )	     \
94 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
95 	  MLX_ASSEMBLE_2 ( _structure_st, _index, __VA_ARGS__ ) )
96 
97 #define MLX_ASSEMBLE_4( _structure_st, _index, _field, _value, ... )	     \
98 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
99 	  MLX_ASSEMBLE_3 ( _structure_st, _index, __VA_ARGS__ ) )
100 
101 #define MLX_ASSEMBLE_5( _structure_st, _index, _field, _value, ... )	     \
102 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
103 	  MLX_ASSEMBLE_4 ( _structure_st, _index, __VA_ARGS__ ) )
104 
105 #define MLX_ASSEMBLE_6( _structure_st, _index, _field, _value, ... )	     \
106 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
107 	  MLX_ASSEMBLE_5 ( _structure_st, _index, __VA_ARGS__ ) )
108 
109 #define MLX_ASSEMBLE_7( _structure_st, _index, _field, _value, ... )	     \
110 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
111 	  MLX_ASSEMBLE_6 ( _structure_st, _index, __VA_ARGS__ ) )
112 
113 /*
114  * Build native-endian (positive) dword bitmasks from named fields
115  *
116  */
117 
118 #define MLX_MASK_1( _structure_st, _index, _field )			     \
119 	( MLX_BIT_MASK ( _structure_st, _field ) <<			     \
120 	  MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
121 
122 #define MLX_MASK_2( _structure_st, _index, _field, ... )		     \
123 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
124 	  MLX_MASK_1 ( _structure_st, _index, __VA_ARGS__ ) )
125 
126 #define MLX_MASK_3( _structure_st, _index, _field, ... )		     \
127 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
128 	  MLX_MASK_2 ( _structure_st, _index, __VA_ARGS__ ) )
129 
130 #define MLX_MASK_4( _structure_st, _index, _field, ... )		     \
131 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
132 	  MLX_MASK_3 ( _structure_st, _index, __VA_ARGS__ ) )
133 
134 #define MLX_MASK_5( _structure_st, _index, _field, ... )		     \
135 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
136 	  MLX_MASK_4 ( _structure_st, _index, __VA_ARGS__ ) )
137 
138 #define MLX_MASK_6( _structure_st, _index, _field, ... )		     \
139 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
140 	  MLX_MASK_5 ( _structure_st, _index, __VA_ARGS__ ) )
141 
142 #define MLX_MASK_7( _structure_st, _index, _field, ... )		     \
143 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
144 	  MLX_MASK_6 ( _structure_st, _index, __VA_ARGS__ ) )
145 
146 /*
147  * Populate big-endian dwords from named fields and values
148  *
149  */
150 
151 #define MLX_FILL( _ptr, _index, _assembled )				     \
152 	do {								     \
153 		uint32_t *__ptr = &(_ptr)->u.dwords[(_index)];		     \
154 		uint32_t __assembled = (_assembled);			     \
155 		*__ptr = cpu_to_be32 ( __assembled );			     \
156 	} while ( 0 )
157 
158 #define MLX_FILL_1( _ptr, _index, ... )					     \
159 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),\
160 						  _index, __VA_ARGS__ ) )
161 
162 #define MLX_FILL_2( _ptr, _index, ... )					     \
163 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ),\
164 						  _index, __VA_ARGS__ ) )
165 
166 #define MLX_FILL_3( _ptr, _index, ... )					     \
167 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ),\
168 						  _index, __VA_ARGS__ ) )
169 
170 #define MLX_FILL_4( _ptr, _index, ... )					     \
171 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ),\
172 						  _index, __VA_ARGS__ ) )
173 
174 #define MLX_FILL_5( _ptr, _index, ... )					     \
175 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_5 ( MLX_PSEUDO_STRUCT ( _ptr ),\
176 						  _index, __VA_ARGS__ ) )
177 
178 #define MLX_FILL_6( _ptr, _index, ... )					     \
179 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_6 ( MLX_PSEUDO_STRUCT ( _ptr ),\
180 						  _index, __VA_ARGS__ ) )
181 
182 #define MLX_FILL_7( _ptr, _index, ... )					     \
183 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_7 ( MLX_PSEUDO_STRUCT ( _ptr ),\
184 						  _index, __VA_ARGS__ ) )
185 
186 /*
187  * Modify big-endian dword using named field and value
188  *
189  */
190 
191 #define MLX_SET( _ptr, _field, _value )					     \
192 	do {								     \
193 		unsigned int __index = 					     \
194 		    MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
195 		uint32_t *__ptr = &(_ptr)->u.dwords[__index];		     \
196 		uint32_t __value = be32_to_cpu ( *__ptr );		     \
197 		__value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
198 					   __index, _field ) );		     \
199 		__value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
200 					    __index, _field, _value );	     \
201 		*__ptr = cpu_to_be32 ( __value );			     \
202 	} while ( 0 )
203 
204 /*
205  * Extract value of named field
206  *
207  */
208 
209 #define MLX_GET( _ptr, _field )						     \
210 	( {								     \
211 		unsigned int __index = 					     \
212 		    MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
213 		uint32_t *__ptr = &(_ptr)->u.dwords[__index];		     \
214 		uint32_t __value = be32_to_cpu ( *__ptr );		     \
215 		__value >>=						     \
216 		    MLX_DWORD_BIT_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
217 					    __index, _field );		     \
218 		__value &=						     \
219 		    MLX_BIT_MASK ( MLX_PSEUDO_STRUCT ( _ptr ), _field );     \
220 		__value;						     \
221 	} )
222 
223 #endif /* _MLX_BITOPS_H */
224