1/*
2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3 *
4 * This software may be freely used, copied, modified, and distributed
5 * provided that the above copyright notice is preserved in all copies of the
6 * software.
7 */
8
9/* -*-C-*-
10 *
11 * $Revision: 1.3 $
12 *     $Date: 1999/11/01 13:31:39 $
13 *
14 *
15 *   Project: ANGEL
16 *
17 *     Title: Parameter negotiation utility functions
18 */
19
20#include "params.h"
21
22#include "angel_endian.h"
23#include "logging.h"
24
25
26/*
27 * Function: Angel_FindParam
28 *  Purpose: find the value of a given parameter from a config.
29 *
30 * see params.h for details
31 */
32bool Angel_FindParam( ADP_Parameter          type,
33                      const ParameterConfig *config,
34                      unsigned int          *value )
35{
36    unsigned int i;
37
38    for ( i = 0; i < config->num_parameters; ++i )
39       if ( config->param[i].type == type )
40       {
41           *value = config->param[i].value;
42           return TRUE;
43       }
44
45    return FALSE;
46}
47
48
49#if !defined(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
50
51ParameterList *Angel_FindParamList( const ParameterOptions *options,
52                                    ADP_Parameter           type )
53{
54    unsigned int i;
55
56    for ( i = 0; i < options->num_param_lists; ++i )
57       if ( options->param_list[i].type == type )
58          return &options->param_list[i];
59
60    return NULL;
61}
62
63
64#if defined(TARGET) || defined(TEST_PARAMS)
65/*
66 * Function: Angel_MatchParams
67 *  Purpose: find a configuration from the requested options which is
68 *           the best match from the supported options.
69 *
70 * see params.h for details
71 */
72const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
73                                          const ParameterOptions *supported )
74{
75    static Parameter        chosen_params[AP_NUM_PARAMS];
76    static ParameterConfig  chosen_config = {
77        AP_NUM_PARAMS,
78        chosen_params
79    };
80    unsigned int i;
81
82    ASSERT( requested != NULL, "requested is NULL" );
83    ASSERT( requested != NULL, "requested is NULL" );
84    ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" );
85
86    if ( requested->num_param_lists > supported->num_param_lists )
87    {
88        WARN( "req_num exceeds supp_num" );
89        return NULL;
90    }
91
92    for ( i = 0; i < requested->num_param_lists; ++i )
93    {
94        bool           match;
95        unsigned int   j;
96
97        const ParameterList *req_list = &requested->param_list[i];
98        ADP_Parameter        req_type = req_list->type;
99        const ParameterList *sup_list = Angel_FindParamList(
100                                            supported, req_type );
101
102        if ( sup_list == NULL )
103        {
104#ifdef ASSERTIONS_ENABLED
105            __rt_warning( "option %x not supported\n", req_type );
106#endif
107            return NULL;
108        }
109
110        for ( j = 0, match = FALSE;
111              (j < req_list->num_options) && !match;
112              ++j
113            )
114        {
115            unsigned int k;
116
117            for ( k = 0;
118                  (k < sup_list->num_options) && !match;
119                  ++k
120                )
121            {
122                if ( req_list->option[j] == sup_list->option[k] )
123                {
124#ifdef DEBUG
125                    __rt_info( "chose value %d for option %x\n",
126                               req_list->option[j], req_type );
127#endif
128                    match = TRUE;
129                    chosen_config.param[i].type = req_type;
130                    chosen_config.param[i].value = req_list->option[j];
131                }
132            }
133        }
134
135        if ( !match )
136        {
137#ifdef ASSERTIONS_ENABLED
138            __rt_warning( "no match found for option %x\n", req_type );
139#endif
140            return NULL;
141        }
142    }
143
144    chosen_config.num_parameters = i;
145    INFO( "match succeeded" );
146    return &chosen_config;
147}
148#endif /* defined(TARGET) || defined(TEST_PARAMS) */
149
150
151#if !defined(TARGET) || defined(TEST_PARAMS)
152/*
153 * Function: Angel_StoreParam
154 *  Purpose: store the value of a given parameter to a config.
155 *
156 * see params.h for details
157 */
158bool Angel_StoreParam( ParameterConfig *config,
159                       ADP_Parameter    type,
160                       unsigned int     value )
161{
162    unsigned int i;
163
164    for ( i = 0; i < config->num_parameters; ++i )
165       if ( config->param[i].type == type )
166       {
167           config->param[i].value = value;
168           return TRUE;
169       }
170
171    return FALSE;
172}
173#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
174
175
176#if defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
177/*
178 * Function: Angel_BuildParamConfigMessage
179 *  Purpose: write a parameter config to a buffer in ADP format.
180 *
181 * see params.h for details
182 */
183unsigned int Angel_BuildParamConfigMessage( unsigned char         *buffer,
184                                            const ParameterConfig *config )
185{
186    unsigned char *start = buffer;
187    unsigned int i;
188
189    PUT32LE( buffer, config->num_parameters );
190    buffer += sizeof( word );
191
192    for ( i = 0; i < config->num_parameters; ++i )
193    {
194        PUT32LE( buffer, config->param[i].type );
195        buffer += sizeof( word );
196        PUT32LE( buffer, config->param[i].value );
197        buffer += sizeof( word );
198    }
199
200    return (buffer - start);
201}
202#endif /* defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
203
204
205#if !defined(TARGET) || defined(TEST_PARAMS)
206/*
207 * Function: Angel_BuildParamOptionsMessage
208 *  Purpose: write a parameter Options to a buffer in ADP format.
209 *
210 * see params.h for details
211 */
212unsigned int Angel_BuildParamOptionsMessage( unsigned char          *buffer,
213                                             const ParameterOptions *options )
214{
215    unsigned char *start = buffer;
216    unsigned int i, j;
217
218    PUT32LE( buffer, options->num_param_lists );
219    buffer += sizeof( word );
220
221    for ( i = 0; i < options->num_param_lists; ++i )
222    {
223        PUT32LE( buffer, options->param_list[i].type );
224        buffer += sizeof( word );
225        PUT32LE( buffer, options->param_list[i].num_options );
226        buffer += sizeof( word );
227        for ( j = 0; j < options->param_list[i].num_options; ++j )
228        {
229            PUT32LE( buffer, options->param_list[i].option[j] );
230            buffer += sizeof( word );
231        }
232    }
233
234    return (buffer - start);
235}
236#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
237
238
239#if !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
240/*
241 * Function: Angel_ReadParamConfigMessage
242 *  Purpose: read a parameter config from a buffer where it is in ADP format.
243 *
244 * see params.h for details
245 */
246bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
247                                   ParameterConfig     *config )
248{
249    unsigned int word;
250    unsigned int i;
251
252    word = GET32LE( buffer );
253    buffer += sizeof( word );
254    if ( word > config->num_parameters )
255    {
256        WARN( "not enough space" );
257        return FALSE;
258    }
259    config->num_parameters = word;
260
261    for ( i = 0; i < config->num_parameters; ++i )
262    {
263        config->param[i].type = (ADP_Parameter)GET32LE( buffer );
264        buffer += sizeof( word );
265        config->param[i].value = GET32LE( buffer );
266        buffer += sizeof( word );
267    }
268
269    return TRUE;
270}
271#endif /* !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
272
273
274#if defined(TARGET) || defined(TEST_PARAMS)
275/*
276 * Function: Angel_ReadParamOptionsMessage
277 *  Purpose: read a parameter options block from a buffer
278 *             where it is in ADP format.
279 *
280 * see params.h for details
281 */
282bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
283                                    ParameterOptions    *options )
284{
285    unsigned int word;
286    unsigned int i, j;
287
288    word = GET32LE( buffer );
289    buffer += sizeof( word );
290    if ( word > options->num_param_lists )
291    {
292        WARN( "not enough space" );
293        return FALSE;
294    }
295    options->num_param_lists = word;
296
297    for ( i = 0; i < options->num_param_lists; ++i )
298    {
299        ParameterList *list = &options->param_list[i];
300
301        list->type = (ADP_Parameter)GET32LE( buffer );
302        buffer += sizeof( word );
303        word = GET32LE( buffer );
304        buffer += sizeof( word );
305        if ( word > list->num_options )
306        {
307            WARN( "not enough list space" );
308            return FALSE;
309        }
310        list->num_options = word;
311
312        for ( j = 0; j < list->num_options; ++j )
313        {
314            list->option[j] = GET32LE( buffer );
315            buffer += sizeof( word );
316        }
317    }
318
319    return TRUE;
320}
321#endif /* defined(TARGET) || defined(TEST_PARAMS) */
322
323#endif /* !define(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 */
324
325/* EOF params.c */
326