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