PAPI  5.3.0.0
linux-IOunit.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00020 #include "linux-IOunit.h"
00021 
00022 /* Declare our vector in advance */
00023 papi_vector_t _IOunit_vector;
00024 
00025 /* prototypes */
00026 void user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext );
00027 
00028 /*****************************************************************************
00029  *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
00030  *****************************************************************************/
00031 
00032 /*
00033  * This is called whenever a thread is initialized
00034  */
00035 int
00036 IOUNIT_init_thread( hwd_context_t * ctx )
00037 {
00038 #ifdef DEBUG_BGQ
00039     printf( "IOUNIT_init_thread\n" );
00040 #endif
00041     
00042     ( void ) ctx;
00043     return PAPI_OK;
00044 }
00045 
00046 
00047 /* Initialize hardware counters, setup the function vector table
00048  * and get hardware information, this routine is called when the 
00049  * PAPI process is initialized (IE PAPI_library_init)
00050  */
00051 int
00052 IOUNIT_init_component( int cidx )
00053 {  
00054 #ifdef DEBUG_BGQ
00055     printf( "IOUNIT_init_component\n" );
00056 #endif
00057 
00058     _IOunit_vector.cmp_info.CmpIdx = cidx;
00059 #ifdef DEBUG_BGQ
00060     printf( "IOUNIT_init_component cidx = %d\n", cidx );
00061 #endif
00062     
00063     return ( PAPI_OK );
00064 }
00065 
00066 
00067 /*
00068  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00069  * functions
00070  */
00071 int
00072 IOUNIT_init_control_state( hwd_control_state_t * ptr )
00073 {
00074 #ifdef DEBUG_BGQ
00075     printf( "IOUNIT_init_control_state\n" );
00076 #endif
00077     int retval;
00078 
00079     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00080     
00081     this_state->EventGroup = Bgpm_CreateEventSet();
00082     retval = _check_BGPM_error( this_state->EventGroup, "Bgpm_CreateEventSet" );
00083     if ( retval < 0 ) return retval;
00084 
00085     // initialize overflow flag to OFF (0)
00086     this_state->overflow = 0;
00087     this_state->overflow_count = 0;
00088     
00089     return PAPI_OK;
00090 }
00091 
00092 
00093 /*
00094  *
00095  */
00096 int
00097 IOUNIT_start( hwd_context_t * ctx, hwd_control_state_t * ptr )
00098 {
00099 #ifdef DEBUG_BGQ
00100     printf( "IOUNIT_start\n" );
00101 #endif
00102     ( void ) ctx;
00103     int retval;
00104     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00105     
00106     retval = Bgpm_ResetStart( this_state->EventGroup );
00107     retval = _check_BGPM_error( retval, "Bgpm_ResetStart" );
00108     if ( retval < 0 ) return retval;
00109 
00110     return ( PAPI_OK );
00111 }
00112 
00113 
00114 /*
00115  *
00116  */
00117 int
00118 IOUNIT_stop( hwd_context_t * ctx, hwd_control_state_t * ptr )
00119 {
00120 #ifdef DEBUG_BGQ
00121     printf( "IOUNIT_stop\n" );
00122 #endif
00123     ( void ) ctx;
00124     int retval;
00125     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00126     
00127     retval = Bgpm_Stop( this_state->EventGroup );
00128     retval = _check_BGPM_error( retval, "Bgpm_Stop" );
00129     if ( retval < 0 ) return retval;
00130 
00131     return ( PAPI_OK );
00132 }
00133 
00134 
00135 /*
00136  *
00137  */
00138 int
00139 IOUNIT_read( hwd_context_t * ctx, hwd_control_state_t * ptr,
00140            long_long ** events, int flags )
00141 {
00142 #ifdef DEBUG_BGQ
00143     printf( "IOUNIT_read\n" );
00144 #endif
00145     ( void ) ctx;
00146     ( void ) flags;
00147     int i, numEvts;
00148     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00149 
00150     numEvts = Bgpm_NumEvents( this_state->EventGroup );
00151     if ( numEvts == 0 ) {
00152 #ifdef DEBUG_BGPM
00153         printf ("Error: ret value is %d for BGPM API function Bgpm_NumEvents.\n", numEvts );
00154 #endif
00155         //return ( EXIT_FAILURE );
00156     }
00157         
00158     for ( i = 0; i < numEvts; i++ )
00159         this_state->counts[i] = _common_getEventValue( i, this_state->EventGroup );
00160 
00161     *events = this_state->counts;
00162     
00163     return ( PAPI_OK );
00164 }
00165 
00166 
00167 /*
00168  *
00169  */
00170 int
00171 IOUNIT_shutdown_thread( hwd_context_t * ctx )
00172 {
00173 #ifdef DEBUG_BGQ
00174     printf( "IOUNIT_shutdown_thread\n" );
00175 #endif
00176     
00177     ( void ) ctx;
00178     return ( PAPI_OK );
00179 }
00180 
00181 
00182 /*
00183  * user_signal_handler
00184  *
00185  * This function is used when hardware overflows are working or when
00186  * software overflows are forced
00187  */
00188 void
00189 user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext )
00190 {
00191 #ifdef DEBUG_BGQ
00192     printf( "user_signal_handler_IOUNIT\n" );
00193 #endif
00194     ( void ) address;
00195     int retval;
00196     unsigned i;
00197     int isHardware = 1;
00198     int cidx = _IOunit_vector.cmp_info.CmpIdx;
00199     long_long overflow_bit = 0;
00200     caddr_t address1;
00201     _papi_hwi_context_t ctx;
00202     ctx.ucontext = ( hwd_ucontext_t * ) pContext;
00203     ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 );
00204     EventSetInfo_t *ESI;
00205     ESI = thread->running_eventset[cidx];
00206     // Get the indices of all events which have overflowed.
00207     unsigned ovfIdxs[BGPM_MAX_OVERFLOW_EVENTS];
00208     unsigned len = BGPM_MAX_OVERFLOW_EVENTS;
00209     
00210     retval = Bgpm_GetOverflowEventIndices( hEvtSet, ovfVector, ovfIdxs, &len );
00211     if ( retval < 0 ) {
00212 #ifdef DEBUG_BGPM
00213         printf ( "Error: ret value is %d for BGPM API function Bgpm_GetOverflowEventIndices.\n", 
00214                 retval ); 
00215 #endif
00216         return;
00217     }
00218     
00219     if ( thread == NULL ) {
00220         PAPIERROR( "thread == NULL in user_signal_handler!" );
00221         return;
00222     }
00223     
00224     if ( ESI == NULL ) {
00225         PAPIERROR( "ESI == NULL in user_signal_handler!");
00226         return;
00227     }
00228     
00229     if ( ESI->overflow.flags == 0 ) {
00230         PAPIERROR( "ESI->overflow.flags == 0 in user_signal_handler!");
00231         return;
00232     }
00233     
00234     for ( i = 0; i < len; i++ ) {
00235         uint64_t hProf;
00236         Bgpm_GetEventUser1( hEvtSet, ovfIdxs[i], &hProf );
00237         if ( hProf ) {
00238             overflow_bit ^= 1 << ovfIdxs[i];
00239             break;
00240         }
00241         
00242     }
00243     
00244     if ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) {
00245 #ifdef DEBUG_BGQ
00246         printf("OVERFLOW_SOFTWARE\n");
00247 #endif
00248         address1 = GET_OVERFLOW_ADDRESS( ctx );
00249         _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, NULL, 0, 0, &thread, cidx );
00250         return;
00251     }
00252     else if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
00253 #ifdef DEBUG_BGQ
00254         printf("OVERFLOW_HARDWARE\n");
00255 #endif
00256         address1 = GET_OVERFLOW_ADDRESS( ctx );
00257         _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, &isHardware, overflow_bit, 0, &thread, cidx );
00258     }
00259     else {
00260 #ifdef DEBUG_BGQ
00261         printf("OVERFLOW_NONE\n");
00262 #endif
00263         PAPIERROR( "ESI->overflow.flags is set to something other than PAPI_OVERFLOW_HARDWARE or PAPI_OVERFLOW_FORCE_SW (%#x)", thread->running_eventset[cidx]->overflow.flags);
00264     }
00265 }
00266 
00267 
00268 /*
00269  * Set Overflow
00270  *
00271  * This is commented out in BG/L/P - need to explore and complete...
00272  * However, with true 64-bit counters in BG/Q and all counters for PAPI
00273  * always starting from a true zero (we don't allow write...), the possibility
00274  * for overflow is remote at best...
00275  */
00276 int
00277 IOUNIT_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
00278 {
00279 #ifdef DEBUG_BGQ
00280     printf("BEGIN IOUNIT_set_overflow\n");
00281 #endif
00282     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ESI->ctl_state;
00283     int retval;
00284     int evt_idx;
00285         
00286     evt_idx = ESI->EventInfoArray[EventIndex].pos[0];
00287     SUBDBG( "Hardware counter %d (vs %d) used in overflow, threshold %d\n",
00288            evt_idx, EventIndex, threshold );
00289 #ifdef DEBUG_BGQ
00290     printf( "Hardware counter %d (vs %d) used in overflow, threshold %d\n",
00291            evt_idx, EventIndex, threshold );
00292 #endif
00293     /* If this counter isn't set to overflow, it's an error */
00294     if ( threshold == 0 ) {
00295         /* Remove the signal handler */
00296         retval = _papi_hwi_stop_signal( _IOunit_vector.cmp_info.hardware_intr_sig );
00297         if ( retval != PAPI_OK )
00298             return ( retval );
00299     }
00300     else {
00301         this_state->overflow = 1;
00302         this_state->overflow_count++;
00303         this_state->overflow_list[this_state->overflow_count-1].threshold = threshold;
00304         this_state->overflow_list[this_state->overflow_count-1].EventIndex = evt_idx;
00305         
00306 #ifdef DEBUG_BGQ
00307         printf( "IOUNIT_set_overflow: Enable the signal handler\n" );
00308 #endif
00309         /* Enable the signal handler */
00310         retval = _papi_hwi_start_signal( _IOunit_vector.cmp_info.hardware_intr_sig, 
00311                                         NEED_CONTEXT, 
00312                                         _IOunit_vector.cmp_info.CmpIdx );
00313         if ( retval != PAPI_OK )
00314             return ( retval );
00315 
00316         retval = _common_set_overflow_BGPM( this_state->EventGroup,
00317                                   this_state->overflow_list[this_state->overflow_count-1].EventIndex,
00318                                   this_state->overflow_list[this_state->overflow_count-1].threshold,
00319                                   user_signal_handler_IOUNIT );
00320         if ( retval < 0 ) return retval;
00321     }
00322     
00323     return ( PAPI_OK );
00324 }
00325 
00326 
00327 /* This function sets various options in the component
00328  * The valid codes being passed in are PAPI_SET_DEFDOM,
00329  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00330  */
00331 int
00332 IOUNIT_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00333 {
00334 #ifdef DEBUG_BGQ
00335     printf( "IOUNIT_ctl\n" );
00336 #endif
00337     
00338     ( void ) ctx;
00339     ( void ) code;
00340     ( void ) option;
00341     return ( PAPI_OK );
00342 }
00343 
00344 
00345 /*
00346  *
00347  */
00348 int
00349 IOUNIT_update_control_state( hwd_control_state_t * ptr,
00350                            NativeInfo_t * native, int count,
00351                            hwd_context_t * ctx )
00352 {
00353 #ifdef DEBUG_BGQ
00354     printf( "IOUNIT_update_control_state: count = %d\n", count );
00355 #endif
00356     ( void ) ctx;
00357     int retval, index, i, k;
00358     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00359     
00360     // Delete and re-create BGPM eventset
00361     retval = _common_deleteRecreate( &this_state->EventGroup );
00362     if ( retval < 0 ) return retval;
00363 
00364 #ifdef DEBUG_BGQ
00365     printf( "IOUNIT_update_control_state: EventGroup=%d, overflow = %d\n",
00366            this_state->EventGroup, this_state->overflow );
00367 #endif
00368         
00369     // otherwise, add the events to the eventset
00370     for ( i = 0; i < count; i++ ) {
00371         index = ( native[i].ni_event ) + OFFSET;
00372         
00373         native[i].ni_position = i;
00374 
00375 #ifdef DEBUG_BGQ
00376         printf("IOUNIT_update_control_state: ADD event: i = %d, index = %d\n", i, index );
00377 #endif
00378                 
00379         /* Add events to the BGPM eventGroup */
00380         retval = Bgpm_AddEvent( this_state->EventGroup, index );
00381         retval = _check_BGPM_error( retval, "Bgpm_AddEvent" );
00382         if ( retval < 0 ) return retval;
00383     }
00384 
00385     // since update_control_state trashes overflow settings, this puts things
00386     // back into balance for BGPM
00387     if ( 1 == this_state->overflow ) {
00388         for ( k = 0; k < this_state->overflow_count; k++ ) {
00389             retval = _common_set_overflow_BGPM( this_state->EventGroup,
00390                                       this_state->overflow_list[k].EventIndex,
00391                                       this_state->overflow_list[k].threshold,
00392                                       user_signal_handler_IOUNIT );
00393             if ( retval < 0 ) return retval;
00394         }
00395     }
00396 
00397     return ( PAPI_OK );
00398 }
00399 
00400 
00401 /*
00402  * This function has to set the bits needed to count different domains
00403  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00404  * By default return PAPI_EINVAL if none of those are specified
00405  * and PAPI_OK with success
00406  * PAPI_DOM_USER is only user context is counted
00407  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00408  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00409  * PAPI_DOM_ALL   is all of the domains
00410  */
00411 int
00412 IOUNIT_set_domain( hwd_control_state_t * cntrl, int domain )
00413 {
00414 #ifdef DEBUG_BGQ
00415     printf( "IOUNIT_set_domain\n" );
00416 #endif
00417     int found = 0;
00418     ( void ) cntrl;
00419 
00420     if ( PAPI_DOM_USER & domain )
00421         found = 1;
00422 
00423     if ( PAPI_DOM_KERNEL & domain )
00424         found = 1;
00425 
00426     if ( PAPI_DOM_OTHER & domain )
00427         found = 1;
00428 
00429     if ( !found )
00430         return ( PAPI_EINVAL );
00431 
00432     return ( PAPI_OK );
00433 }
00434 
00435 
00436 /*
00437  *
00438  */
00439 int
00440 IOUNIT_reset( hwd_context_t * ctx, hwd_control_state_t * ptr )
00441 {
00442 #ifdef DEBUG_BGQ
00443     printf( "IOUNIT_reset\n" );
00444 #endif
00445     ( void ) ctx;
00446     int retval;
00447     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00448 
00449     /* we can't simply call Bgpm_Reset() since PAPI doesn't have the 
00450      restriction that an EventSet has to be stopped before resetting is
00451      possible. However, BGPM does have this restriction. 
00452      Hence we need to stop, reset and start */
00453     retval = Bgpm_Stop( this_state->EventGroup );
00454     retval = _check_BGPM_error( retval, "Bgpm_Stop" );
00455     if ( retval < 0 ) return retval;
00456 
00457     retval = Bgpm_ResetStart( this_state->EventGroup );
00458     retval = _check_BGPM_error( retval, "Bgpm_ResetStart" );
00459     if ( retval < 0 ) return retval;
00460 
00461     return ( PAPI_OK );
00462 }
00463 
00464 
00465 /*
00466  * PAPI Cleanup Eventset
00467  *
00468  * Destroy and re-create the BGPM / IOunit EventSet
00469  */
00470 int
00471 IOUNIT_cleanup_eventset( hwd_control_state_t * ctrl )
00472 {
00473 #ifdef DEBUG_BGQ
00474     printf( "IOUNIT_cleanup_eventset\n" );
00475 #endif
00476     int retval;
00477 
00478     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ctrl;
00479         
00480     // create a new empty bgpm eventset
00481     // reason: bgpm doesn't permit to remove events from an eventset; 
00482     // hence we delete the old eventset and create a new one
00483     retval = _common_deleteRecreate( &this_state->EventGroup ); // HJ try to use delete() only
00484     if ( retval < 0 ) return retval;
00485 
00486     // set overflow flag to OFF (0)
00487     this_state->overflow = 0;
00488     this_state->overflow_count = 0;
00489     
00490     return ( PAPI_OK );
00491 }
00492 
00493 
00494 /*
00495  * Native Event functions
00496  */
00497 int
00498 IOUNIT_ntv_enum_events( unsigned int *EventCode, int modifier )
00499 {
00500 #ifdef DEBUG_BGQ
00501     //printf( "IOUNIT_ntv_enum_events\n" );
00502 #endif
00503 
00504     switch ( modifier ) {
00505     case PAPI_ENUM_FIRST:
00506         *EventCode = 0;
00507 
00508         return ( PAPI_OK );
00509         break;
00510 
00511     case PAPI_ENUM_EVENTS:
00512     {
00513         int index = ( *EventCode ) + OFFSET;
00514 
00515         if ( index < IOUNIT_MAX_COUNTERS ) {
00516             *EventCode = *EventCode + 1;
00517             return ( PAPI_OK );
00518         } else
00519             return ( PAPI_ENOEVNT );
00520 
00521         break;
00522     }
00523     default:
00524         return ( PAPI_EINVAL );
00525     }
00526     return ( PAPI_EINVAL );
00527 }
00528 
00529 
00530 /*
00531  *
00532  */
00533 int
00534 IOUNIT_ntv_name_to_code( char *name, unsigned int *event_code )
00535 {
00536 #ifdef DEBUG_BGQ
00537     printf( "IOUNIT_ntv_name_to_code\n" );
00538 #endif
00539     int ret;
00540     
00541     /* Return event id matching a given event label string */
00542     ret = Bgpm_GetEventIdFromLabel ( name );
00543     
00544     if ( ret <= 0 ) {
00545 #ifdef DEBUG_BGPM
00546         printf ("Error: ret value is %d for BGPM API function '%s'.\n",
00547                 ret, "Bgpm_GetEventIdFromLabel" );
00548 #endif
00549         return PAPI_ENOEVNT;
00550     }
00551     else if ( ret < OFFSET || ret > IOUNIT_MAX_COUNTERS ) // not an IOUnit event
00552         return PAPI_ENOEVNT;
00553     else
00554         *event_code = ( ret - OFFSET ) ;
00555     
00556     return PAPI_OK;
00557 }
00558 
00559 
00560 /*
00561  *
00562  */
00563 int
00564 IOUNIT_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00565 {
00566 #ifdef DEBUG_BGQ
00567     //printf( "IOUNIT_ntv_code_to_name\n" );
00568 #endif
00569     int index;
00570     
00571     index = ( EventCode ) + OFFSET;
00572 
00573     if ( index >= MAX_COUNTERS )
00574         return PAPI_ENOEVNT;
00575 
00576     strncpy( name, Bgpm_GetEventIdLabel( index ), len );
00577     
00578     if ( name == NULL ) {
00579 #ifdef DEBUG_BGPM
00580         printf ("Error: ret value is NULL for BGPM API function Bgpm_GetEventIdLabel.\n" );
00581 #endif
00582         return PAPI_ENOEVNT;
00583     }
00584     
00585     return ( PAPI_OK );
00586 }
00587 
00588 
00589 /*
00590  *
00591  */
00592 int
00593 IOUNIT_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00594 {
00595 #ifdef DEBUG_BGQ
00596     //printf( "IOUNIT_ntv_code_to_descr\n" );
00597 #endif  
00598     int retval, index;
00599     
00600     index = ( EventCode ) + OFFSET;
00601     
00602     retval = Bgpm_GetLongDesc( index, name, &len );
00603     retval = _check_BGPM_error( retval, "Bgpm_GetLongDesc" );                        
00604     if ( retval < 0 ) return retval;
00605 
00606     return ( PAPI_OK );
00607 }
00608 
00609 
00610 /*
00611  *
00612  */
00613 int
00614 IOUNIT_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
00615 {
00616 #ifdef DEBUG_BGQ
00617     printf( "IOUNIT_ntv_code_to_bits\n" );
00618 #endif
00619     ( void ) EventCode;
00620     ( void ) bits;
00621     return ( PAPI_OK );
00622 }
00623 
00624 
00625 /*
00626  *
00627  */
00628 papi_vector_t _IOunit_vector = {
00629     .cmp_info = {
00630                  /* default component information (unspecified values are initialized to 0) */
00631                  .name = "bgpm/IOUnit",
00632                  .short_name = "IOUnit",
00633                  .description = "Blue Gene/Q IOUnit component",
00634                  .num_cntrs = IOUNIT_MAX_COUNTERS,
00635                  .num_mpx_cntrs = IOUNIT_MAX_COUNTERS,
00636                  .default_domain = PAPI_DOM_USER,
00637                  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00638                  .default_granularity = PAPI_GRN_THR,
00639                  .available_granularities = PAPI_GRN_THR,
00640 
00641                  .hardware_intr_sig = PAPI_INT_SIGNAL,
00642                  .hardware_intr = 1,
00643         
00644                  .kernel_multiplex = 0,
00645 
00646                  /* component specific cmp_info initializations */
00647                  .fast_real_timer = 0,
00648                  .fast_virtual_timer = 0,
00649                  .attach = 0,
00650                  .attach_must_ptrace = 0,
00651                  }
00652     ,
00653 
00654     /* sizes of framework-opaque component-private structures */
00655     .size = {
00656              .context = sizeof ( IOUNIT_context_t ),
00657              .control_state = sizeof ( IOUNIT_control_state_t ),
00658              .reg_value = sizeof ( IOUNIT_register_t ),
00659              .reg_alloc = sizeof ( IOUNIT_reg_alloc_t ),
00660              }
00661     ,
00662     /* function pointers in this component */
00663     .init_thread = IOUNIT_init_thread,
00664     .init_component = IOUNIT_init_component,
00665     .init_control_state = IOUNIT_init_control_state,
00666     .start = IOUNIT_start,
00667     .stop = IOUNIT_stop,
00668     .read = IOUNIT_read,
00669     .shutdown_thread = IOUNIT_shutdown_thread,
00670     .set_overflow = IOUNIT_set_overflow,
00671     .cleanup_eventset = IOUNIT_cleanup_eventset,
00672     .ctl = IOUNIT_ctl,
00673     
00674     .update_control_state = IOUNIT_update_control_state,
00675     .set_domain = IOUNIT_set_domain,
00676     .reset = IOUNIT_reset,
00677 
00678     .ntv_name_to_code = IOUNIT_ntv_name_to_code,
00679     .ntv_enum_events = IOUNIT_ntv_enum_events,
00680     .ntv_code_to_name = IOUNIT_ntv_code_to_name,
00681     .ntv_code_to_descr = IOUNIT_ntv_code_to_descr,
00682     .ntv_code_to_bits = IOUNIT_ntv_code_to_bits
00683 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines