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., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  */
22 
23 FILE_LICENCE ( GPL2_OR_LATER );
24 
25 /**
26  * @file
27  *
28  * Mellanox bit operations
29  *
30  */
31 
32 /* Datatype used to represent a bit in the Mellanox autogenerated headers */
33 typedef unsigned char pseudo_bit_t;
34 
35 /**
36  * Wrapper structure for pseudo_bit_t structures
37  *
38  * This structure provides a wrapper around the autogenerated
39  * pseudo_bit_t structures.  It has the correct size, and also
40  * encapsulates type information about the underlying pseudo_bit_t
41  * structure, which allows the MLX_FILL etc. macros to work without
42  * requiring explicit type information.
43  */
44 #define MLX_DECLARE_STRUCT( _structure )				     \
45 	_structure {							     \
46 	    union {							     \
47 		uint8_t bytes[ sizeof ( struct _structure ## _st ) / 8 ];    \
48 		uint32_t dwords[ sizeof ( struct _structure ## _st ) / 32 ]; \
49 		struct _structure ## _st *dummy[0];			     \
50 	    } __attribute__ (( packed )) u;				     \
51 	} __attribute__ (( packed ))
52 
53 /** Get pseudo_bit_t structure type from wrapper structure pointer */
54 #define MLX_PSEUDO_STRUCT( _ptr )					     \
55 	typeof ( *((_ptr)->u.dummy[0]) )
56 
57 /** Bit offset of a field within a pseudo_bit_t structure */
58 #define MLX_BIT_OFFSET( _structure_st, _field )				     \
59 	offsetof ( _structure_st, _field )
60 
61 /** Dword offset of a field within a pseudo_bit_t structure */
62 #define MLX_DWORD_OFFSET( _structure_st, _field )			     \
63 	( MLX_BIT_OFFSET ( _structure_st, _field ) / 32 )
64 
65 /** Dword bit offset of a field within a pseudo_bit_t structure
66  *
67  * Yes, using mod-32 would work, but would lose the check for the
68  * error of specifying a mismatched field name and dword index.
69  */
70 #define MLX_DWORD_BIT_OFFSET( _structure_st, _index, _field )		     \
71 	( MLX_BIT_OFFSET ( _structure_st, _field ) - ( 32 * (_index) ) )
72 
73 /** Bit width of a field within a pseudo_bit_t structure */
74 #define MLX_BIT_WIDTH( _structure_st, _field )				     \
75 	sizeof ( ( ( _structure_st * ) NULL )->_field )
76 
77 /** Bit mask for a field within a pseudo_bit_t structure */
78 #define MLX_BIT_MASK( _structure_st, _field )				     \
79 	( ( ~( ( uint32_t ) 0 ) ) >>					     \
80 	  ( 32 - MLX_BIT_WIDTH ( _structure_st, _field ) ) )
81 
82 /*
83  * Assemble native-endian dword from named fields and values
84  *
85  */
86 
87 #define MLX_ASSEMBLE_1( _structure_st, _index, _field, _value )		     \
88 	( (_value) << MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
89 
90 #define MLX_ASSEMBLE_2( _structure_st, _index, _field, _value, ... )	     \
91 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
92 	  MLX_ASSEMBLE_1 ( _structure_st, _index, __VA_ARGS__ ) )
93 
94 #define MLX_ASSEMBLE_3( _structure_st, _index, _field, _value, ... )	     \
95 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
96 	  MLX_ASSEMBLE_2 ( _structure_st, _index, __VA_ARGS__ ) )
97 
98 #define MLX_ASSEMBLE_4( _structure_st, _index, _field, _value, ... )	     \
99 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
100 	  MLX_ASSEMBLE_3 ( _structure_st, _index, __VA_ARGS__ ) )
101 
102 #define MLX_ASSEMBLE_5( _structure_st, _index, _field, _value, ... )	     \
103 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
104 	  MLX_ASSEMBLE_4 ( _structure_st, _index, __VA_ARGS__ ) )
105 
106 #define MLX_ASSEMBLE_6( _structure_st, _index, _field, _value, ... )	     \
107 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
108 	  MLX_ASSEMBLE_5 ( _structure_st, _index, __VA_ARGS__ ) )
109 
110 #define MLX_ASSEMBLE_7( _structure_st, _index, _field, _value, ... )	     \
111 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
112 	  MLX_ASSEMBLE_6 ( _structure_st, _index, __VA_ARGS__ ) )
113 
114 #define MLX_ASSEMBLE_8( _structure_st, _index, _field, _value, ... )	     \
115 	( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |	     \
116 	  MLX_ASSEMBLE_7 ( _structure_st, _index, __VA_ARGS__ ) )
117 
118 /*
119  * Build native-endian (positive) dword bitmasks from named fields
120  *
121  */
122 
123 #define MLX_MASK_1( _structure_st, _index, _field )			     \
124 	( MLX_BIT_MASK ( _structure_st, _field ) <<			     \
125 	  MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
126 
127 #define MLX_MASK_2( _structure_st, _index, _field, ... )		     \
128 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
129 	  MLX_MASK_1 ( _structure_st, _index, __VA_ARGS__ ) )
130 
131 #define MLX_MASK_3( _structure_st, _index, _field, ... )		     \
132 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
133 	  MLX_MASK_2 ( _structure_st, _index, __VA_ARGS__ ) )
134 
135 #define MLX_MASK_4( _structure_st, _index, _field, ... )		     \
136 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
137 	  MLX_MASK_3 ( _structure_st, _index, __VA_ARGS__ ) )
138 
139 #define MLX_MASK_5( _structure_st, _index, _field, ... )		     \
140 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
141 	  MLX_MASK_4 ( _structure_st, _index, __VA_ARGS__ ) )
142 
143 #define MLX_MASK_6( _structure_st, _index, _field, ... )		     \
144 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
145 	  MLX_MASK_5 ( _structure_st, _index, __VA_ARGS__ ) )
146 
147 #define MLX_MASK_7( _structure_st, _index, _field, ... )		     \
148 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
149 	  MLX_MASK_6 ( _structure_st, _index, __VA_ARGS__ ) )
150 
151 #define MLX_MASK_8( _structure_st, _index, _field, ... )		     \
152 	( MLX_MASK_1 ( _structure_st, _index, _field ) |		     \
153 	  MLX_MASK_7 ( _structure_st, _index, __VA_ARGS__ ) )
154 
155 /*
156  * Populate big-endian dwords from named fields and values
157  *
158  */
159 
160 #define MLX_FILL( _ptr, _index, _assembled )				     \
161 	do {								     \
162 		uint32_t *__ptr = &(_ptr)->u.dwords[(_index)];		     \
163 		uint32_t __assembled = (_assembled);			     \
164 		*__ptr = cpu_to_be32 ( __assembled );			     \
165 	} while ( 0 )
166 
167 #define MLX_FILL_1( _ptr, _index, ... )					     \
168 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),\
169 						  _index, __VA_ARGS__ ) )
170 
171 #define MLX_FILL_2( _ptr, _index, ... )					     \
172 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ),\
173 						  _index, __VA_ARGS__ ) )
174 
175 #define MLX_FILL_3( _ptr, _index, ... )					     \
176 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ),\
177 						  _index, __VA_ARGS__ ) )
178 
179 #define MLX_FILL_4( _ptr, _index, ... )					     \
180 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ),\
181 						  _index, __VA_ARGS__ ) )
182 
183 #define MLX_FILL_5( _ptr, _index, ... )					     \
184 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_5 ( MLX_PSEUDO_STRUCT ( _ptr ),\
185 						  _index, __VA_ARGS__ ) )
186 
187 #define MLX_FILL_6( _ptr, _index, ... )					     \
188 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_6 ( MLX_PSEUDO_STRUCT ( _ptr ),\
189 						  _index, __VA_ARGS__ ) )
190 
191 #define MLX_FILL_7( _ptr, _index, ... )					     \
192 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_7 ( MLX_PSEUDO_STRUCT ( _ptr ),\
193 						  _index, __VA_ARGS__ ) )
194 
195 #define MLX_FILL_8( _ptr, _index, ... )					     \
196 	MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_8 ( MLX_PSEUDO_STRUCT ( _ptr ),\
197 						  _index, __VA_ARGS__ ) )
198 
199 /*
200  * Modify big-endian dword using named field and value
201  *
202  */
203 
204 #define MLX_SET( _ptr, _field, _value )					     \
205 	do {								     \
206 		unsigned int __index = 					     \
207 		    MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
208 		uint32_t *__ptr = &(_ptr)->u.dwords[__index];		     \
209 		uint32_t __value = be32_to_cpu ( *__ptr );		     \
210 		__value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
211 					   __index, _field ) );		     \
212 		__value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
213 					    __index, _field, _value );	     \
214 		*__ptr = cpu_to_be32 ( __value );			     \
215 	} while ( 0 )
216 
217 /*
218  * Extract value of named field
219  *
220  */
221 
222 #define MLX_GET( _ptr, _field )						     \
223 	( {								     \
224 		unsigned int __index = 					     \
225 		    MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
226 		uint32_t *__ptr = &(_ptr)->u.dwords[__index];		     \
227 		uint32_t __value = be32_to_cpu ( *__ptr );		     \
228 		__value >>=						     \
229 		    MLX_DWORD_BIT_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ),	     \
230 					    __index, _field );		     \
231 		__value &=						     \
232 		    MLX_BIT_MASK ( MLX_PSEUDO_STRUCT ( _ptr ), _field );     \
233 		__value;						     \
234 	} )
235 
236 /*
237  * Fill high dword of physical address, if necessary
238  *
239  */
240 #define MLX_FILL_H( _structure_st, _index, _field, _address ) do {	     \
241 	if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {		     \
242 		MLX_FILL_1 ( _structure_st, _index, _field,		     \
243 			     ( ( ( uint64_t ) (_address) ) >> 32 ) );	     \
244 	} } while ( 0 )
245 
246 #endif /* _MLX_BITOPS_H */
247