| 1 | /*************************************************************** |
|---|
| 2 | ** |
|---|
| 3 | ** Broadcom Corp. Confidential |
|---|
| 4 | ** Copyright 2003-2012 Broadcom Corp. All Rights Reserved. |
|---|
| 5 | ** |
|---|
| 6 | ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED |
|---|
| 7 | ** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. |
|---|
| 8 | ** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT |
|---|
| 9 | ** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 10 | ** |
|---|
| 11 | ** File: si_vcm.c |
|---|
| 12 | ** Description: function that parses the VCM table sections. |
|---|
| 13 | ** |
|---|
| 14 | ** Created: 03/08/2001 |
|---|
| 15 | ** 02/01/2012 modified for A56 support |
|---|
| 16 | ** |
|---|
| 17 | ** REVISION: |
|---|
| 18 | ** |
|---|
| 19 | ** $Log: $ |
|---|
| 20 | ** |
|---|
| 21 | ** |
|---|
| 22 | ****************************************************************/ |
|---|
| 23 | #include "si.h" |
|---|
| 24 | #include "si_os.h" |
|---|
| 25 | #include "si_dbg.h" |
|---|
| 26 | #include "si_util.h" |
|---|
| 27 | #include "si_list.h" |
|---|
| 28 | #include "si_descriptors.h" |
|---|
| 29 | #include "si_transmission_medium.h" |
|---|
| 30 | |
|---|
| 31 | #include "si_vcm.h" |
|---|
| 32 | #include "si_vcm_vct.h" |
|---|
| 33 | |
|---|
| 34 | unsigned char VCM_VCT_version_number; |
|---|
| 35 | unsigned char VCM_VCT_last_section_number; |
|---|
| 36 | unsigned long VCM_VCT_section_mask[8]; |
|---|
| 37 | unsigned short g_vct_id = 0; |
|---|
| 38 | |
|---|
| 39 | static SI_VCM_VCT_Callback_t *s_vcm_vct_cb = NULL; |
|---|
| 40 | |
|---|
| 41 | void SI_VCM_Init( |
|---|
| 42 | SI_VCM_VCT_Callback_t *cb, |
|---|
| 43 | unsigned char iVCM_VCT_version_number |
|---|
| 44 | ) |
|---|
| 45 | { |
|---|
| 46 | unsigned long i; |
|---|
| 47 | |
|---|
| 48 | s_vcm_vct_cb = cb; |
|---|
| 49 | SI_VCM_VCT_Init(s_vcm_vct_cb); |
|---|
| 50 | VCM_VCT_version_number = iVCM_VCT_version_number; |
|---|
| 51 | for (i=0; i<8; i++) |
|---|
| 52 | VCM_VCT_section_mask[i] = 0; |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | /********************************************************************* |
|---|
| 56 | Function : SI_VCM_Get |
|---|
| 57 | Description : Return the version numbers and masks. |
|---|
| 58 | Input : none. |
|---|
| 59 | Output : version number and pointers to section masks. |
|---|
| 60 | **********************************************************************/ |
|---|
| 61 | bool SI_VCM_Complete(void) |
|---|
| 62 | { |
|---|
| 63 | return (SI_Chk_Section_complete(VCM_VCT_section_mask,VCM_VCT_last_section_number) == SI_SUCCESS); |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | /********************************************************************* |
|---|
| 67 | Function : SI_VCM_parse |
|---|
| 68 | Description : Function to parse the VCM table. |
|---|
| 69 | Input : unsigned char * table: point to the current VCM table section. |
|---|
| 70 | Output : SI_RET_CODE. |
|---|
| 71 | **********************************************************************/ |
|---|
| 72 | SI_RET_CODE SI_VCM_parse (unsigned char * table) |
|---|
| 73 | { |
|---|
| 74 | unsigned long temp; |
|---|
| 75 | unsigned long section_length; |
|---|
| 76 | unsigned char table_subtype; |
|---|
| 77 | unsigned long desc_tag, len; |
|---|
| 78 | unsigned char version_number, section_number, last_section_number; |
|---|
| 79 | unsigned char *current, *crc_start; |
|---|
| 80 | int found_rdd; |
|---|
| 81 | |
|---|
| 82 | found_rdd = 0; |
|---|
| 83 | |
|---|
| 84 | SI_DBG_PRINT(E_SI_DBG_MSG,("VCM Table received.\n")); |
|---|
| 85 | |
|---|
| 86 | if (*table != SI_VCM_TABLE_ID) |
|---|
| 87 | { |
|---|
| 88 | SI_DBG_PRINT(E_SI_ERR_MSG,("VCM Table ID error!!! %x\n", *table)); |
|---|
| 89 | return SI_TABLE_ID_ERROR; |
|---|
| 90 | } |
|---|
| 91 | |
|---|
| 92 | /* calculate and check section length. */ |
|---|
| 93 | section_length = SI_Construct_Data(table, |
|---|
| 94 | VCM_SECTION_LENGTH_BYTE_INDX, |
|---|
| 95 | VCM_SECTION_LENGTH_BYTE_NUM, |
|---|
| 96 | VCM_SECTION_LENGTH_SHIFT, |
|---|
| 97 | VCM_SECTION_LENGTH_MASK); |
|---|
| 98 | section_length += VCM_SECTION_LENGTH_BYTE_INDX+VCM_SECTION_LENGTH_BYTE_NUM; |
|---|
| 99 | if (section_length > SI_NORMAL_SECTION_LENGTH) |
|---|
| 100 | { |
|---|
| 101 | SI_DBG_PRINT(E_SI_ERR_MSG,("VCM Table section length error!!! %x\n", section_length)); |
|---|
| 102 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | /* We do the CRC check here to verify the contents of this section. */ |
|---|
| 106 | if (SI_CRC32_Check(table, section_length) != SI_SUCCESS) |
|---|
| 107 | { |
|---|
| 108 | SI_DBG_PRINT(E_SI_ERR_MSG,("VCM Table section CRC error!!!\n")); |
|---|
| 109 | return SI_CRC_ERROR; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | /* check protocol version. It should be zero for now. */ |
|---|
| 113 | temp = SI_Construct_Data(table, |
|---|
| 114 | VCM_PROTOCOL_VERSION_BYTE_INDX, |
|---|
| 115 | VCM_PROTOCOL_VERSION_BYTE_NUM, |
|---|
| 116 | VCM_PROTOCOL_VERSION_SHIFT, |
|---|
| 117 | VCM_PROTOCOL_VERSION_MASK); |
|---|
| 118 | if (temp != SI_CURRENT_PROTOCOL_VERSION) |
|---|
| 119 | { |
|---|
| 120 | SI_DBG_PRINT(E_SI_ERR_MSG,("VCM Table PROTOCOL version error!!! %x\n", temp)); |
|---|
| 121 | return SI_PROTOCOL_VER_ERROR; |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | temp = SI_Construct_Data(table, |
|---|
| 125 | VCM_TRANS_MEDIUM_BYTE_INDX, |
|---|
| 126 | VCM_TRANS_MEDIUM_BYTE_NUM, |
|---|
| 127 | VCM_TRANS_MEDIUM_SHIFT, |
|---|
| 128 | VCM_TRANS_MEDIUM_MASK); |
|---|
| 129 | if (TRANSMISSION_MEDIUM_CABLE != temp) { |
|---|
| 130 | SI_DBG_PRINT(E_SI_ERR_MSG,("Not supported transmission medium type!!!")); |
|---|
| 131 | return SI_NOT_SUPPORTED_ERROR; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | /* we just need to handle VCT. Ignore the ICT or DCM for now. */ |
|---|
| 135 | table_subtype = SI_Construct_Data(table, |
|---|
| 136 | VCM_TABLE_SUBTYPE_BYTE_INDX, |
|---|
| 137 | VCM_TABLE_SUBTYPE_BYTE_NUM, |
|---|
| 138 | VCM_TABLE_SUBTYPE_SHIFT, |
|---|
| 139 | VCM_TABLE_SUBTYPE_MASK); |
|---|
| 140 | if (table_subtype != VCT) |
|---|
| 141 | { |
|---|
| 142 | SI_DBG_PRINT(E_SI_DBG_MSG,("We are only interested in VCT of VCM right now.\n")); |
|---|
| 143 | return SI_SUCCESS; |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | g_vct_id = SI_Construct_Data(table, |
|---|
| 147 | VCM_VCT_ID_BYTE_INDX, |
|---|
| 148 | VCM_VCT_ID_BYTE_NUM, |
|---|
| 149 | VCM_VCT_ID_SHIFT, |
|---|
| 150 | VCM_VCT_ID_MASK); |
|---|
| 151 | |
|---|
| 152 | /* we get a VCM record. see if we have any table level |
|---|
| 153 | descriptors for revision dectection. */ |
|---|
| 154 | current = table + VCM_VCT_ID_BYTE_INDX + VCM_VCT_ID_BYTE_NUM; |
|---|
| 155 | |
|---|
| 156 | /* point to the start of table level descriptor. */ |
|---|
| 157 | current = SI_VCM_VCT_Pointer(current); |
|---|
| 158 | crc_start = table + section_length - SI_CRC_LENGTH; |
|---|
| 159 | |
|---|
| 160 | /* go through all descriptors. */ |
|---|
| 161 | while ((unsigned long)current < (unsigned long)crc_start) |
|---|
| 162 | { |
|---|
| 163 | desc_tag = *(current++); |
|---|
| 164 | len = *(current++); |
|---|
| 165 | switch(desc_tag) |
|---|
| 166 | { |
|---|
| 167 | case SI_DESC_REVISION_DETECTION: |
|---|
| 168 | found_rdd = 1; |
|---|
| 169 | /* we got a revision dectection descriptor. */ |
|---|
| 170 | SI_DBG_PRINT(E_SI_DBG_MSG,("VCM VCM revision detection descriptors found.\n")); |
|---|
| 171 | version_number = SI_Construct_Data( current, |
|---|
| 172 | DESC_REV_DECTECT_VER_NUM_BYTE_INDEX, |
|---|
| 173 | DESC_REV_DECTECT_VER_NUM_BYTE_NUM, |
|---|
| 174 | DESC_REV_DECTECT_VER_NUM_SHIFT, |
|---|
| 175 | DESC_REV_DECTECT_VER_NUM_MASK); |
|---|
| 176 | section_number = SI_Construct_Data( current, |
|---|
| 177 | DESC_REV_DECTECT_SEC_NUM_BYTE_INDEX, |
|---|
| 178 | DESC_REV_DECTECT_SEC_NUM_BYTE_NUM, |
|---|
| 179 | DESC_REV_DECTECT_SEC_NUM_SHIFT, |
|---|
| 180 | DESC_REV_DECTECT_SEC_NUM_MASK); |
|---|
| 181 | last_section_number = SI_Construct_Data( current, |
|---|
| 182 | DESC_REV_DECTECT_LAST_SEC_NUM_BYTE_INDEX, |
|---|
| 183 | DESC_REV_DECTECT_LAST_SEC_NUM_BYTE_NUM, |
|---|
| 184 | DESC_REV_DECTECT_LAST_SEC_NUM_SHIFT, |
|---|
| 185 | DESC_REV_DECTECT_LAST_SEC_NUM_MASK); |
|---|
| 186 | VCM_VCT_last_section_number = last_section_number; |
|---|
| 187 | if (version_number == VCM_VCT_version_number) |
|---|
| 188 | { |
|---|
| 189 | /* same version number, check section mask. */ |
|---|
| 190 | if (SI_Chk_Section_mask(VCM_VCT_section_mask, section_number)) |
|---|
| 191 | return SI_SUCCESS; /* no need to update. */ |
|---|
| 192 | } |
|---|
| 193 | else |
|---|
| 194 | { |
|---|
| 195 | /* different CDS version, init the CDS table and section mask .*/ |
|---|
| 196 | SI_VCM_VCT_Free_List(); |
|---|
| 197 | VCM_VCT_version_number = version_number; |
|---|
| 198 | SI_Init_Section_Mask(VCM_VCT_section_mask, last_section_number); |
|---|
| 199 | } |
|---|
| 200 | /* update the mask */ |
|---|
| 201 | SI_Set_Section_mask(VCM_VCT_section_mask, section_number); |
|---|
| 202 | break; |
|---|
| 203 | |
|---|
| 204 | default: |
|---|
| 205 | SI_DBG_PRINT(E_SI_WRN_MSG,("VCM VCM table descriptor %x received! Ignoring!\n", desc_tag)); |
|---|
| 206 | break; |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | /* update pointer. */ |
|---|
| 210 | current += len; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | /* check for desc length. */ |
|---|
| 214 | if ((unsigned long)current != (unsigned long)crc_start) |
|---|
| 215 | { |
|---|
| 216 | SI_DBG_PRINT(E_SI_ERR_MSG,("VCM Table length error!!!\n")); |
|---|
| 217 | return SI_SECTION_LENGTH_ERROR; |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | if (found_rdd == 0) |
|---|
| 221 | { |
|---|
| 222 | #ifdef CONFIG_RDD_REQUIRED |
|---|
| 223 | SI_DBG_PRINT(E_SI_ERR_MSG,("Revistion Detection Descriptor is required!!!\n")); |
|---|
| 224 | return SI_DESCRIPTOR_ERROR; |
|---|
| 225 | #else |
|---|
| 226 | /* set completion flag if there is no version descriptor */ |
|---|
| 227 | VCM_VCT_last_section_number = 0; |
|---|
| 228 | SI_Set_Section_mask(VCM_VCT_section_mask, 0); |
|---|
| 229 | #endif |
|---|
| 230 | } |
|---|
| 231 | |
|---|
| 232 | /* we either need to update the channel table or we don't have a revision detection. */ |
|---|
| 233 | current = table + VCM_VCT_ID_BYTE_INDX + VCM_VCT_ID_BYTE_NUM; |
|---|
| 234 | return SI_VCM_VCT_Parse(current); |
|---|
| 235 | } |
|---|