nx_bitops.h

Go to the documentation of this file.
00001 #ifndef _NX_BITOPS_H
00002 #define _NX_BITOPS_H
00003 
00004 /*
00005  * Copyright (C) 2008 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., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  */
00021 
00022 FILE_LICENCE ( GPL2_OR_LATER );
00023 
00024 /**
00025  * @file
00026  *
00027  * NetXen bit operations
00028  *
00029  */
00030 
00031 /** Datatype used to represent a bit in the pseudo-structures */
00032 typedef unsigned char pseudo_bit_t;
00033 
00034 /**
00035  * Wrapper structure for pseudo_bit_t structures
00036  *
00037  * This structure provides a wrapper around pseudo_bit_t structures.
00038  * It has the correct size, and also encapsulates type information
00039  * about the underlying pseudo_bit_t-based structure, which allows the
00040  * NX_FILL etc. macros to work without requiring explicit type
00041  * information.
00042  */
00043 #define NX_PSEUDO_BIT_STRUCT( _structure )                                   \
00044         union {                                                              \
00045                 uint8_t bytes[ sizeof ( _structure ) / 8 ];                  \
00046                 uint64_t qwords[ sizeof ( _structure ) / 64 ];               \
00047                 _structure *dummy[0];                                        \
00048         } u;
00049 
00050 /** Get pseudo_bit_t structure type from wrapper structure pointer */
00051 #define NX_PSEUDO_STRUCT( _ptr )                                             \
00052         typeof ( *((_ptr)->u.dummy[0]) )
00053 
00054 /** Bit offset of a field within a pseudo_bit_t structure */
00055 #define NX_BIT_OFFSET( _ptr, _field )                                        \
00056         offsetof ( NX_PSEUDO_STRUCT ( _ptr ), _field )
00057 
00058 /** Bit width of a field within a pseudo_bit_t structure */
00059 #define NX_BIT_WIDTH( _ptr, _field )                                         \
00060         sizeof ( ( ( NX_PSEUDO_STRUCT ( _ptr ) * ) NULL )->_field )
00061 
00062 /** Qword offset of a field within a pseudo_bit_t structure */
00063 #define NX_QWORD_OFFSET( _ptr, _field )                                      \
00064         ( NX_BIT_OFFSET ( _ptr, _field ) / 64 )
00065 
00066 /** Qword bit offset of a field within a pseudo_bit_t structure
00067  *
00068  * Yes, using mod-64 would work, but would lose the check for the
00069  * error of specifying a mismatched field name and qword index.
00070  */
00071 #define NX_QWORD_BIT_OFFSET( _ptr, _index, _field )                          \
00072         ( NX_BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
00073 
00074 /** Bit mask for a field within a pseudo_bit_t structure */
00075 #define NX_BIT_MASK( _ptr, _field )                                          \
00076         ( ( ~( ( uint64_t ) 0 ) ) >>                                         \
00077           ( 64 - NX_BIT_WIDTH ( _ptr, _field ) ) )
00078 
00079 /*
00080  * Assemble native-endian qword from named fields and values
00081  *
00082  */
00083 
00084 #define NX_ASSEMBLE_1( _ptr, _index, _field, _value )                        \
00085         ( ( ( uint64_t) (_value) ) <<                                        \
00086           NX_QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
00087 
00088 #define NX_ASSEMBLE_2( _ptr, _index, _field, _value, ... )                   \
00089         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00090           NX_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
00091 
00092 #define NX_ASSEMBLE_3( _ptr, _index, _field, _value, ... )                   \
00093         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00094           NX_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
00095 
00096 #define NX_ASSEMBLE_4( _ptr, _index, _field, _value, ... )                   \
00097         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00098           NX_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
00099 
00100 #define NX_ASSEMBLE_5( _ptr, _index, _field, _value, ... )                   \
00101         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00102           NX_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
00103 
00104 #define NX_ASSEMBLE_6( _ptr, _index, _field, _value, ... )                   \
00105         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00106           NX_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
00107 
00108 #define NX_ASSEMBLE_7( _ptr, _index, _field, _value, ... )                   \
00109         ( NX_ASSEMBLE_1 ( _ptr, _index, _field, _value ) |                   \
00110           NX_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
00111 
00112 /*
00113  * Build native-endian (positive) qword bitmasks from named fields
00114  *
00115  */
00116 
00117 #define NX_MASK_1( _ptr, _index, _field )                            \
00118         ( NX_BIT_MASK ( _ptr, _field ) <<                            \
00119           NX_QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
00120 
00121 #define NX_MASK_2( _ptr, _index, _field, ... )                       \
00122         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00123           NX_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
00124 
00125 #define NX_MASK_3( _ptr, _index, _field, ... )                       \
00126         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00127           NX_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
00128 
00129 #define NX_MASK_4( _ptr, _index, _field, ... )                       \
00130         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00131           NX_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
00132 
00133 #define NX_MASK_5( _ptr, _index, _field, ... )                       \
00134         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00135           NX_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
00136 
00137 #define NX_MASK_6( _ptr, _index, _field, ... )                       \
00138         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00139           NX_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
00140 
00141 #define NX_MASK_7( _ptr, _index, _field, ... )                       \
00142         ( NX_MASK_1 ( _ptr, _index, _field ) |                       \
00143           NX_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
00144 
00145 /*
00146  * Populate big-endian qwords from named fields and values
00147  *
00148  */
00149 
00150 #define NX_FILL( _ptr, _index, _assembled )                                  \
00151         do {                                                                 \
00152                 uint64_t *__ptr = &(_ptr)->u.qwords[(_index)];               \
00153                 uint64_t __assembled = (_assembled);                         \
00154                 *__ptr = cpu_to_le64 ( __assembled );                        \
00155         } while ( 0 )
00156 
00157 #define NX_FILL_1( _ptr, _index, ... )                                       \
00158         NX_FILL ( _ptr, _index, NX_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
00159 
00160 #define NX_FILL_2( _ptr, _index, ... )                                       \
00161         NX_FILL ( _ptr, _index, NX_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
00162 
00163 #define NX_FILL_3( _ptr, _index, ... )                                       \
00164         NX_FILL ( _ptr, _index, NX_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
00165 
00166 #define NX_FILL_4( _ptr, _index, ... )                                       \
00167         NX_FILL ( _ptr, _index, NX_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
00168 
00169 #define NX_FILL_5( _ptr, _index, ... )                                       \
00170         NX_FILL ( _ptr, _index, NX_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
00171 
00172 #define NX_FILL_6( _ptr, _index, ... )                                       \
00173         NX_FILL ( _ptr, _index, NX_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
00174 
00175 #define NX_FILL_7( _ptr, _index, ... )                                       \
00176         NX_FILL ( _ptr, _index, NX_ASSEMBLE_7 ( _ptr, _index, __VA_ARGS__ ) )
00177 
00178 /** Extract value of named field */
00179 #define NX_GET64( _ptr, _field )                                             \
00180         ( {                                                                  \
00181                 unsigned int __index = NX_QWORD_OFFSET ( _ptr, _field );     \
00182                 uint64_t *__ptr = &(_ptr)->u.qwords[__index];                \
00183                 uint64_t __value = le64_to_cpu ( *__ptr );                   \
00184                 __value >>=                                                  \
00185                     NX_QWORD_BIT_OFFSET ( _ptr, __index, _field );           \
00186                 __value &= NX_BIT_MASK ( _ptr, _field );                     \
00187                 __value;                                                     \
00188         } )
00189 
00190 /** Extract value of named field (for fields up to the size of a long) */
00191 #define NX_GET( _ptr, _field )                                               \
00192         ( ( unsigned long ) NX_GET64 ( _ptr, _field ) )
00193 
00194 #endif /* _NX_BITOPS_H */

Generated on Tue Apr 6 20:01:02 2010 for gPXE by  doxygen 1.5.7.1