blob: 55d9eb210efd78a7353a6c4d050ba168d5d4d15d [file] [log] [blame]
/*
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
*
* This software may be freely used, copied, modified, and distributed
* provided that the above copyright notice is preserved in all copies of the
* software.
*/
/* -*-C-*-
*
* $Revision$
* $Date$
*
*
* Project: ANGEL
*
* Title: Parameter negotiation utility functions
*/
#include "params.h"
#include "angel_endian.h"
#include "logging.h"
/*
* Function: Angel_FindParam
* Purpose: find the value of a given parameter from a config.
*
* see params.h for details
*/
bool Angel_FindParam( ADP_Parameter type,
const ParameterConfig *config,
unsigned int *value )
{
unsigned int i;
for ( i = 0; i < config->num_parameters; ++i )
if ( config->param[i].type == type )
{
*value = config->param[i].value;
return TRUE;
}
return FALSE;
}
#if !defined(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
ParameterList *Angel_FindParamList( const ParameterOptions *options,
ADP_Parameter type )
{
unsigned int i;
for ( i = 0; i < options->num_param_lists; ++i )
if ( options->param_list[i].type == type )
return &options->param_list[i];
return NULL;
}
#if defined(TARGET) || defined(TEST_PARAMS)
/*
* Function: Angel_MatchParams
* Purpose: find a configuration from the requested options which is
* the best match from the supported options.
*
* see params.h for details
*/
const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
const ParameterOptions *supported )
{
static Parameter chosen_params[AP_NUM_PARAMS];
static ParameterConfig chosen_config = {
AP_NUM_PARAMS,
chosen_params
};
unsigned int i;
ASSERT( requested != NULL, "requested is NULL" );
ASSERT( requested != NULL, "requested is NULL" );
ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" );
if ( requested->num_param_lists > supported->num_param_lists )
{
WARN( "req_num exceeds supp_num" );
return NULL;
}
for ( i = 0; i < requested->num_param_lists; ++i )
{
bool match;
unsigned int j;
const ParameterList *req_list = &requested->param_list[i];
ADP_Parameter req_type = req_list->type;
const ParameterList *sup_list = Angel_FindParamList(
supported, req_type );
if ( sup_list == NULL )
{
#ifdef ASSERTIONS_ENABLED
__rt_warning( "option %x not supported\n", req_type );
#endif
return NULL;
}
for ( j = 0, match = FALSE;
(j < req_list->num_options) && !match;
++j
)
{
unsigned int k;
for ( k = 0;
(k < sup_list->num_options) && !match;
++k
)
{
if ( req_list->option[j] == sup_list->option[k] )
{
#ifdef DEBUG
__rt_info( "chose value %d for option %x\n",
req_list->option[j], req_type );
#endif
match = TRUE;
chosen_config.param[i].type = req_type;
chosen_config.param[i].value = req_list->option[j];
}
}
}
if ( !match )
{
#ifdef ASSERTIONS_ENABLED
__rt_warning( "no match found for option %x\n", req_type );
#endif
return NULL;
}
}
chosen_config.num_parameters = i;
INFO( "match succeeded" );
return &chosen_config;
}
#endif /* defined(TARGET) || defined(TEST_PARAMS) */
#if !defined(TARGET) || defined(TEST_PARAMS)
/*
* Function: Angel_StoreParam
* Purpose: store the value of a given parameter to a config.
*
* see params.h for details
*/
bool Angel_StoreParam( ParameterConfig *config,
ADP_Parameter type,
unsigned int value )
{
unsigned int i;
for ( i = 0; i < config->num_parameters; ++i )
if ( config->param[i].type == type )
{
config->param[i].value = value;
return TRUE;
}
return FALSE;
}
#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
#if defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
/*
* Function: Angel_BuildParamConfigMessage
* Purpose: write a parameter config to a buffer in ADP format.
*
* see params.h for details
*/
unsigned int Angel_BuildParamConfigMessage( unsigned char *buffer,
const ParameterConfig *config )
{
unsigned char *start = buffer;
unsigned int i;
PUT32LE( buffer, config->num_parameters );
buffer += sizeof( word );
for ( i = 0; i < config->num_parameters; ++i )
{
PUT32LE( buffer, config->param[i].type );
buffer += sizeof( word );
PUT32LE( buffer, config->param[i].value );
buffer += sizeof( word );
}
return (buffer - start);
}
#endif /* defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
#if !defined(TARGET) || defined(TEST_PARAMS)
/*
* Function: Angel_BuildParamOptionsMessage
* Purpose: write a parameter Options to a buffer in ADP format.
*
* see params.h for details
*/
unsigned int Angel_BuildParamOptionsMessage( unsigned char *buffer,
const ParameterOptions *options )
{
unsigned char *start = buffer;
unsigned int i, j;
PUT32LE( buffer, options->num_param_lists );
buffer += sizeof( word );
for ( i = 0; i < options->num_param_lists; ++i )
{
PUT32LE( buffer, options->param_list[i].type );
buffer += sizeof( word );
PUT32LE( buffer, options->param_list[i].num_options );
buffer += sizeof( word );
for ( j = 0; j < options->param_list[i].num_options; ++j )
{
PUT32LE( buffer, options->param_list[i].option[j] );
buffer += sizeof( word );
}
}
return (buffer - start);
}
#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
#if !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
/*
* Function: Angel_ReadParamConfigMessage
* Purpose: read a parameter config from a buffer where it is in ADP format.
*
* see params.h for details
*/
bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
ParameterConfig *config )
{
unsigned int word;
unsigned int i;
word = GET32LE( buffer );
buffer += sizeof( word );
if ( word > config->num_parameters )
{
WARN( "not enough space" );
return FALSE;
}
config->num_parameters = word;
for ( i = 0; i < config->num_parameters; ++i )
{
config->param[i].type = (ADP_Parameter)GET32LE( buffer );
buffer += sizeof( word );
config->param[i].value = GET32LE( buffer );
buffer += sizeof( word );
}
return TRUE;
}
#endif /* !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
#if defined(TARGET) || defined(TEST_PARAMS)
/*
* Function: Angel_ReadParamOptionsMessage
* Purpose: read a parameter options block from a buffer
* where it is in ADP format.
*
* see params.h for details
*/
bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
ParameterOptions *options )
{
unsigned int word;
unsigned int i, j;
word = GET32LE( buffer );
buffer += sizeof( word );
if ( word > options->num_param_lists )
{
WARN( "not enough space" );
return FALSE;
}
options->num_param_lists = word;
for ( i = 0; i < options->num_param_lists; ++i )
{
ParameterList *list = &options->param_list[i];
list->type = (ADP_Parameter)GET32LE( buffer );
buffer += sizeof( word );
word = GET32LE( buffer );
buffer += sizeof( word );
if ( word > list->num_options )
{
WARN( "not enough list space" );
return FALSE;
}
list->num_options = word;
for ( j = 0; j < list->num_options; ++j )
{
list->option[j] = GET32LE( buffer );
buffer += sizeof( word );
}
}
return TRUE;
}
#endif /* defined(TARGET) || defined(TEST_PARAMS) */
#endif /* !define(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 */
/* EOF params.c */