Henk de Groot | 68c0bdf | 2009-09-27 11:12:52 +0200 | [diff] [blame] | 1 | |
| 2 | // vim:tw=110:ts=4: |
| 3 | /************************************************************************************************************ |
| 4 | * |
| 5 | * FILE : mmd.c |
| 6 | * |
| 7 | * DATE : $Date: 2004/07/23 11:57:45 $ $Revision: 1.4 $ |
| 8 | * Original: 2004/05/28 14:05:35 Revision: 1.32 Tag: hcf7_t20040602_01 |
| 9 | * Original: 2004/05/13 15:31:45 Revision: 1.30 Tag: hcf7_t7_20040513_01 |
| 10 | * Original: 2004/04/15 09:24:42 Revision: 1.25 Tag: hcf7_t7_20040415_01 |
| 11 | * Original: 2004/04/08 15:18:17 Revision: 1.24 Tag: t7_20040413_01 |
| 12 | * Original: 2004/04/01 15:32:55 Revision: 1.22 Tag: t7_20040401_01 |
| 13 | * Original: 2004/03/10 15:39:28 Revision: 1.18 Tag: t20040310_01 |
| 14 | * Original: 2004/03/03 14:10:12 Revision: 1.16 Tag: t20040304_01 |
| 15 | * Original: 2004/03/02 09:27:12 Revision: 1.14 Tag: t20040302_03 |
| 16 | * Original: 2004/02/24 13:00:29 Revision: 1.12 Tag: t20040224_01 |
| 17 | * Original: 2004/01/30 09:59:33 Revision: 1.11 Tag: t20040219_01 |
| 18 | * |
| 19 | * AUTHOR : Nico Valster |
| 20 | * |
| 21 | * DESC : Common routines for HCF, MSF, UIL as well as USF sources |
| 22 | * |
| 23 | * Note: relative to Asserts, the following can be observed: |
| 24 | * Since the IFB is not known inside the routine, the macro HCFASSERT is replaced with MDDASSERT. |
| 25 | * Also the line number reported in the assert is raised by FILE_NAME_OFFSET (20000) to discriminate the |
| 26 | * MMD Asserts from HCF and DHF asserts. |
| 27 | * |
| 28 | *************************************************************************************************************** |
| 29 | * |
| 30 | * |
| 31 | * SOFTWARE LICENSE |
| 32 | * |
| 33 | * This software is provided subject to the following terms and conditions, |
| 34 | * which you should read carefully before using the software. Using this |
| 35 | * software indicates your acceptance of these terms and conditions. If you do |
| 36 | * not agree with these terms and conditions, do not use the software. |
| 37 | * |
| 38 | * COPYRIGHT © 2001 - 2004 by Agere Systems Inc. All Rights Reserved |
| 39 | * All rights reserved. |
| 40 | * |
| 41 | * Redistribution and use in source or binary forms, with or without |
| 42 | * modifications, are permitted provided that the following conditions are met: |
| 43 | * |
| 44 | * . Redistributions of source code must retain the above copyright notice, this |
| 45 | * list of conditions and the following Disclaimer as comments in the code as |
| 46 | * well as in the documentation and/or other materials provided with the |
| 47 | * distribution. |
| 48 | * |
| 49 | * . Redistributions in binary form must reproduce the above copyright notice, |
| 50 | * this list of conditions and the following Disclaimer in the documentation |
| 51 | * and/or other materials provided with the distribution. |
| 52 | * |
| 53 | * . Neither the name of Agere Systems Inc. nor the names of the contributors |
| 54 | * may be used to endorse or promote products derived from this software |
| 55 | * without specific prior written permission. |
| 56 | * |
| 57 | * Disclaimer |
| 58 | * |
| 59 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| 60 | * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF |
| 61 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY |
| 62 | * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN |
| 63 | * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY |
| 64 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 65 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 66 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 67 | * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT |
| 68 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| 69 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| 70 | * DAMAGE. |
| 71 | * |
| 72 | * |
| 73 | **************************************************************************************************************/ |
| 74 | |
| 75 | #include "hcf.h" // Needed as long as we do not really sort out the mess |
| 76 | #include "hcfdef.h" // get CNV_LITTLE_TO_SHORT |
| 77 | #include "mmd.h" // MoreModularDriver common include file |
| 78 | |
| 79 | //to distinguish DHF from HCF asserts by means of line number |
| 80 | #undef FILE_NAME_OFFSET |
| 81 | #define FILE_NAME_OFFSET DHF_FILE_NAME_OFFSET |
| 82 | |
| 83 | |
| 84 | /************************************************************************************************************* |
| 85 | * |
| 86 | *.MODULE CFG_RANGE_SPEC_STRCT* mmd_check_comp( CFG_RANGES_STRCT *actp, CFG_SUP_RANGE_STRCT *supp ) |
| 87 | *.PURPOSE Checks compatibility between an actor and a supplier. |
| 88 | * |
| 89 | *.ARGUMENTS |
| 90 | * actp |
| 91 | * supp |
| 92 | * |
| 93 | *.RETURNS |
| 94 | * NULL incompatible |
| 95 | * <>NULL pointer to matching CFG_RANGE_SPEC_STRCT substructure in actor-structure matching the supplier |
| 96 | * |
| 97 | *.NARRATIVE |
| 98 | * |
| 99 | * Parameters: |
| 100 | * actp address of the actor specification |
| 101 | * supp address of the supplier specification |
| 102 | * |
| 103 | * Description: mmd_check_comp is a support routine to check the compatibility between an actor and a |
| 104 | * supplier. mmd_check_comp is independent of the endianess of the actp and supp structures. This is |
| 105 | * achieved by checking the "bottom" or "role" fields of these structures. Since these fields are restricted |
| 106 | * to a limited range, comparing the contents to a value with a known endian-ess gives a clue to their actual |
| 107 | * endianess. |
| 108 | * |
| 109 | *.DIAGRAM |
| 110 | *1a: The role-field of the actor structure has a known non-zero, not "byte symmetric" value (namely |
| 111 | * COMP_ROLE_ACT or 0x0001), so if and only the contents of this field matches COMP_ROLE_ACT (in Native |
| 112 | * Endian format), the actor structure is Native Endian. |
| 113 | *2a: Since the role-field of the supplier structure is 0x0000, the test as used for the actor does not work |
| 114 | * for a supplier. A supplier has always exactly 1 variant,top,bottom record with (officially, but see the |
| 115 | * note below) each of these 3 values in the range 1 through 99, so one byte of the word value of variant, |
| 116 | * top and bottom words is 0x00 and the other byte is non-zero. Whether the lowest address byte or the |
| 117 | * highest address byte is non-zero depends on the Endianess of the LTV. If and only if the word value of |
| 118 | * bottom is less than 0x0100, the supplier is Native Endian. |
| 119 | * NOTE: the variant field of the supplier structure can not be used for the Endian Detection Algorithm, |
| 120 | * because a a zero-valued variant has been used as Controlled Deployment indication in the past. |
| 121 | * Note: An actor may have multiple sets of variant,top,bottom records, including dummy sets with variant, |
| 122 | * top and bottom fields with a zero-value. As a consequence the endianess of the actor can not be determined |
| 123 | * based on its variant,top,bottom values. |
| 124 | * |
| 125 | * Note: the L and T field of the structures are always in Native Endian format, so you can not draw |
| 126 | * conclusions concerning the Endianess of the structure based on these two fields. |
| 127 | * |
| 128 | *1b/2b |
| 129 | * The only purpose of the CFG_RANGE_SPEC_BYTE_STRCT is to give easy access to the non-zero byte of the word |
| 130 | * value of variant, top and bottom. The variables sup_endian and act_endian are used for the supplier and |
| 131 | * actor structure respectively. These variables must be 0 when the structure has LE format and 1 if the |
| 132 | * structure has BE format. This can be phrased as: |
| 133 | * the variable is false (i.e 0x0000) if either |
| 134 | * (the platform is LE and the LTV is the same as the platform) |
| 135 | * or |
| 136 | * (the platform is BE and the LTV differs from the platform). |
| 137 | * the variable is true (i.e 0x0001) if either |
| 138 | * (the platform is BE and the LTV is the same as the platform) |
| 139 | * or |
| 140 | * (the platform is LE and the LTV differs from the platform). |
| 141 | * |
| 142 | * Alternatively this can be phrased as: |
| 143 | * if the platform is LE |
| 144 | * if the LTV is LE (i.e the same as the platform), then the variable = 0 |
| 145 | * else (the LTV is BE (i.e. different from the platform) ), then the variable = 1 |
| 146 | * if the platform is BE |
| 147 | * if the LTV is BE (i.e the same as the platform), then the variable = 1 |
| 148 | * else (the LTV is LE (i.e. different from the platform) ), then the variable = 0 |
| 149 | * |
| 150 | * This is implemented as: |
| 151 | * #if HCF_BIG_ENDIAN == 0 //platform is LE |
| 152 | * sup/act_endian becomes reverse of structure-endianess as determined in 1a/1b |
| 153 | * #endif |
| 154 | *6: Each of the actor variant-bottom-top records is checked against the (single) supplier variant-bottom-top |
| 155 | * range till either an acceptable match is found or all actor records are tried. As explained above, due to |
| 156 | * the limited ranges of these values, checking a byte is acceptable and suitable. |
| 157 | *8: depending on whether a match was found or not (as reflected by the value of the control variable of the |
| 158 | * for loop), the NULL pointer or a pointer to the matching Number/Bottom/Top record of the Actor structure |
| 159 | * is returned. |
| 160 | * As an additional safety, checking the supplier length protects against invalid Supplier structures, which |
| 161 | * may be caused by failing hcf_get_info (in which case the len-field is zero). Note that the contraption |
| 162 | * "supp->len != sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1" |
| 163 | * did turn out not to work for a compiler which padded the structure definition. |
| 164 | * |
| 165 | * Note: when consulting references like DesignNotes and Architecture specifications there is a confusing use |
| 166 | * of the notions number and variant. This resulted in an inconsistent use in the HCF nomenclature as well. |
| 167 | * This makes the logic hard to follow and one has to be very much aware of the context when walking through |
| 168 | * the code. |
| 169 | * NOTE: The Endian Detection Algorithm places limitations on future extensions of the fields, i.e. they should |
| 170 | * stay within the currently defined boundaries of 1 through 99 (although 1 through 255) would work as well |
| 171 | * and there should never be used a zero value for the bottom of a valid supplier. |
| 172 | * Note: relative to Asserts, the following can be observed: |
| 173 | * 1: Supplier variant 0x0000 has been used for Controlled Deployment |
| 174 | * 2: An actor may have one or more variant record specifications with a top of zero and a non-zero bottom |
| 175 | * to override the HCF default support of a particular variant by the MSF programmer via hcfcfg.h |
| 176 | * 3: An actor range can be specified as all zeros, e.g. as padding in the automatically generated firmware |
| 177 | * image files. |
| 178 | *.ENDDOC END DOCUMENTATION |
| 179 | *************************************************************************************************************/ |
| 180 | CFG_RANGE_SPEC_STRCT* |
| 181 | mmd_check_comp( CFG_RANGES_STRCT *actp, CFG_SUP_RANGE_STRCT *supp ) |
| 182 | { |
| 183 | |
| 184 | CFG_RANGE_SPEC_BYTE_STRCT *actq = (CFG_RANGE_SPEC_BYTE_STRCT*)actp->var_rec; |
| 185 | CFG_RANGE_SPEC_BYTE_STRCT *supq = (CFG_RANGE_SPEC_BYTE_STRCT*)&(supp->variant); |
| 186 | hcf_16 i; |
| 187 | int act_endian; //actor endian flag |
| 188 | int sup_endian; //supplier endian flag |
| 189 | |
| 190 | act_endian = actp->role == COMP_ROLE_ACT; //true if native endian /* 1a */ |
| 191 | sup_endian = supp->bottom < 0x0100; //true if native endian /* 2a */ |
| 192 | |
| 193 | #if HCF_ASSERT |
| 194 | MMDASSERT( supp->len == 6, supp->len ) |
| 195 | MMDASSERT( actp->len >= 6 && actp->len%3 == 0, actp->len ) |
| 196 | |
| 197 | if ( act_endian ) { //native endian |
| 198 | MMDASSERT( actp->role == COMP_ROLE_ACT, actp->role ) |
| 199 | MMDASSERT( 1 <= actp->id && actp->id <= 99, actp->id ) |
| 200 | } else { //non-native endian |
| 201 | MMDASSERT( actp->role == CNV_END_SHORT(COMP_ROLE_ACT), actp->role ) |
| 202 | MMDASSERT( 1 <= CNV_END_SHORT(actp->id) && CNV_END_SHORT(actp->id) <= 99, actp->id ) |
| 203 | } |
| 204 | if ( sup_endian ) { //native endian |
| 205 | MMDASSERT( supp->role == COMP_ROLE_SUPL, supp->role ) |
| 206 | MMDASSERT( 1 <= supp->id && supp->id <= 99, supp->id ) |
| 207 | MMDASSERT( 1 <= supp->variant && supp->variant <= 99, supp->variant ) |
| 208 | MMDASSERT( 1 <= supp->bottom && supp->bottom <= 99, supp->bottom ) |
| 209 | MMDASSERT( 1 <= supp->top && supp->top <= 99, supp->top ) |
| 210 | MMDASSERT( supp->bottom <= supp->top, supp->bottom << 8 | supp->top ) |
| 211 | } else { //non-native endian |
| 212 | MMDASSERT( supp->role == CNV_END_SHORT(COMP_ROLE_SUPL), supp->role ) |
| 213 | MMDASSERT( 1 <= CNV_END_SHORT(supp->id) && CNV_END_SHORT(supp->id) <= 99, supp->id ) |
| 214 | MMDASSERT( 1 <= CNV_END_SHORT(supp->variant) && CNV_END_SHORT(supp->variant) <= 99, supp->variant ) |
| 215 | MMDASSERT( 1 <= CNV_END_SHORT(supp->bottom) && CNV_END_SHORT(supp->bottom) <=99, supp->bottom ) |
| 216 | MMDASSERT( 1 <= CNV_END_SHORT(supp->top) && CNV_END_SHORT(supp->top) <=99, supp->top ) |
| 217 | MMDASSERT( CNV_END_SHORT(supp->bottom) <= CNV_END_SHORT(supp->top), supp->bottom << 8 | supp->top ) |
| 218 | } |
| 219 | #endif // HCF_ASSERT |
| 220 | |
| 221 | #if HCF_BIG_ENDIAN == 0 |
| 222 | act_endian = !act_endian; /* 1b*/ |
| 223 | sup_endian = !sup_endian; /* 2b*/ |
| 224 | #endif // HCF_BIG_ENDIAN |
| 225 | |
| 226 | for ( i = actp->len ; i > 3; actq++, i -= 3 ) { /* 6 */ |
| 227 | MMDASSERT( actq->variant[act_endian] <= 99, i<<8 | actq->variant[act_endian] ) |
| 228 | MMDASSERT( actq->bottom[act_endian] <= 99 , i<<8 | actq->bottom[act_endian] ) |
| 229 | MMDASSERT( actq->top[act_endian] <= 99 , i<<8 | actq->top[act_endian] ) |
| 230 | MMDASSERT( actq->bottom[act_endian] <= actq->top[act_endian], i<<8 | actq->bottom[act_endian] ) |
| 231 | if ( actq->variant[act_endian] == supq->variant[sup_endian] && |
| 232 | actq->bottom[act_endian] <= supq->top[sup_endian] && |
| 233 | actq->top[act_endian] >= supq->bottom[sup_endian] |
| 234 | ) break; |
| 235 | } |
| 236 | if ( i <= 3 || supp->len != 6 /*sizeof(CFG_SUP_RANGE_STRCT)/sizeof(hcf_16) - 1 */ ) { |
| 237 | actq = NULL; /* 8 */ |
| 238 | } |
| 239 | #if HCF_ASSERT |
| 240 | if ( actq == NULL ) { |
| 241 | for ( i = 0; i <= supp->len; i += 2 ) { |
| 242 | MMDASSERT( DO_ASSERT, MERGE_2( ((hcf_16*)supp)[i], ((hcf_16*)supp)[i+1] ) ); |
| 243 | } |
| 244 | for ( i = 0; i <= actp->len; i += 2 ) { |
| 245 | MMDASSERT( DO_ASSERT, MERGE_2( ((hcf_16*)actp)[i], ((hcf_16*)actp)[i+1] ) ); |
| 246 | } |
| 247 | } |
| 248 | #endif // HCF_ASSERT |
| 249 | return (CFG_RANGE_SPEC_STRCT*)actq; |
| 250 | } // mmd_check_comp |
| 251 | |