iPXE
mlx_bitops.h
Go to the documentation of this file.
00001 #ifndef _MLX_BITOPS_H
00002 #define _MLX_BITOPS_H
00003 
00004 /*
00005  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of the
00010  * License, or any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00020  * 02110-1301, USA.
00021  */
00022 
00023 FILE_LICENCE ( GPL2_OR_LATER );
00024 
00025 /**
00026  * @file
00027  *
00028  * Mellanox bit operations
00029  *
00030  */
00031 
00032 /* Datatype used to represent a bit in the Mellanox autogenerated headers */
00033 typedef unsigned char pseudo_bit_t;
00034 
00035 /**
00036  * Wrapper structure for pseudo_bit_t structures
00037  *
00038  * This structure provides a wrapper around the autogenerated
00039  * pseudo_bit_t structures.  It has the correct size, and also
00040  * encapsulates type information about the underlying pseudo_bit_t
00041  * structure, which allows the MLX_FILL etc. macros to work without
00042  * requiring explicit type information.
00043  */
00044 #define MLX_DECLARE_STRUCT( _structure )                                     \
00045         _structure {                                                         \
00046             union {                                                          \
00047                 uint8_t bytes[ sizeof ( struct _structure ## _st ) / 8 ];    \
00048                 uint32_t dwords[ sizeof ( struct _structure ## _st ) / 32 ]; \
00049                 struct _structure ## _st *dummy[0];                          \
00050             } __attribute__ (( packed )) u;                                  \
00051         } __attribute__ (( packed ))
00052 
00053 /** Get pseudo_bit_t structure type from wrapper structure pointer */
00054 #define MLX_PSEUDO_STRUCT( _ptr )                                            \
00055         typeof ( *((_ptr)->u.dummy[0]) )
00056 
00057 /** Bit offset of a field within a pseudo_bit_t structure */
00058 #define MLX_BIT_OFFSET( _structure_st, _field )                              \
00059         offsetof ( _structure_st, _field )
00060 
00061 /** Dword offset of a field within a pseudo_bit_t structure */
00062 #define MLX_DWORD_OFFSET( _structure_st, _field )                            \
00063         ( MLX_BIT_OFFSET ( _structure_st, _field ) / 32 )
00064 
00065 /** Dword bit offset of a field within a pseudo_bit_t structure
00066  *
00067  * Yes, using mod-32 would work, but would lose the check for the
00068  * error of specifying a mismatched field name and dword index.
00069  */
00070 #define MLX_DWORD_BIT_OFFSET( _structure_st, _index, _field )                \
00071         ( MLX_BIT_OFFSET ( _structure_st, _field ) - ( 32 * (_index) ) )
00072 
00073 /** Bit width of a field within a pseudo_bit_t structure */
00074 #define MLX_BIT_WIDTH( _structure_st, _field )                               \
00075         sizeof ( ( ( _structure_st * ) NULL )->_field )
00076 
00077 /** Bit mask for a field within a pseudo_bit_t structure */
00078 #define MLX_BIT_MASK( _structure_st, _field )                                \
00079         ( ( ~( ( uint32_t ) 0 ) ) >>                                         \
00080           ( 32 - MLX_BIT_WIDTH ( _structure_st, _field ) ) )
00081 
00082 /*
00083  * Assemble native-endian dword from named fields and values
00084  *
00085  */
00086 
00087 #define MLX_ASSEMBLE_1( _structure_st, _index, _field, _value )              \
00088         ( (_value) << MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
00089 
00090 #define MLX_ASSEMBLE_2( _structure_st, _index, _field, _value, ... )         \
00091         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00092           MLX_ASSEMBLE_1 ( _structure_st, _index, __VA_ARGS__ ) )
00093 
00094 #define MLX_ASSEMBLE_3( _structure_st, _index, _field, _value, ... )         \
00095         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00096           MLX_ASSEMBLE_2 ( _structure_st, _index, __VA_ARGS__ ) )
00097 
00098 #define MLX_ASSEMBLE_4( _structure_st, _index, _field, _value, ... )         \
00099         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00100           MLX_ASSEMBLE_3 ( _structure_st, _index, __VA_ARGS__ ) )
00101 
00102 #define MLX_ASSEMBLE_5( _structure_st, _index, _field, _value, ... )         \
00103         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00104           MLX_ASSEMBLE_4 ( _structure_st, _index, __VA_ARGS__ ) )
00105 
00106 #define MLX_ASSEMBLE_6( _structure_st, _index, _field, _value, ... )         \
00107         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00108           MLX_ASSEMBLE_5 ( _structure_st, _index, __VA_ARGS__ ) )
00109 
00110 #define MLX_ASSEMBLE_7( _structure_st, _index, _field, _value, ... )         \
00111         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00112           MLX_ASSEMBLE_6 ( _structure_st, _index, __VA_ARGS__ ) )
00113 
00114 #define MLX_ASSEMBLE_8( _structure_st, _index, _field, _value, ... )         \
00115         ( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) |         \
00116           MLX_ASSEMBLE_7 ( _structure_st, _index, __VA_ARGS__ ) )
00117 
00118 /*
00119  * Build native-endian (positive) dword bitmasks from named fields
00120  *
00121  */
00122 
00123 #define MLX_MASK_1( _structure_st, _index, _field )                          \
00124         ( MLX_BIT_MASK ( _structure_st, _field ) <<                          \
00125           MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
00126 
00127 #define MLX_MASK_2( _structure_st, _index, _field, ... )                     \
00128         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00129           MLX_MASK_1 ( _structure_st, _index, __VA_ARGS__ ) )
00130 
00131 #define MLX_MASK_3( _structure_st, _index, _field, ... )                     \
00132         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00133           MLX_MASK_2 ( _structure_st, _index, __VA_ARGS__ ) )
00134 
00135 #define MLX_MASK_4( _structure_st, _index, _field, ... )                     \
00136         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00137           MLX_MASK_3 ( _structure_st, _index, __VA_ARGS__ ) )
00138 
00139 #define MLX_MASK_5( _structure_st, _index, _field, ... )                     \
00140         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00141           MLX_MASK_4 ( _structure_st, _index, __VA_ARGS__ ) )
00142 
00143 #define MLX_MASK_6( _structure_st, _index, _field, ... )                     \
00144         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00145           MLX_MASK_5 ( _structure_st, _index, __VA_ARGS__ ) )
00146 
00147 #define MLX_MASK_7( _structure_st, _index, _field, ... )                     \
00148         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00149           MLX_MASK_6 ( _structure_st, _index, __VA_ARGS__ ) )
00150 
00151 #define MLX_MASK_8( _structure_st, _index, _field, ... )                     \
00152         ( MLX_MASK_1 ( _structure_st, _index, _field ) |                     \
00153           MLX_MASK_7 ( _structure_st, _index, __VA_ARGS__ ) )
00154 
00155 /*
00156  * Populate big-endian dwords from named fields and values
00157  *
00158  */
00159 
00160 #define MLX_FILL( _ptr, _index, _assembled )                                 \
00161         do {                                                                 \
00162                 uint32_t *__ptr = &(_ptr)->u.dwords[(_index)];               \
00163                 uint32_t __assembled = (_assembled);                         \
00164                 *__ptr = cpu_to_be32 ( __assembled );                        \
00165         } while ( 0 )
00166 
00167 #define MLX_FILL_1( _ptr, _index, ... )                                      \
00168         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00169                                                   _index, __VA_ARGS__ ) )
00170 
00171 #define MLX_FILL_2( _ptr, _index, ... )                                      \
00172         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00173                                                   _index, __VA_ARGS__ ) )
00174 
00175 #define MLX_FILL_3( _ptr, _index, ... )                                      \
00176         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00177                                                   _index, __VA_ARGS__ ) )
00178 
00179 #define MLX_FILL_4( _ptr, _index, ... )                                      \
00180         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00181                                                   _index, __VA_ARGS__ ) )
00182 
00183 #define MLX_FILL_5( _ptr, _index, ... )                                      \
00184         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_5 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00185                                                   _index, __VA_ARGS__ ) )
00186 
00187 #define MLX_FILL_6( _ptr, _index, ... )                                      \
00188         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_6 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00189                                                   _index, __VA_ARGS__ ) )
00190 
00191 #define MLX_FILL_7( _ptr, _index, ... )                                      \
00192         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_7 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00193                                                   _index, __VA_ARGS__ ) )
00194 
00195 #define MLX_FILL_8( _ptr, _index, ... )                                      \
00196         MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_8 ( MLX_PSEUDO_STRUCT ( _ptr ),\
00197                                                   _index, __VA_ARGS__ ) )
00198 
00199 /*
00200  * Modify big-endian dword using named field and value
00201  *
00202  */
00203 
00204 #define MLX_SET( _ptr, _field, _value )                                      \
00205         do {                                                                 \
00206                 unsigned int __index =                                       \
00207                     MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
00208                 uint32_t *__ptr = &(_ptr)->u.dwords[__index];                \
00209                 uint32_t __value = be32_to_cpu ( *__ptr );                   \
00210                 __value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ),       \
00211                                            __index, _field ) );              \
00212                 __value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),      \
00213                                             __index, _field, _value );       \
00214                 *__ptr = cpu_to_be32 ( __value );                            \
00215         } while ( 0 )
00216 
00217 /*
00218  * Extract value of named field
00219  *
00220  */
00221 
00222 #define MLX_GET( _ptr, _field )                                              \
00223         ( {                                                                  \
00224                 unsigned int __index =                                       \
00225                     MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
00226                 uint32_t *__ptr = &(_ptr)->u.dwords[__index];                \
00227                 uint32_t __value = be32_to_cpu ( *__ptr );                   \
00228                 __value >>=                                                  \
00229                     MLX_DWORD_BIT_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ),       \
00230                                             __index, _field );               \
00231                 __value &=                                                   \
00232                     MLX_BIT_MASK ( MLX_PSEUDO_STRUCT ( _ptr ), _field );     \
00233                 __value;                                                     \
00234         } )
00235 
00236 /*
00237  * Fill high dword of physical address, if necessary
00238  *
00239  */
00240 #define MLX_FILL_H( _structure_st, _index, _field, _address ) do {           \
00241         if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {                 \
00242                 MLX_FILL_1 ( _structure_st, _index, _field,                  \
00243                              ( ( ( uint64_t ) (_address) ) >> 32 ) );        \
00244         } } while ( 0 )
00245 
00246 #endif /* _MLX_BITOPS_H */