cancun.c (105767B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: cancun.c 8 * Purpose: CANCUN API and routines 9 * This module provides API's for all CANCUN related operations 10 */ 11 #include <sal/core/libc.h> 12 #include <shared/bsl.h> 13 14 #include <bcm/types.h> 15 #include <soc/drv.h> 16 #include <soc/error.h> 17 #include <soc/cmic.h> 18 #include <soc/util.h> 19 #include <soc/debug.h> 20 #ifdef BCM_CMICM_SUPPORT 21 #include <soc/cmicm.h> 22 #endif 23 #include <soc/esw/cancun.h> 24 25 #ifdef BCM_WARM_BOOT_SUPPORT 26 #include <soc/scache.h> 27 #endif 28 29 #include <soc/devids.h> 30 31 /* Environment switch */ 32 #define _PCID_TEST 0 33 34 /* Local defines */ 35 #define BYTES_PER_UINT32 (sizeof(uint32)) 36 37 /* 38 * Variable: 39 * soc_cancun_info 40 * Purpose: 41 * One entry for each SOC device containing port information 42 * for that device. 43 */ 44 static soc_cancun_t *soc_cancun_info[BCM_MAX_NUM_UNITS]; 45 46 /* Local functions */ 47 static int _soc_cancun_alloc(soc_cancun_t** cancun); 48 static int _soc_cancun_file_pio_load(int unit, uint8* buf, int buf_words); 49 static int _soc_cancun_file_cmh_load(int unit, uint8* buf, int buf_words); 50 static int _soc_cancun_file_cch_load(int unit, uint8* buf, int buf_words); 51 static int _soc_cancun_file_ceh_load(int unit, uint8* buf, int buf_words); 52 static int _soc_cancun_cih_load(int unit, uint8* buf, int num_data_blobs); 53 static int _soc_cancun_cih_pio_load(int unit, uint8* buf, int length, 54 uint32 flags); 55 static int _soc_cancun_cih_tcam_write(int unit, uint8 *buf); 56 static int _soc_cancun_hash(soc_cancun_hash_table_t* t, uint32 mem, 57 soc_field_t field, uint32* key); 58 static uint32* _soc_cancun_hash_find_entry(uint32 *hash_entry, uint32 src_mem, 59 uint32 src_field, int src_app); 60 static int _soc_cancun_cmh_list_update(soc_cancun_cmh_t *cmh); 61 static int _soc_cancun_memcpy_letohl(uint32 *des, uint32 *src, uint32 word_len); 62 static int _soc_cancun_enum_check(int unit, int regmem, int enum_val, int enum_type); 63 static int _soc_cancun_cih_mem_load(int unit, uint8 *buf); 64 static int _soc_cancun_cch_dest_set (int unit, 65 soc_cancun_cch_map_t *cch_map, uint64 data); 66 static int _soc_cancun_cch_dest_set_with_idx (int unit, 67 soc_cancun_cch_map_t *cch_map, uint64 data, uint32 val_idx); 68 69 70 /* ZLIB CRC-32 table*/ 71 static uint32 soc_crc32_tab[] = { 72 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 73 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 74 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 75 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 76 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 77 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 78 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 79 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 80 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 81 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 82 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 83 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 84 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 85 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 86 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 87 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 88 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 89 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 90 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 91 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 92 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 93 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 94 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 95 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 96 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 97 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 98 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 99 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 100 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 101 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 102 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 103 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 104 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 105 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 106 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 107 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 108 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 109 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 110 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 111 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 112 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 113 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 114 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 115 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 116 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 117 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 118 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 119 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 120 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 121 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 122 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 123 0x2d02ef8dL 124 }; 125 126 /* 127 * Function: 128 * soc_cancun_init 129 * Purpose: 130 * Initialization sequence for loading all applied CANCUN loadable files 131 * Parameters: 132 * unit - (IN) Unit ID 133 * Returns: 134 * SOC_E_NONE 135 * SOC_E_FAIL 136 */ 137 int soc_cancun_init (uint32 unit) { 138 soc_cancun_t* cc = soc_cancun_info[unit]; 139 char *cancun_path; 140 uint32 val, cancun_path_len = 0; 141 142 if(cc == NULL) { 143 144 if(_soc_cancun_alloc(&cc)) { 145 return SOC_E_MEMORY; 146 } 147 148 cc->unit = unit; 149 cc->flags = SOC_CANCUN_FLAG_LOAD_DEFAULT_ALL; 150 151 cancun_path = soc_property_get_str(unit, "cancun_dir"); 152 if(cancun_path != NULL) { 153 cancun_path_len = sal_strlen(cancun_path); 154 if(cancun_path_len < CANCUN_FILENAME_SIZE) { 155 sal_memcpy(cc->default_path, cancun_path, cancun_path_len); 156 } 157 } else { 158 sal_memset(cc->default_path, 0, CANCUN_FILENAME_SIZE); 159 } 160 161 val = soc_property_get(unit, "cancun_load_skip", 0); 162 cc->flags &= (val & SOC_PROPERTY_CANCUN_LOAD_SKIP_CIH)? 163 (~SOC_CANCUN_FLAG_LOAD_DEFAULT_CIH) : (~0); 164 cc->flags &= (val & SOC_PROPERTY_CANCUN_LOAD_SKIP_CMH)? 165 (~SOC_CANCUN_FLAG_LOAD_DEFAULT_CMH) : (~0); 166 cc->flags &= (val & SOC_PROPERTY_CANCUN_LOAD_SKIP_CCH)? 167 (~SOC_CANCUN_FLAG_LOAD_DEFAULT_CCH) : (~0); 168 cc->flags &= (val & SOC_PROPERTY_CANCUN_LOAD_SKIP_CFH)? 169 (~SOC_CANCUN_FLAG_LOAD_DEFAULT_CFH) : (~0); 170 cc->flags &= (val & SOC_PROPERTY_CANCUN_LOAD_SKIP_CEH)? 171 (~SOC_CANCUN_FLAG_LOAD_DEFAULT_CEH) : (~0); 172 val = soc_property_get(unit, "cancun_debug_mode", 0); 173 cc->flags |= (val & SOC_PROPERTY_CANCUN_DEBUG_MODE)? 174 SOC_CANCUN_FLAG_DEBUG_MODE: 0; 175 cc->flags |= (val & SOC_PROPERTY_CANCUN_FILE_VALIDITY)? 176 SOC_CANCUN_FLAG_SKIP_VALIDITY: 0; 177 cc->flags |= SOC_CANCUN_FLAG_INITIALIZED; 178 soc_cancun_info[unit] = cc; 179 } 180 181 if((cc->flags & SOC_CANCUN_FLAG_INITIALIZED) == 0) { 182 return SOC_E_INIT; 183 } 184 185 #ifdef BCM_WARM_BOOT_SUPPORT 186 if (!SOC_WARM_BOOT(unit)) { 187 (void)soc_cancun_scache_alloc(unit); 188 } 189 #endif /* BCM_WARM_BOOT_SUPPORT */ 190 191 return SOC_E_NONE; 192 } 193 194 /* 195 * Function: 196 * soc_cancun_deinit 197 * Purpose: 198 * De-initialization CANCUN control structures 199 * Parameters: 200 * unit - (IN) Unit ID 201 * Returns: 202 * SOC_E_NONE 203 * SOC_E_FAIL 204 */ 205 void soc_cancun_deinit(uint32 unit) { 206 soc_cancun_t* cc = soc_cancun_info[unit]; 207 208 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 209 "De-initialize CANCUN for UNIT %d\n"), unit)); 210 211 if(cc != NULL) { 212 if(cc->cih != NULL) { 213 sal_free(cc->cih); 214 } 215 216 if(cc->cmh != NULL) { 217 if(cc->cmh->cmh_table != NULL) { 218 sal_free(cc->cmh->cmh_table); 219 } 220 if(cc->cmh->cmh_list != NULL) { 221 sal_free(cc->cmh->cmh_list); 222 } 223 sal_free(cc->cmh); 224 } 225 226 if(cc->cch != NULL) { 227 if(cc->cch->cch_table != NULL) { 228 sal_free(cc->cch->cch_table); 229 } 230 if(cc->cch->pseudo_regs != NULL) { 231 sal_free(cc->cch->pseudo_regs); 232 } 233 sal_free(cc->cch); 234 } 235 236 if(cc->ceh != NULL) { 237 if(cc->ceh->ceh_table != NULL) { 238 sal_free(cc->ceh->ceh_table); 239 } 240 sal_free(cc->ceh); 241 } 242 243 if(cc->flow_db != NULL) { 244 if(cc->flow_db->flow_map != NULL) { 245 sal_free(cc->flow_db->flow_map); 246 } 247 sal_free(cc->flow_db); 248 } 249 250 sal_free(cc); 251 252 soc_cancun_info[unit] = (soc_cancun_t*) NULL; 253 } 254 } 255 256 /* 257 * Function: 258 * soc_cancun_info_get 259 * Purpose: 260 * Get cancun info 261 * Parameters: 262 * unit - (IN) Unit ID 263 * cc - (IN/OUT) cancun info 264 * Returns: 265 * SOC_E_NONE 266 * SOC_E_FAIL 267 */ 268 int soc_cancun_info_get(uint32 unit, soc_cancun_t** cc) { 269 270 soc_cancun_t* pcc = soc_cancun_info[unit]; 271 272 if(pcc == NULL) { 273 return SOC_E_INTERNAL; 274 } 275 276 *cc = soc_cancun_info[unit]; 277 278 return SOC_E_NONE; 279 } 280 281 /* 282 * Function: 283 * soc_cancun_status_get 284 * Purpose: 285 * Initialization sequence for loading all applied CANCUN loadable files 286 * Parameters: 287 * unit - (IN) Unit ID 288 * Returns: 289 * SOC_E_NONE 290 * SOC_E_FAIL 291 */ 292 int soc_cancun_status_get(uint32 unit, soc_cancun_t** cc) { 293 294 soc_cancun_t* pcc = soc_cancun_info[unit]; 295 296 if(pcc == NULL) { 297 return SOC_E_UNIT; 298 } else if (!(pcc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 299 return SOC_E_INIT; 300 } 301 302 *cc = soc_cancun_info[unit]; 303 304 return SOC_E_NONE; 305 } 306 307 void soc_cancun_buf_swap32(uint8 *buf, long buf_size) 308 { 309 long i; 310 uint32 *fword = (uint32 *)buf; 311 for (i = 0; i < ((buf_size + 3) / 4); i++) { 312 *fword = soc_letohl(*fword); 313 fword ++; 314 } 315 return ; 316 } 317 318 int soc_cancun_chip_rev_validate(const uint32 chip_rev_id, 319 const uint16 dev_id, const uint8 rev_id) { 320 uint16 cancun_dev_id = chip_rev_id >> 16; 321 uint8 cancun_rev_id = chip_rev_id & 0xff; 322 323 if(chip_rev_id == ((dev_id << 16) | rev_id)) { 324 return TRUE; 325 } 326 327 328 if ((cancun_dev_id == BCM56870_DEVICE_ID) && 329 (cancun_rev_id == BCM56870_A0_REV_ID)) { 330 if ((dev_id == BCM56873_DEVICE_ID) && (rev_id == BCM56873_A0_REV_ID)) { 331 return TRUE; 332 } 333 } 334 if ((cancun_dev_id == BCM56770_DEVICE_ID) && 335 (cancun_rev_id == BCM56770_A0_REV_ID)) { 336 if ((dev_id == BCM56771_DEVICE_ID) && (rev_id == BCM56771_A0_REV_ID)) { 337 return TRUE; 338 } 339 } 340 341 if ((cancun_dev_id == BCM56370_DEVICE_ID) && 342 (cancun_rev_id == BCM56370_A0_REV_ID)) { 343 if (((dev_id == BCM56371_DEVICE_ID) && (rev_id == BCM56371_A0_REV_ID)) || 344 ((dev_id == BCM56372_DEVICE_ID) && (rev_id == BCM56372_A0_REV_ID)) || 345 ((dev_id == BCM56374_DEVICE_ID) && (rev_id == BCM56374_A0_REV_ID)) || 346 ((dev_id == BCM56375_DEVICE_ID) && (rev_id == BCM56375_A0_REV_ID)) || 347 ((dev_id == BCM56376_DEVICE_ID) && (rev_id == BCM56376_A0_REV_ID)) || 348 ((dev_id == BCM56377_DEVICE_ID) && (rev_id == BCM56377_A0_REV_ID)) || 349 ((dev_id == BCM56577_DEVICE_ID) && (rev_id == BCM56577_A0_REV_ID)) || 350 ((dev_id == BCM56578_DEVICE_ID) && (rev_id == BCM56578_A0_REV_ID)) || 351 ((dev_id == BCM56579_DEVICE_ID) && (rev_id == BCM56579_A0_REV_ID)) || 352 ((dev_id == BCM56370_DEVICE_ID) && (rev_id == BCM56370_A1_REV_ID)) || 353 ((dev_id == BCM56371_DEVICE_ID) && (rev_id == BCM56371_A1_REV_ID)) || 354 ((dev_id == BCM56372_DEVICE_ID) && (rev_id == BCM56372_A1_REV_ID)) || 355 ((dev_id == BCM56374_DEVICE_ID) && (rev_id == BCM56374_A1_REV_ID)) || 356 ((dev_id == BCM56375_DEVICE_ID) && (rev_id == BCM56375_A1_REV_ID)) || 357 ((dev_id == BCM56376_DEVICE_ID) && (rev_id == BCM56376_A1_REV_ID)) || 358 ((dev_id == BCM56377_DEVICE_ID) && (rev_id == BCM56377_A1_REV_ID)) || 359 ((dev_id == BCM56577_DEVICE_ID) && (rev_id == BCM56577_A1_REV_ID)) || 360 ((dev_id == BCM56578_DEVICE_ID) && (rev_id == BCM56578_A1_REV_ID)) || 361 ((dev_id == BCM56579_DEVICE_ID) && (rev_id == BCM56579_A1_REV_ID))) { 362 return TRUE; 363 } 364 } 365 366 return FALSE; 367 } 368 369 370 /* 371 * Function: 372 * soc_cancun_file_info_get 373 * Purpose: 374 * Decode a packaged format CANCUN files and save it into file structure 375 * Parameters: 376 * unit - (IN) Unit ID 377 * ccf - (OUT) Pointer to CANCUN file structure 378 * filename - (IN) Filename string if available 379 * buf - (IN) Pointer to buffer of a CANCUN loadable file 380 * buf_bytes - (IN) Length of buffer in bytes 381 * Returns: 382 * SOC_E_NONE 383 * SOC_E_INTERNAL - NULL file structure pointer 384 * SOC_E_BADID - File validity check fails 385 */ 386 int soc_cancun_file_info_get(int unit, soc_cancun_file_t* ccf, char *filename, 387 uint8 *buf, long buf_bytes) { 388 389 soc_cancun_t *cc = soc_cancun_info[unit]; 390 soc_cancun_file_header_t *ccfh = (soc_cancun_file_header_t *) buf; 391 uint16 dev_id; 392 uint8 rev_id; 393 uint32 crc, *file_crc; 394 uint8 *cur_buf; 395 long cur_buf_size; 396 397 if (ccf == NULL) { 398 return SOC_E_INTERNAL; 399 } 400 401 crc = soc_cancun_crc32(0, buf, buf_bytes - 4); 402 403 /* convert file header into correct endianness */ 404 cur_buf = buf; 405 cur_buf_size = SOC_CANCUN_FILE_HEADER_OFFSET; 406 soc_cancun_buf_swap32(cur_buf, cur_buf_size); 407 sal_memcpy(&ccf->header, ccfh, sizeof(soc_cancun_file_header_t)); 408 409 cur_buf += cur_buf_size; 410 cur_buf_size = buf_bytes - cur_buf_size; 411 /* check if CEH or CFH, don't swap rest of file */ 412 if ((ccfh->file_type != SOC_CANCUN_FILE_ID_CEH) && 413 (ccfh->file_type != SOC_CANCUN_FILE_ID_CFH)) { 414 soc_cancun_buf_swap32(cur_buf, cur_buf_size); 415 } else { 416 /* swap the checksum */ 417 soc_cancun_buf_swap32(buf + buf_bytes - 4, 4); 418 } 419 420 if (filename) { 421 sal_strncpy(ccf->filename, filename, sal_strlen(filename)+1); 422 } 423 424 ccf->valid = 0; 425 /* 1. File identifier */ 426 if(ccfh->file_identifier != SOC_CANCUN_FILE_ID) { 427 if (filename) { 428 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 429 "ERROR: %s is not a CANCUN file\n"), filename)); 430 } else { 431 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 432 "ERROR: Not a CANCUN file: 0x%08x. Abort\n"), ccfh->file_identifier)); 433 } 434 return SOC_E_INTERNAL; 435 } 436 /* 2. File type */ 437 switch(ccfh->file_type) { 438 case SOC_CANCUN_FILE_ID_CIH: 439 ccf->type = CANCUN_SOC_FILE_TYPE_CIH; 440 break; 441 case SOC_CANCUN_FILE_ID_CMH: 442 ccf->type = CANCUN_SOC_FILE_TYPE_CMH; 443 break; 444 case SOC_CANCUN_FILE_ID_CCH: 445 ccf->type = CANCUN_SOC_FILE_TYPE_CCH; 446 break; 447 case SOC_CANCUN_FILE_ID_CFH: 448 ccf->type = CANCUN_SOC_FILE_TYPE_CFH; 449 break; 450 case SOC_CANCUN_FILE_ID_CEH: 451 ccf->type = CANCUN_SOC_FILE_TYPE_CEH; 452 break; 453 454 default: 455 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 456 "ERROR: Invalid file type. Abort\n"))); 457 return SOC_E_INTERNAL; 458 } 459 460 /* CANCUN file validation */ 461 if((cc->flags & SOC_CANCUN_FLAG_SKIP_VALIDITY) == 0) { 462 /* 3. File length */ 463 if(ccfh->file_length != BYTES2WORDS(buf_bytes)) { 464 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 465 "ERROR: File length mismatch. Abort\n"))); 466 return SOC_E_INTERNAL; 467 } 468 /* 4. HW version */ 469 soc_cm_get_id(unit, &dev_id, &rev_id); 470 if(!soc_cancun_chip_rev_validate(ccfh->chip_rev_id, dev_id, rev_id)) { 471 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 472 "ERROR: HW version mismatch. Abort\n"))); 473 return SOC_E_INTERNAL; 474 } 475 /* 5. CRC */ 476 file_crc = (uint32 *) (buf + buf_bytes - 4); 477 if (crc != *file_crc) { 478 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 479 "ERROR: CRC check fails (crc 0x%08x, file_crc 0x%08x. Abort\n"), crc, *file_crc)); 480 return SOC_E_INTERNAL; 481 } 482 } 483 484 ccf->valid = 1; 485 ccf->format = CANCUN_SOC_FILE_FORMAT_PACK; 486 ccf->status = CANCUN_SOC_FILE_LOAD_NONE; 487 488 return SOC_E_NONE; 489 } 490 491 /* 492 * Function: 493 * soc_cancun_file_load 494 * Purpose: 495 * Loading a CANCUN loadable file into device or internal structures. This 496 * function also reports file type and format if input content is in 497 * packaged format, or it keep them unchanged 498 * Parameters: 499 * unit - (IN) Unit ID 500 * buf - (IN) Pointer to buffer of a CANCUN loadable file 501 * buf_bytes - (IN) Length of buffer in bytes 502 * type - (INOUT) File type 503 * format - (INOUT) File format 504 * Returns: 505 * SOC_E_NONE 506 * SOC_E_UNIT - Invalid unit ID 507 * SOC_E_PARAM - Invalid input buffer 508 * SOC_E_BADID - File validity check fails 509 * SOC_E_FAIL - Loading fails 510 */ 511 512 int soc_cancun_file_load(int unit, uint8* buf, long buf_bytes, uint32* type, 513 uint32* format) { 514 soc_cancun_t *cc; 515 soc_cancun_file_t ccf_file, *ccf; 516 uint32 status = SOC_CANCUN_LOAD_STATUS_NOT_LOADED; 517 int rv = SOC_E_NONE; 518 519 cc = soc_cancun_info[unit]; 520 if(cc == NULL) { 521 return SOC_E_UNIT; 522 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 523 return SOC_E_INIT; 524 } else if (buf == NULL) { 525 return SOC_E_PARAM; 526 } 527 528 /* Get file information if input PACK or UNKNOWN format */ 529 sal_memset(&ccf_file, 0, sizeof(soc_cancun_file_t)); 530 if (*format == CANCUN_SOC_FILE_FORMAT_PACK || 531 *format == CANCUN_SOC_FILE_FORMAT_UNKNOWN) { 532 rv = soc_cancun_file_info_get(unit, &ccf_file, NULL, buf, buf_bytes); 533 if(rv == SOC_E_NONE) { 534 *type = ccf_file.type; 535 *format = ccf_file.format; 536 537 if(*format == CANCUN_SOC_FILE_FORMAT_PACK) { 538 buf += SOC_CANCUN_FILE_HEADER_OFFSET; 539 buf_bytes -= (SOC_CANCUN_FILE_HEADER_OFFSET + 1); 540 } else { 541 return SOC_E_BADID; 542 } 543 } else { 544 return rv; 545 } 546 } 547 548 if(*type == CANCUN_SOC_FILE_TYPE_CIH) { 549 soc_cancun_file_branch_id_e branch_id = 0; 550 ccf = &cc->cih->file; 551 status = SOC_CANCUN_LOAD_STATUS_IN_PROGRESS; 552 if(*format == CANCUN_SOC_FILE_FORMAT_PIO) { 553 cc->cih->status = status; 554 rv = _soc_cancun_file_pio_load(unit, buf, 555 (buf_bytes/BYTES_PER_UINT32)); 556 557 } else if(*format == CANCUN_SOC_FILE_FORMAT_PACK) { 558 if(SOC_WARM_BOOT(unit)) { 559 rv = SOC_E_NONE; 560 } else { 561 cc->cih->status = status; 562 rv = _soc_cancun_cih_load(unit, buf, 563 ccf_file.header.num_data_blobs); 564 } 565 566 } else { 567 return SOC_E_PARAM; 568 } 569 570 if(rv == SOC_E_NONE) { 571 status = SOC_CANCUN_LOAD_STATUS_LOADED; 572 cc->cih->version = ccf_file.header.version; 573 cc->flags |= SOC_CANCUN_FLAG_CIH_LOADED; 574 575 } else { 576 status = SOC_CANCUN_LOAD_STATUS_FAILED; 577 cc->flags &= ~SOC_CANCUN_FLAG_CIH_LOADED; 578 } 579 cc->cih->status = status; 580 rv = soc_cancun_branch_id_get(unit, 581 CANCUN_SOC_FILE_TYPE_CIH, &branch_id); 582 if (branch_id == CANCUN_FILE_BRANCH_ID_HGoE) { 583 SOC_FEATURE_SET(unit, soc_feature_higig_over_ethernet); 584 } 585 586 587 } else if (*type == CANCUN_SOC_FILE_TYPE_CMH) { 588 ccf = &cc->cmh->file; 589 status = SOC_CANCUN_LOAD_STATUS_IN_PROGRESS; 590 cc->cmh->status = status; 591 rv = _soc_cancun_file_cmh_load(unit, buf, (buf_bytes/BYTES_PER_UINT32)); 592 593 if(rv == SOC_E_NONE) { 594 status = SOC_CANCUN_LOAD_STATUS_LOADED; 595 cc->cmh->version = ccf_file.header.version; 596 cc->cmh->sdk_version = ccf_file.header.sdk_version; 597 cc->flags |= SOC_CANCUN_FLAG_CMH_LOADED; 598 } else { 599 status = SOC_CANCUN_LOAD_STATUS_FAILED; 600 cc->flags &= ~SOC_CANCUN_FLAG_CMH_LOADED; 601 } 602 cc->cmh->status = status; 603 604 } else if (*type == CANCUN_SOC_FILE_TYPE_CCH) { 605 ccf = &cc->cch->file; 606 status = SOC_CANCUN_LOAD_STATUS_IN_PROGRESS; 607 cc->cch->status = status; 608 rv = _soc_cancun_file_cch_load(unit, buf, (buf_bytes/BYTES_PER_UINT32)); 609 610 if(rv == SOC_E_NONE) { 611 status = SOC_CANCUN_LOAD_STATUS_LOADED; 612 cc->cch->version = ccf_file.header.version; 613 cc->cch->sdk_version = ccf_file.header.sdk_version; 614 cc->flags |= SOC_CANCUN_FLAG_CCH_LOADED; 615 } else { 616 status = SOC_CANCUN_LOAD_STATUS_FAILED; 617 cc->flags &= ~SOC_CANCUN_FLAG_CCH_LOADED; 618 } 619 cc->cch->status = status; 620 621 } else if (*type == CANCUN_SOC_FILE_TYPE_CEH) { 622 ccf = &cc->ceh->file; 623 status = SOC_CANCUN_LOAD_STATUS_IN_PROGRESS; 624 cc->ceh->status = status; 625 rv = _soc_cancun_file_ceh_load(unit, buf, (buf_bytes/BYTES_PER_UINT32)); 626 627 if(rv == SOC_E_NONE) { 628 status = SOC_CANCUN_LOAD_STATUS_LOADED; 629 cc->ceh->version = ccf_file.header.version; 630 cc->ceh->sdk_version = ccf_file.header.sdk_version; 631 cc->flags |= SOC_CANCUN_FLAG_CEH_LOADED; 632 } else { 633 status = SOC_CANCUN_LOAD_STATUS_FAILED; 634 cc->flags &= ~SOC_CANCUN_FLAG_CEH_LOADED; 635 } 636 cc->ceh->status = status; 637 638 } else if (*type == CANCUN_SOC_FILE_TYPE_CFH) { 639 ccf = &cc->flow_db->file; 640 status = SOC_CANCUN_LOAD_STATUS_IN_PROGRESS; 641 cc->flow_db->status = status; 642 rv = _soc_flow_db_load(unit, buf, (buf_bytes/BYTES_PER_UINT32)); 643 644 if(rv == SOC_E_NONE) { 645 status = SOC_CANCUN_LOAD_STATUS_LOADED; 646 cc->flow_db->version = ccf_file.header.version; 647 cc->flags |= SOC_CANCUN_FLAG_CFH_LOADED; 648 } else { 649 status = SOC_CANCUN_LOAD_STATUS_FAILED; 650 cc->flags &= ~SOC_CANCUN_FLAG_CFH_LOADED; 651 } 652 cc->flow_db->status = status; 653 } else { 654 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 655 "ERROR: can't recognize file type enum %d\n"), *type)); 656 return SOC_E_PARAM; 657 } 658 659 /* File successfully loaded here. Update ccf */ 660 if(ccf) { 661 sal_memcpy(ccf, &ccf_file, sizeof(soc_cancun_file_t)); 662 ccf->status = status; 663 } 664 665 return rv; 666 } 667 668 669 /* 670 * Function: 671 * soc_cancun_cmh_list 672 * Purpose: 673 * Return the array that contain memory and field pairs covered in CMH 674 * Parameters: 675 * unit - (IN) Unit ID 676 * cmh_list - (INOUT) pointer to a buffer to hold CMH list. 677 * Returns: 678 * SOC_E_NONE 679 * SOC_E_FAIL 680 * 681 * Note: Output format of CANCUN coverage list 682 * +-------------------+-----------------+--------------+--------------+ 683 * | mem_num | mem_1 | field_num | field_1 | 684 * +-------------------+-----------------+--------------+--------------+ 685 * | field_2 | ... | mem_n | field_num_n | 686 * +-------------------+-----------------+--------------+--------------+ 687 * | field_n1 | field_n2 | ... | | 688 * +-------------------+-----------------+--------------+--------------+ 689 */ 690 int soc_cancun_cmh_list (int unit, uint32** cmh_list) { 691 soc_cancun_t *pcc = soc_cancun_info[unit]; 692 soc_cancun_cmh_t *cmh; 693 694 if(pcc == NULL) { 695 return SOC_E_UNIT; 696 } else if (!(pcc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 697 return SOC_E_INIT; 698 } 699 700 cmh = pcc->cmh; 701 if(cmh != NULL) { 702 if(cmh->cmh_list != NULL) { 703 *cmh_list = cmh->cmh_list; 704 return SOC_E_NONE; 705 } 706 } 707 return SOC_E_INIT; 708 } 709 710 /* 711 * Function: 712 * soc_cancun_cmh_check 713 * Purpose: 714 * Check if a mem/field is covered by CMH mapping 715 * Parameters: 716 * unit - (IN) Unit ID 717 * mem - (IN) Memory ID 718 * field - (IN) Field ID 719 * Returns: 720 * SOC_E_NONE - input mem/field is covered by CMH 721 * SOC_E_FAIL - input mem/field is NOT covered by CMH 722 * 723 * Note: For cmh_list, the first word is the number of the entries, and each two 724 * words after it is the pair of memory and field pair in enumeration 725 * +-------------------+-----------------+--------------+--------------+ 726 * | entry_num | mem_1 | field_1 | app_1 | 727 * +-------------------+-----------------+--------------+--------------+ 728 * | ... | mem_n | field_n | app_n | 729 * +-------------------+-----------------+--------------+--------------+ 730 */ 731 int soc_cancun_cmh_check (int unit, soc_mem_t mem, soc_field_t field) { 732 soc_cancun_t *pcc = soc_cancun_info[unit]; 733 soc_cancun_cmh_t *cmh; 734 uint32 entry_num = 0, i; 735 uint32 *entry = NULL; 736 737 if(pcc == NULL) { 738 return SOC_E_UNIT; 739 } else if (!(pcc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 740 return SOC_E_INIT; 741 } 742 743 cmh = pcc->cmh; 744 if(cmh != NULL) { 745 if(cmh->cmh_list != NULL) { 746 entry = cmh->cmh_list; 747 entry_num = *entry++; 748 for(i = 0; i < entry_num; i++, entry += SOC_CANCUN_CMH_LIST_ENTRY_SIZE) { 749 if(mem == *(entry + SOC_CANCUN_CMH_LIST_ENTRY_OFFSET_MEM) && 750 field == *(entry + SOC_CANCUN_CMH_LIST_ENTRY_OFFSET_FIELD)) { 751 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 752 "%s.%s is covered by CMH\n"), 753 SOC_MEM_NAME(unit, mem), 754 SOC_FIELD_NAME(unit, field))); 755 return SOC_E_NONE; 756 } 757 } 758 return SOC_E_FAIL; 759 } 760 } 761 return SOC_E_INIT; 762 } 763 764 /* 765 * Function: 766 * soc_cancun_cmh_mem_set 767 * Purpose: 768 * Configure memory field values according to internal CMH tables 769 * Parameters: 770 * unit - (IN) Unit ID 771 * mem - (IN) Memory ID. Input INVALIDm if not applied 772 * index - (IN) Memory entry index 773 * field - (IN) Field ID. Input INVALIDf if not applied 774 * input - (IN) This parameter can be field value or application 775 * 776 * Returns: 777 * SOC_E_NONE 778 * SOC_E_FAIL 779 * SOC_E_INTERNAL - CMH tables are not loaded 780 * SOC_E_PARAM - Input parameters are invalid 781 * SOC_E_NOT_FOUND - Input mem/reg/field are not found in CMH 782 * 783 * Note: 784 * CMH entry format is shown as following. For more details, please refer 785 * to section 4.1.1 in document "Trident3 SOC Layer Support for CANCUN". 786 * 787 * +-------------------+-----------------+--------------+--------------+ 788 * | entry flags/size | src_mem | src_field | src_value_num| 789 * +-------------------+-----------------+--------------+--------------+ 790 * | /removed/ | dest_mem_num | src_val_0 | ... | 791 * +-------------------+-----------------+--------------+--------------+ 792 * | src_val_n | des_mem_0 | field_num_0 | field_0 | 793 * +-------------------+-----------------+--------------+--------------+ 794 * | ... | field_m | dest_val_00 | ... | 795 * +-------------------+-----------------+--------------+--------------+ 796 * | dest_val_0m | dest_val_10 | ... | dest_val_1m | 797 * +-------------------+-----------------+--------------+--------------+ 798 * | dest_mem_1 | ... | 799 * +-------------------+-----------------------------------------------+ 800 */ 801 int soc_cancun_cmh_mem_set (int unit, soc_mem_t mem, int index, 802 soc_field_t field, uint32 input) { 803 soc_cancun_t* cc; 804 soc_cancun_cmh_t* cmh; 805 soc_cancun_cmh_map_t* cmh_map; 806 soc_cancun_hash_table_t* hash_table_header; 807 uint32 *hash_table_entry, *p; 808 uint32 entry_num, value_ind, mem_num, field_num, value_num; 809 uint32 i, j, k, offset, key, app; 810 soc_mem_t d_mem; 811 soc_field_t fields[SOC_MAX_MEM_FIELD_WORDS]; 812 uint32 values[SOC_MAX_MEM_FIELD_WORDS]; 813 int rv, dest_index = index; 814 815 cc = soc_cancun_info[unit]; 816 if(cc == NULL) { 817 return SOC_E_UNIT; 818 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 819 return SOC_E_INIT; 820 } 821 822 /* deal with EGR_PORT.PORT_TYPE covered by CMH format 2 */ 823 if(mem == EGR_PORTm && field == PORT_TYPEf) { 824 switch(input) { 825 case 0: /* Ethernet */ 826 if(IS_CPU_PORT(unit, index)) { 827 app = CANCUN_APP__EGR_PORT__CPU_ETHERNET_PORT; 828 } else { 829 app = CANCUN_APP__EGR_PORT__ETHERNET; 830 } 831 break; 832 case 1: /* HG2 */ 833 if(IS_CPU_PORT(unit, index)) { 834 app = CANCUN_APP__EGR_PORT__CPU_HG2_PORT; 835 } else { 836 app = CANCUN_APP__EGR_PORT__HG2_PORT; 837 } 838 break; 839 case 2: /* Loopback */ 840 app = CANCUN_APP__EGR_PORT__LOOPBACK; 841 break; 842 case 4: /* Cascade */ 843 app = CANCUN_APP__EGR_PORT__CASCADED_PORT; 844 break; 845 default: 846 return SOC_E_PARAM; 847 break; 848 }; 849 rv = soc_cancun_app_dest_entry_set (unit, mem, index, field, app, input); 850 851 852 (void)soc_cancun_app_dest_entry_set (unit, EGR_PORTm, index, INVALIDf, CANCUN_APP__EGR_PORT__QOS_LAYERED_RESOLUTION, 0); 853 854 return rv; 855 } 856 857 cmh = cc->cmh; 858 hash_table_header = (soc_cancun_hash_table_t*) cmh->cmh_table; 859 hash_table_entry = &hash_table_header->table_entry; 860 861 rv = _soc_cancun_hash(hash_table_header, mem, field, &key); 862 if(rv != SOC_E_NONE) { 863 return rv; 864 } 865 offset = *(hash_table_entry + key); 866 if(offset == 0) { 867 return SOC_E_NOT_FOUND; 868 } 869 870 p = hash_table_entry + offset; 871 entry_num = *p++; 872 cmh_map = (soc_cancun_cmh_map_t*) p; 873 if (entry_num != 0) { 874 for(i = 0; i < entry_num; i++) { 875 if(cmh_map->src_mem == mem && cmh_map->src_field == field && 876 (cmh_map->format == 1 || cmh_map->format == 5)) { 877 878 /* check if value is in value list */ 879 value_num = cmh_map->src_value_num; 880 p = &(cmh_map->dest_map_entry); 881 for(j = 0; j < value_num; j++) { 882 if(input == *(p+j)) { 883 break; 884 } 885 } 886 887 if(j >= value_num) { 888 return SOC_E_PARAM; 889 } else { 890 value_ind = j; 891 } 892 893 /* writing mapped mem/field */ 894 mem_num = cmh_map->dest_mem_num; 895 p = &(cmh_map->dest_map_entry) + value_num; 896 for(j = 0; j < mem_num; j++) { 897 d_mem = *p++; 898 if(cmh_map->format == 5) { 899 dest_index = *p++; 900 } else { 901 dest_index = index; 902 } 903 field_num = *p++; 904 for(k = 0; k < field_num; k++) { 905 fields[k] = *p++; 906 } 907 p += value_ind * field_num; 908 for(k = 0; k < field_num; k++) { 909 values[k] = *p++; 910 } 911 912 rv = soc_mem_fields32_modify(unit, d_mem, dest_index, field_num, 913 fields, values); 914 915 /* Debug log */ 916 if(cc->flags & SOC_CANCUN_FLAG_DEBUG_MODE) { 917 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 918 "For index %d, mem %s, field %s, value %d\nCMH writes:\n\tmem: %s[%d]\n"), 919 index, 920 SOC_MEM_NAME(unit, mem), 921 SOC_FIELD_NAME(unit, field), input, 922 SOC_MEM_NAME(unit, d_mem), 923 dest_index)); 924 925 for(k = 0; k < field_num; k++) { 926 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 927 "\tfield: %s, value: %d\n"), 928 SOC_FIELD_NAME(unit, fields[k]), values[k])); 929 } 930 } 931 } 932 return SOC_E_NONE; 933 } 934 cmh_map = (soc_cancun_cmh_map_t *) \ 935 ((uint32 *)cmh_map + cmh_map->entry_size); 936 } 937 return SOC_E_NOT_FOUND; 938 } 939 return SOC_E_NOT_FOUND; 940 } 941 942 int soc_cancun_cmh_mem_get (int unit, soc_mem_t mem, int index, 943 soc_field_t field, uint32* value) { 944 945 /* No deprecated fields for now. No need to be implement */ 946 947 return SOC_E_NONE; 948 } 949 950 STATIC 951 int _soc_cancun_ceh_hash_key_get(int unit, soc_cancun_hash_table_t *hash_tbl, 952 char *obj_name, 953 uint32 *key) 954 { 955 char *cp; 956 uint32 len; 957 uint32 hash = 0; 958 959 if ((hash_tbl == NULL) || 960 (key == NULL)) { 961 return SOC_E_PARAM; 962 } 963 /* hash function */ 964 cp = obj_name; 965 len = sal_strlen(obj_name); 966 if (len == 0) { 967 return SOC_E_PARAM; 968 } 969 while (*cp != '\0') { 970 hash += *cp++; 971 } 972 973 *key = (hash_tbl->pb * hash) % hash_tbl->pd; 974 975 return SOC_E_NONE; 976 } 977 978 /* 979 * Function: 980 * soc_cancun_ceh_obj_field_get 981 * Purpose: 982 * Get the Cancun encoded object field definition 983 * Parameters: 984 * unit - (IN) Unit ID 985 * obj_name - (IN) object name 986 * field_name - (IN) object field name 987 * field_info - (OUT) Retrieved field information 988 * Returns: 989 * SOC_E_XXX 990 */ 991 int soc_cancun_ceh_obj_field_get (int unit, char *obj_name, 992 char *field_name, 993 soc_cancun_ceh_field_info_t *info) 994 { 995 996 soc_cancun_t* cc; 997 soc_cancun_ceh_t* ceh; 998 soc_cancun_hash_table_t* hash_table_header; 999 uint32 *entry_location_tbl; 1000 uint32 entry_num; 1001 uint32 i, j, offset, key; 1002 uint32 *curr_p; 1003 soc_cancun_ceh_object_t *obj_p; 1004 soc_cancun_ceh_field_t *fld_p; 1005 char *str_mem_offset; 1006 1007 cc = soc_cancun_info[unit]; 1008 if(cc == NULL) { 1009 return SOC_E_UNIT; 1010 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1011 return SOC_E_INIT; 1012 } 1013 1014 ceh = cc->ceh; 1015 hash_table_header = SOC_CANCUN_CEH_HASH_HDR_TBL(ceh->ceh_table); 1016 entry_location_tbl = SOC_CANCUN_CEH_OBJ_ENTRY_LOC_TBL(ceh->ceh_table); 1017 1018 /* hash key generation. The hash function must be same as in CEH */ 1019 SOC_IF_ERROR_RETURN(_soc_cancun_ceh_hash_key_get(unit,hash_table_header, 1020 obj_name, &key)); 1021 1022 /* the hash key is the index to the entry location table where each location 1023 * could have one or more entries with the same hash key value. The location 1024 * is represented by an offset value from the start of entry_location_tbl 1025 * to the start of the entry. 1026 */ 1027 offset = *(entry_location_tbl + key); 1028 if(offset == 0) { 1029 return SOC_E_NOT_FOUND; 1030 } 1031 1032 /* point to the location where the first entry starts */ 1033 curr_p = entry_location_tbl + offset; 1034 entry_num = *curr_p++; 1035 if (!entry_num) { 1036 return SOC_E_NOT_FOUND; 1037 } 1038 /* start of string offset location */ 1039 str_mem_offset = (char *)SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1040 1041 for (i = 0; i < entry_num; i++) { 1042 obj_p = (soc_cancun_ceh_object_t *)curr_p; 1043 fld_p = (soc_cancun_ceh_field_t *)(obj_p + 1); 1044 if (sal_strcmp(obj_name, str_mem_offset + obj_p->name_addr) == 0) { 1045 /* found object */ 1046 for (j = 0; j < obj_p->num_fields; j++) { 1047 if (sal_strcmp(field_name, 1048 str_mem_offset + (fld_p + j)->name_addr) == 0) { 1049 info->offset = (fld_p + j)->offset; 1050 info->width = (fld_p + j)->width; 1051 info->value = (fld_p + j)->value; 1052 info->flags = 0; 1053 return SOC_E_NONE; 1054 } 1055 } 1056 } 1057 /* next entry with the same hash key */ 1058 curr_p = (uint32 *)(fld_p + obj_p->num_fields); 1059 } 1060 return SOC_E_NOT_FOUND; 1061 } 1062 1063 /* 1064 * Function: 1065 * soc_cancun_ceh_obj_field_id_list_get 1066 * Purpose: 1067 * Get a list of field IDs for the given object 1068 * Parameters: 1069 * unit - (IN) Unit ID 1070 * obj_name - (IN) object name 1071 * size - (IN/OUT) size of field_id array buffer 1072 * field_id_arr - (OUT) field_id array buffer 1073 * Returns: 1074 * SOC_E_XXX 1075 */ 1076 int soc_cancun_ceh_obj_field_id_list_get (int unit, char *obj_name, 1077 int *size, 1078 uint32 *field_id_arr) 1079 { 1080 1081 soc_cancun_t* cc; 1082 soc_cancun_ceh_t* ceh; 1083 soc_cancun_hash_table_t* hash_table_header; 1084 uint32 *entry_location_tbl; 1085 uint32 entry_num; 1086 uint32 i, j, offset, key; 1087 uint32 *curr_p; 1088 soc_cancun_ceh_object_t *obj_p; 1089 soc_cancun_ceh_field_t *fld_p; 1090 char *str_mem_offset; 1091 1092 cc = soc_cancun_info[unit]; 1093 if(cc == NULL) { 1094 return SOC_E_UNIT; 1095 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1096 return SOC_E_INIT; 1097 } 1098 1099 ceh = cc->ceh; 1100 hash_table_header = SOC_CANCUN_CEH_HASH_HDR_TBL(ceh->ceh_table); 1101 entry_location_tbl = SOC_CANCUN_CEH_OBJ_ENTRY_LOC_TBL(ceh->ceh_table); 1102 1103 /* hash key generation. The hash function must be same as in CEH */ 1104 SOC_IF_ERROR_RETURN(_soc_cancun_ceh_hash_key_get(unit,hash_table_header, 1105 obj_name, &key)); 1106 1107 /* the hash key is the index to the entry location table where each location 1108 * could have one or more entries with the same hash key value. The location 1109 * is represented by an offset value from the start of entry_location_tbl 1110 * to the start of the entry. 1111 */ 1112 offset = *(entry_location_tbl + key); 1113 if(offset == 0) { 1114 return SOC_E_NOT_FOUND; 1115 } 1116 1117 /* point to the location where the first entry starts */ 1118 curr_p = entry_location_tbl + offset; 1119 entry_num = *curr_p++; 1120 if (!entry_num) { 1121 return SOC_E_NOT_FOUND; 1122 } 1123 /* start of string offset location */ 1124 str_mem_offset = (char *)SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1125 1126 for (i = 0; i < entry_num; i++) { 1127 obj_p = (soc_cancun_ceh_object_t *)curr_p; 1128 fld_p = (soc_cancun_ceh_field_t *)(obj_p + 1); 1129 if (sal_strcmp(obj_name, str_mem_offset + obj_p->name_addr) == 0) { 1130 /* found object */ 1131 if (field_id_arr == NULL) { 1132 /* return size only */ 1133 *size = obj_p->num_fields; 1134 return SOC_E_NONE; 1135 } 1136 for (j = 0; (j < obj_p->num_fields) && (j < *size); j++) { 1137 field_id_arr[j] = (fld_p + j)->name_addr; 1138 } 1139 return SOC_E_NONE; 1140 } 1141 /* next entry with the same hash key */ 1142 curr_p = (uint32 *)(fld_p + obj_p->num_fields); 1143 } 1144 return SOC_E_NOT_FOUND; 1145 } 1146 1147 /* 1148 * Function: 1149 * soc_cancun_ceh_obj_field_id_get 1150 * Purpose: 1151 * Get the field ID for the given field name 1152 * Parameters: 1153 * unit - (IN) Unit ID 1154 * field_name - (IN) object field name 1155 * field_id - (OUT) Retrieved field id 1156 * Returns: 1157 * SOC_E_XXX 1158 */ 1159 int soc_cancun_ceh_obj_field_id_get (int unit, 1160 char *field_name, 1161 uint32 *field_id) 1162 { 1163 1164 soc_cancun_t* cc; 1165 soc_cancun_ceh_t* ceh; 1166 uint32 offset; 1167 char *str_tbl; 1168 uint32 str_tbl_size; 1169 1170 cc = soc_cancun_info[unit]; 1171 if(cc == NULL) { 1172 return SOC_E_UNIT; 1173 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1174 return SOC_E_INIT; 1175 } 1176 1177 ceh = cc->ceh; 1178 1179 str_tbl_size = *SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1180 1181 /* start of string offset location */ 1182 str_tbl = (char *)SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1183 offset = 4; 1184 while ((offset < str_tbl_size) && (*(str_tbl + offset) != 0)) { 1185 if (sal_strcmp(field_name, str_tbl + offset) == 0) { 1186 *field_id = offset; 1187 return SOC_E_NONE; 1188 } 1189 offset += sal_strlen(str_tbl + offset) + 1; 1190 } 1191 return SOC_E_NOT_FOUND; 1192 } 1193 1194 /* 1195 * Function: 1196 * soc_cancun_ceh_obj_field_name_get 1197 * Purpose: 1198 * Get the object field name for the given field_id 1199 * Parameters: 1200 * unit - (IN) Unit ID 1201 * field_id - (IN) field id 1202 * size - (IN) size of the field name buffer 1203 * field_name - (OUT) field name buffer 1204 * Returns: 1205 * SOC_E_XXX 1206 */ 1207 int soc_cancun_ceh_obj_field_name_get (int unit, 1208 uint32 field_id, 1209 int *size, 1210 char *field_name) 1211 { 1212 1213 soc_cancun_t* cc; 1214 soc_cancun_ceh_t* ceh; 1215 char *str_tbl; 1216 uint32 str_tbl_size; 1217 1218 cc = soc_cancun_info[unit]; 1219 if(cc == NULL) { 1220 return SOC_E_UNIT; 1221 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1222 return SOC_E_INIT; 1223 } 1224 1225 ceh = cc->ceh; 1226 1227 str_tbl_size = *SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1228 1229 /* start of string offset location */ 1230 str_tbl = (char *)SOC_CANCUN_CEH_STR_NAME_TBL(ceh->ceh_table); 1231 1232 /* validate field_id */ 1233 if ((field_id < 4) || (field_id >= str_tbl_size) ) { 1234 return SOC_E_NOT_FOUND; 1235 } 1236 /* return size */ 1237 if (field_name == NULL) { 1238 *size = sal_strlen(str_tbl + field_id) + 1; 1239 return SOC_E_NONE; 1240 } 1241 1242 if (sal_strlen(str_tbl + field_id) < *size) { 1243 sal_strcpy(field_name, str_tbl + field_id); 1244 } else { 1245 sal_strncpy(field_name, str_tbl + field_id, *size - 1); 1246 field_name[*size - 1] = 0; 1247 } 1248 return SOC_E_NONE; 1249 } 1250 1251 /* 1252 * Function: 1253 * soc_cancun_app_dest_entry_set 1254 * Purpose: 1255 * Write to destination fields according to source table and application 1256 * Parameters: 1257 * unit - (IN) Unit ID 1258 * mem - (IN) Memory ID or Register ID 1259 * app - (IN) CANCUN application ID 1260 * Returns: 1261 * SOC_E_NONE 1262 * SOC_E_FAIL - input mem/app is NOT covered by CANCUN 1263 */ 1264 int soc_cancun_app_dest_entry_set (int unit, soc_mem_t mem, int index, soc_field_t field, int app, uint32 input) { 1265 soc_cancun_t *cc; 1266 soc_cancun_cmh_t *cmh; 1267 soc_cancun_cmh_map_t *cmh_map = NULL; 1268 soc_cancun_hash_table_t *hash_table_header; 1269 uint32 *hash_table_entry, *hash_entry, *p; 1270 uint32 d_mem, d_field_num, key, offset, value_ind=0, value_num = 0; 1271 int i, j, rv, cmh_d_mem_is_reg = 0; 1272 soc_field_t fields[SOC_MAX_MEM_FIELD_WORDS]; 1273 uint32 values[SOC_MAX_MEM_FIELD_WORDS]; 1274 1275 cc = soc_cancun_info[unit]; 1276 if(cc == NULL) { 1277 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1278 "CANCUN is not initialized\n"))); 1279 return SOC_E_INIT; 1280 } else if (!(cc->flags & SOC_CANCUN_FLAG_CMH_LOADED)) { 1281 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1282 "CMH file is not loaded\n"))); 1283 return SOC_E_INIT; 1284 } 1285 1286 cmh = cc->cmh; 1287 hash_table_header = (soc_cancun_hash_table_t*) cmh->cmh_table; 1288 hash_table_entry = &hash_table_header->table_entry; 1289 rv = _soc_cancun_hash(hash_table_header, mem, app, &key); 1290 if(rv != SOC_E_NONE) { 1291 return rv; 1292 } 1293 offset = *(hash_table_entry + key); 1294 if(offset == 0) { 1295 return SOC_E_NOT_FOUND; 1296 } 1297 hash_table_entry = &hash_table_header->table_entry + offset; 1298 hash_entry = _soc_cancun_hash_find_entry(hash_table_entry, mem, field, app); 1299 if(hash_entry == NULL) { 1300 return SOC_E_NOT_FOUND; 1301 } 1302 cmh_map = (soc_cancun_cmh_map_t *) hash_entry; 1303 1304 p = &cmh_map->dest_map_entry; 1305 if(cmh_map->format == 3 || cmh_map->format == 2) { 1306 if(cmh_map->format == 2) { 1307 value_num = cmh_map->src_value_num; 1308 for(i = 0; i < value_num; i++) { 1309 if(input == *(p+i)) { 1310 break; 1311 } 1312 } 1313 1314 if(i >= value_num) { 1315 return SOC_E_PARAM; 1316 } else { 1317 value_ind = i; 1318 } 1319 p += value_num; 1320 } 1321 1322 for(i = 0; i < cmh_map->dest_mem_num; i++) { 1323 d_mem = *p++; 1324 d_field_num = *p++; 1325 for(j = 0; j < d_field_num; j++) { 1326 fields[j] = *p++; 1327 } 1328 if(cmh_map->format == 2) { 1329 p += value_ind * d_field_num; 1330 } 1331 for(j = 0; j < d_field_num; j++) { 1332 values[j] = *p++; 1333 } 1334 if(cmh_map->format == 2) { 1335 p += (value_num - value_ind - 1) * d_field_num; 1336 } 1337 1338 cmh_d_mem_is_reg = (d_mem & SOC_CANCUN_FLAG_REG_ENUM)? 1: 0; 1339 1340 if(cmh_d_mem_is_reg) { 1341 d_mem &= ~(SOC_CANCUN_FLAG_REG_ENUM); 1342 rv = soc_reg_fields32_modify(unit, d_mem, REG_PORT_ANY, 1343 d_field_num, fields, values); 1344 } else { 1345 rv = soc_mem_fields32_modify(unit, d_mem, index, d_field_num, 1346 fields, values); 1347 } 1348 1349 if(rv != SOC_E_NONE) { 1350 return rv; 1351 } 1352 1353 /* Debug log */ 1354 if(cc->flags & SOC_CANCUN_FLAG_DEBUG_MODE) { 1355 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1356 "For index %d, mem %s, app %d\nCMH writes:\n\t%s: %s\n"), 1357 index, 1358 SOC_MEM_IS_VALID(unit, mem)? SOC_MEM_NAME(unit, mem): 1359 SOC_REG_NAME(unit,mem), 1360 app, 1361 cmh_d_mem_is_reg? "reg": "mem", 1362 cmh_d_mem_is_reg? SOC_REG_NAME(unit, d_mem): 1363 SOC_MEM_NAME(unit, d_mem))); 1364 1365 for(j = 0; j < d_field_num; j++) { 1366 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1367 "\tfield: %s, value: %d\n"), 1368 SOC_FIELD_NAME(unit, fields[j]), values[j])); 1369 } 1370 } 1371 } 1372 } else { 1373 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1374 "CMH format %d is not supported for soc_cancun_app_dest_entry_set() yet\n"), 1375 cmh_map->format)); 1376 return SOC_E_INTERNAL; 1377 } 1378 1379 return SOC_E_NONE; 1380 } 1381 1382 /* 1383 * Function: 1384 * soc_cancun_app_dest_entry_get 1385 * Purpose: 1386 * Return CANCUN destination entry by input source table and application 1387 * Parameters: 1388 * unit - (IN) Unit ID 1389 * mem - (IN) Memory ID or Register ID 1390 * app - (IN) CANCUN application ID 1391 * dest_entry - (OUT) CANCUN destination information entry 1392 * Returns: 1393 * SOC_E_NONE 1394 * SOC_E_FAIL - input mem/app is NOT covered by CMH 1395 */ 1396 int soc_cancun_app_dest_entry_get (int unit, soc_mem_t mem, int index, soc_field_t field, int app, 1397 soc_cancun_dest_entry_t *dest_entry) { 1398 1399 soc_cancun_t *cc; 1400 soc_cancun_cmh_t *cmh; 1401 soc_cancun_cmh_map_t *cmh_map = NULL; 1402 soc_cancun_hash_table_t *hash_table_header; 1403 uint32 *hash_table_entry, *hash_entry, *p; 1404 uint32 key, offset; 1405 int i, rv; 1406 1407 cc = soc_cancun_info[unit]; 1408 if(cc == NULL) { 1409 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1410 "CANCUN is not initialized\n"))); 1411 return SOC_E_INIT; 1412 } else if (!(cc->flags & SOC_CANCUN_FLAG_CMH_LOADED)) { 1413 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1414 "CMH file is not loaded\n"))); 1415 return SOC_E_INIT; 1416 } 1417 1418 cmh = cc->cmh; 1419 hash_table_header = (soc_cancun_hash_table_t*) cmh->cmh_table; 1420 hash_table_entry = &hash_table_header->table_entry; 1421 rv = _soc_cancun_hash(hash_table_header, mem, app, &key); 1422 if(rv != SOC_E_NONE) { 1423 return rv; 1424 } 1425 offset = *(hash_table_entry + key); 1426 if(offset == 0) { 1427 return SOC_E_NOT_FOUND; 1428 } 1429 hash_table_entry = &hash_table_header->table_entry + offset; 1430 hash_entry = _soc_cancun_hash_find_entry(hash_table_entry, mem, field, app); 1431 if(hash_entry == NULL) { 1432 return SOC_E_NOT_FOUND; 1433 } 1434 cmh_map = (soc_cancun_cmh_map_t *) hash_entry; 1435 1436 p = &cmh_map->dest_map_entry; 1437 if(cmh_map->format == 3) { 1438 if(cmh_map->dest_mem_num > 1) { 1439 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1440 "Only 1 destination memory for CMH format 3 for now\n"))); 1441 return SOC_E_INTERNAL; 1442 } 1443 dest_entry->dest_index_num = 0; 1444 dest_entry->dest_mems[0] = *p++; 1445 dest_entry->dest_field_num = *p++; 1446 if (dest_entry->dest_field_num > CANCUN_DEST_FIELD_NUM_MAX) { 1447 return SOC_E_INTERNAL; 1448 } 1449 for(i = 0; i < dest_entry->dest_field_num; i++) { 1450 dest_entry->dest_fields[i] = *p++; 1451 dest_entry->dest_values[i] = *p++; 1452 } 1453 } else if(cmh_map->format == 4) { 1454 if(cmh_map->dest_mem_num > CANCUN_DEST_MEM_NUM_MAX) { 1455 return SOC_E_INTERNAL; 1456 } 1457 dest_entry->dest_index_num = cmh_map->dest_mem_num; 1458 dest_entry->dest_field_num = 0; 1459 for(i = 0; i < dest_entry->dest_index_num; i++) { 1460 dest_entry->dest_mems[i] = *p++; 1461 dest_entry->dest_values[i] = *p++; 1462 } 1463 } else { 1464 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1465 "CMH format %d is not supported yet\n"), cmh_map->format)); 1466 return SOC_E_INTERNAL; 1467 } 1468 1469 return SOC_E_NONE; 1470 } 1471 1472 /* 1473 * Function: 1474 * soc_cancun_cch_list 1475 * Purpose: 1476 * Return the memory and field list of CCH coverage 1477 * Parameters: 1478 * unit - (IN) Unit ID 1479 * buf - (INOUT) buffer to load CCH coverage list 1480 * buf_len - (IN) the length of passing buffer 1481 * Returns: 1482 * SOC_E_NONE 1483 * SOC_E_FAIL 1484 * 1485 * Note: Output format of CANCUN coverage list 1486 * +-------------------+-----------------+--------------+--------------+ 1487 * | mem_num | mem_1 | field_num | field_1 | 1488 * +-------------------+-----------------+--------------+--------------+ 1489 * | field_2 | ... | mem_n | field_num_n | 1490 * +-------------------+-----------------+--------------+--------------+ 1491 * | field_n1 | field_n2 | ... | | 1492 * +-------------------+-----------------+--------------+--------------+ 1493 */ 1494 int soc_cancun_cch_list (int unit, uint32* buf, uint32 buf_len) { 1495 soc_cancun_t *pcc = soc_cancun_info[unit]; 1496 soc_cancun_cch_t *cch; 1497 soc_cancun_hash_table_t *hash_table; 1498 soc_cancun_list_t *p_mem, *p_fld; 1499 uint32 *p1, *p2, *hash_table_entry, *buf_end; 1500 uint32 i, j, key = 0; 1501 int rv; 1502 1503 if(pcc == NULL) { 1504 return SOC_E_UNIT; 1505 } else if (!(pcc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1506 return SOC_E_INIT; 1507 } else if (buf == NULL) { 1508 return SOC_E_PARAM; 1509 } 1510 1511 buf_end = buf + buf_len - 1; 1512 cch = pcc->cch; 1513 if(cch != NULL) { 1514 hash_table = (soc_cancun_hash_table_t*) cch->cch_table; 1515 hash_table_entry = &hash_table->table_entry; 1516 1517 /* mem list is always at key 0 */ 1518 p1 = hash_table_entry + *(hash_table_entry + 0); 1519 p1 = _soc_cancun_hash_find_entry(p1, 0, INVALIDf, CANCUN_APP_INVALID); 1520 if(p1 == NULL) { 1521 return SOC_E_INTERNAL; 1522 } 1523 1524 p_mem = (soc_cancun_list_t*) p1; 1525 if(buf > buf_end) { 1526 return SOC_E_MEMORY; 1527 } 1528 *buf++ = p_mem->member_num; 1529 p1 = &p_mem->members; 1530 for(i = 0; i < p_mem->member_num; i++) { 1531 if(buf > buf_end) { 1532 return SOC_E_MEMORY; 1533 } 1534 *buf++ = *p1; 1535 rv = _soc_cancun_hash(hash_table, *p1, 0, &key); 1536 if(rv != SOC_E_NONE) { 1537 return rv; 1538 } 1539 p2 = hash_table_entry + *(hash_table_entry + key); 1540 p2 = _soc_cancun_hash_find_entry(p2, *p1, SOC_CANCUN_FIELD_LISTf, 1541 CANCUN_APP_INVALID); 1542 if(p2 == NULL) { 1543 return SOC_E_INTERNAL; 1544 } 1545 1546 p_fld = (soc_cancun_list_t*) p2; 1547 *buf++ = p_fld->member_num; 1548 p2 = &p_fld->members; 1549 for(j = 0; j < p_fld->member_num; j++) { 1550 if(buf > buf_end) { 1551 return SOC_E_MEMORY; 1552 } 1553 *buf++ = *p2++; 1554 } 1555 p1++; 1556 } 1557 1558 return SOC_E_NONE; 1559 } 1560 return SOC_E_INIT; 1561 } 1562 1563 int soc_cancun_cch_reg_set(int unit, soc_reg_t reg, int index, uint64 data) { 1564 1565 soc_cancun_t *cc = NULL; 1566 soc_cancun_cch_t *cch = NULL; 1567 soc_cancun_cch_map_t *cch_map = NULL; 1568 soc_cancun_hash_table_t *hash_table_header = NULL; 1569 soc_cancun_list_t *field_list = NULL; 1570 uint32 *hash_table_entry = NULL, *p_field = NULL; 1571 uint32 *hash_entry = NULL, *p = NULL; 1572 uint32 l, key = 0, offset, val_idx = 0; 1573 uint64 rval, orval, odata64; 1574 uint64 p64; 1575 int rv; 1576 1577 cc = soc_cancun_info[unit]; 1578 if (cc == NULL) { 1579 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1580 "CANCUN is not initialized\n"))); 1581 return SOC_E_INIT; 1582 } else if (!(cc->flags & SOC_CANCUN_FLAG_CCH_LOADED)) { 1583 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1584 "CCH file is not loaded\n"))); 1585 return SOC_E_INIT; 1586 } 1587 1588 /* dealing with array register */ 1589 if (SOC_REG_ARRAY(unit, reg)) { 1590 assert(index >= 0 && index < 2 * SOC_REG_NUMELS(unit, reg)); 1591 reg += (index + 1); 1592 } 1593 1594 cch = cc->cch; 1595 hash_table_header = (soc_cancun_hash_table_t*) cch->cch_table; 1596 hash_table_entry = &hash_table_header->table_entry; 1597 rv = _soc_cancun_hash(hash_table_header, reg, 0, &key); 1598 if (rv != SOC_E_NONE) { 1599 return rv; 1600 } 1601 offset = *(hash_table_entry + key); 1602 if (offset == 0) { 1603 return SOC_E_NOT_FOUND; 1604 } 1605 hash_table_entry = &hash_table_header->table_entry + offset; 1606 1607 /* Obtain the source field list to write */ 1608 field_list = (soc_cancun_list_t *) \ 1609 _soc_cancun_hash_find_entry(hash_table_entry, reg, 1610 SOC_CANCUN_FIELD_LISTf, CANCUN_APP_INVALID); 1611 if (field_list == NULL) { 1612 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1613 "can't find field list for %s\n"), SOC_REG_NAME(unit, reg))); 1614 return SOC_E_NOT_FOUND; 1615 } 1616 1617 /* Go through CCH covered field list for this register */ 1618 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1619 rv = soc_cancun_pseudo_reg_get(unit, reg, &odata64); 1620 } else { 1621 rv = soc_reg_get(unit, reg, REG_PORT_ANY, 0, &odata64); 1622 } 1623 if (rv != SOC_E_NONE) { 1624 return rv; 1625 } 1626 1627 p_field = &field_list->members; 1628 for (l = 0; l < field_list->member_num; l++, p_field++) { 1629 hash_table_entry = &hash_table_header->table_entry; 1630 rv = _soc_cancun_hash(hash_table_header, reg, *p_field, &key); 1631 if(rv != SOC_E_NONE) { 1632 return rv; 1633 } 1634 offset = *(hash_table_entry + key); 1635 if (offset == 0) { 1636 return SOC_E_NOT_FOUND; 1637 } 1638 hash_table_entry = &hash_table_header->table_entry + offset; 1639 hash_entry = _soc_cancun_hash_find_entry(hash_table_entry, reg, 1640 *p_field, CANCUN_APP_INVALID); 1641 if (hash_entry == NULL) { 1642 return SOC_E_NOT_FOUND; 1643 } 1644 cch_map = (soc_cancun_cch_map_t *) hash_entry; 1645 1646 /* Get CCH map entry for current source field */ 1647 p = &cch_map->dest_map_entry; 1648 orval = soc_reg64_field_get(unit, reg, odata64, *p_field); 1649 rval = soc_reg64_field_get(unit, reg, data, *p_field); 1650 if (COMPILER_64_EQ(orval, rval)) { 1651 /* No value change on this field. Skip */ 1652 continue; 1653 } 1654 if (cch_map->src_value_num != 0) { 1655 for (val_idx = 0; val_idx < cch_map->src_value_num; val_idx++) { 1656 COMPILER_64_SET(p64, 0, *p++); 1657 if (COMPILER_64_EQ(rval, p64)) { 1658 break; 1659 } 1660 } 1661 if (val_idx >= cch_map->src_value_num) { 1662 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1663 "can't find source value %0X_%0X for (%s, %s)\n"), 1664 COMPILER_64_HI(data), 1665 COMPILER_64_LO(data), 1666 SOC_REG_NAME(unit, reg), 1667 SOC_FIELD_NAME(unit, *p_field))); 1668 return SOC_E_NOT_FOUND; 1669 } 1670 } 1671 1672 if (cc->flags & SOC_CANCUN_FLAG_DEBUG_MODE) { 1673 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1674 "For reg %s, field %s, value 0x%08X_%08X, CCH writes:\n"), 1675 SOC_REG_NAME(unit, reg), 1676 SOC_FIELD_NAME(unit, *p_field), 1677 COMPILER_64_HI(rval), 1678 COMPILER_64_LO(rval))); 1679 } 1680 1681 SOC_IF_ERROR_RETURN(_soc_cancun_cch_dest_set_with_idx (unit, cch_map, rval, val_idx)); 1682 } 1683 1684 return SOC_E_NONE; 1685 } 1686 1687 int soc_cancun_pseudo_reg_set(int unit, soc_reg_t reg, uint64 data) { 1688 1689 soc_cancun_t* cc = soc_cancun_info[unit]; 1690 soc_cancun_cch_t *cch; 1691 uint64 *preg, *flags; 1692 uint64 flags_read64; 1693 1694 if (!SOC_REG_IS_VALID(unit, reg)) { 1695 return SOC_E_PARAM; 1696 } 1697 1698 if(cc == NULL) { 1699 return SOC_E_UNIT; 1700 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1701 return SOC_E_INIT; 1702 } else { 1703 cch = cc->cch; 1704 } 1705 1706 if(cch->pseudo_regs == NULL) { 1707 return SOC_E_INIT; 1708 } 1709 1710 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1711 1712 flags = cch->pseudo_regs + (SOC_REG_INFO(unit, reg).offset & 0xFFFF)/ 1713 (sizeof(uint64)/sizeof(uint8)); 1714 preg = flags + 1; 1715 COMPILER_64_SET(flags_read64, 0, SOC_CANCUN_PSEUDO_REGS_FLAGS_VALID_READ); 1716 COMPILER_64_OR(*flags, flags_read64); 1717 *preg = data; 1718 return SOC_E_NONE; 1719 } else { 1720 return SOC_E_PARAM; 1721 } 1722 } 1723 1724 int soc_cancun_pseudo_reg_get(int unit, soc_reg_t reg, uint64 *data) { 1725 1726 soc_cancun_t* cc = soc_cancun_info[unit]; 1727 soc_cancun_cch_t *cch; 1728 uint64 *preg, *flags; 1729 uint64 rval64, flags_valid_read64; 1730 1731 if (!SOC_REG_IS_VALID(unit, reg)) { 1732 return SOC_E_PARAM; 1733 } 1734 1735 if(cc == NULL) { 1736 return SOC_E_UNIT; 1737 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 1738 return SOC_E_INIT; 1739 } else { 1740 cch = cc->cch; 1741 } 1742 1743 1744 if (SOC_BLOCK_IS(SOC_REG_INFO(unit, reg).block, SOC_BLK_CCH)) { 1745 1746 flags = cch->pseudo_regs + (SOC_REG_INFO(unit, reg).offset & 0xFFFF)/ 1747 (sizeof(uint64)/sizeof(uint8)); 1748 preg = flags + 1; 1749 COMPILER_64_SET(flags_valid_read64, 0, SOC_CANCUN_PSEUDO_REGS_FLAGS_VALID_READ); 1750 COMPILER_64_AND(*flags, flags_valid_read64); 1751 /* Load RESET value at first read */ 1752 1753 if (COMPILER_64_IS_ZERO(*flags)) { 1754 COMPILER_64_SET(rval64, SOC_REG_INFO(unit, reg).rst_val_hi, 1755 SOC_REG_INFO(unit, reg).rst_val_lo); 1756 COMPILER_64_OR(*flags, flags_valid_read64); 1757 *preg = rval64; 1758 } 1759 *data = *preg; 1760 return SOC_E_NONE; 1761 } else { 1762 return SOC_E_PARAM; 1763 } 1764 } 1765 1766 int _soc_cancun_cch_dest_set_with_idx (int unit, 1767 soc_cancun_cch_map_t *cch_map, uint64 data, uint32 val_idx) { 1768 1769 soc_cancun_t *cc = soc_cancun_info[unit]; 1770 uint32 *p = NULL, *p_val = NULL; 1771 uint32 i, j, k, bit_offset; 1772 uint32 d_ind_num, d_fld_num, d_mem, d_ind, d_fld; 1773 uint32 fld_max, fld_min, fld_bits, fld_words; 1774 uint32 entbuf[SOC_MAX_MEM_WORDS] = {0}; 1775 uint32 fldbuf[SOC_MAX_MEM_WORDS] = {0}; 1776 uint64 rval, rdata64, fdata64; 1777 int cch_d_mem_is_reg; 1778 soc_field_info_t *finfop = NULL; 1779 soc_mem_info_t *meminfo = NULL; 1780 uint32 rvalbuf[2]; 1781 uint32 p_shift = 0; 1782 1783 if (cch_map == NULL) { 1784 return SOC_E_PARAM; 1785 } 1786 1787 COMPILER_64_COPY(rval, data); 1788 1789 p = &cch_map->dest_map_entry + cch_map->src_value_num; 1790 for (i = 0; i < cch_map->dest_mem_num; i++) { 1791 d_mem = *p++; 1792 d_ind_num = *p++; 1793 d_fld_num = *p++; 1794 for (j = 0; j < d_ind_num; j++) { 1795 d_ind = *p++; 1796 if (d_mem & SOC_CANCUN_FLAG_REG_ENUM) { 1797 cch_d_mem_is_reg = 1; 1798 d_mem &= ~SOC_CANCUN_FLAG_REG_ENUM; 1799 SOC_IF_ERROR_RETURN( 1800 soc_reg_get(unit, d_mem, REG_PORT_ANY, 0, &rdata64)); 1801 } else { 1802 cch_d_mem_is_reg = 0; 1803 SOC_IF_ERROR_RETURN( 1804 soc_mem_read(unit, d_mem, MEM_BLOCK_ANY, d_ind, entbuf)); 1805 } 1806 1807 for (k = 0; k < d_fld_num; k++) { 1808 d_fld = *p++; 1809 fld_max = *p >> 16 & 0xFFFF; 1810 fld_min = *p++ & 0xFFFF; 1811 fld_bits = fld_max - fld_min + 1; 1812 fld_words = BITS2WORDS(fld_bits); 1813 p_shift = 2; 1814 if (cch_map->src_value_num != 0) { 1815 p_val = p + (val_idx * fld_words); 1816 p += cch_map->src_value_num * fld_words; 1817 COMPILER_64_SET(fdata64, 0, *p_val); 1818 p_shift += cch_map->src_value_num * fld_words; 1819 } else { 1820 rvalbuf[0] = COMPILER_64_LO(rval); 1821 rvalbuf[1] = COMPILER_64_HI(rval); 1822 p_val = &rvalbuf[0]; 1823 COMPILER_64_COPY(fdata64, rval); 1824 } 1825 1826 if (cch_d_mem_is_reg == 1) { 1827 SOC_FIND_FIELD(d_fld, 1828 SOC_REG_INFO(unit, d_mem).fields, 1829 SOC_REG_INFO(unit, d_mem).nFields, 1830 finfop); 1831 if (finfop == NULL) { 1832 return SOC_E_INTERNAL; 1833 } 1834 if (finfop->len != fld_bits) { 1835 uint64 rfdata64; 1836 uint64 fmask; 1837 1838 rfdata64 = soc_reg64_field_get(unit, d_mem, rdata64, 1839 d_fld); 1840 bit_offset = fld_min - finfop->bp; 1841 COMPILER_64_MASK_CREATE(fmask, fld_bits, 0); 1842 COMPILER_64_AND(fdata64, fmask); 1843 COMPILER_64_SHL(fdata64, bit_offset); 1844 COMPILER_64_SHL(fmask, bit_offset); 1845 COMPILER_64_NOT(fmask); 1846 COMPILER_64_AND(rfdata64, fmask); 1847 COMPILER_64_OR(fdata64, rfdata64); 1848 } 1849 soc_reg64_field_set(unit, d_mem, &rdata64, d_fld, fdata64); 1850 1851 if (cc->flags & SOC_CANCUN_FLAG_DEBUG_MODE) { 1852 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1853 "\t%s.%s = 0x%08X_%08X\n"), 1854 SOC_REG_NAME(unit, d_mem), 1855 SOC_FIELD_NAME(unit, d_fld), 1856 COMPILER_64_HI(fdata64), 1857 COMPILER_64_LO(fdata64))); 1858 } 1859 } else { 1860 /* Bit shift if needed */ 1861 1862 meminfo = &SOC_MEM_INFO(unit, d_mem); 1863 SOC_FIND_FIELD(d_fld, 1864 meminfo->fields, 1865 meminfo->nFields, 1866 finfop); 1867 if (finfop == NULL) { 1868 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1869 "\t special field num detected: %d,%d \n"), d_fld_num, k)); 1870 p -= p_shift; 1871 1872 break; 1873 } 1874 1875 soc_mem_field_get(unit, d_mem, entbuf, d_fld, fldbuf); 1876 1877 if (finfop->len != fld_bits) { 1878 bit_offset = fld_min - finfop->bp; 1879 SHR_BITCOPY_RANGE(fldbuf, bit_offset, p_val, 0, fld_bits); 1880 } else { 1881 SHR_BITCOPY_RANGE(fldbuf, 0, p_val, 0, fld_bits); 1882 } 1883 1884 soc_mem_field_set(unit, d_mem, entbuf, d_fld, fldbuf); 1885 1886 if (cc->flags & SOC_CANCUN_FLAG_DEBUG_MODE) { 1887 char *fldbuf_str = sal_alloc(sizeof(char) * 1888 ((SOC_MAX_MEM_FIELD_WORDS * 8) + 3), 1889 "soc_cancun_debug_cch_str"); 1890 if (fldbuf_str != NULL) { 1891 _shr_format_long_integer(fldbuf_str, fldbuf, 1892 BITS2BYTES(finfop->len)); 1893 1894 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1895 "\t%s[%d].%s = %s\n"), 1896 SOC_MEM_NAME(unit, d_mem), 1897 d_ind, 1898 SOC_FIELD_NAME(unit, d_fld), 1899 fldbuf_str)); 1900 sal_free(fldbuf_str); 1901 } 1902 } 1903 } 1904 } 1905 1906 if (cch_d_mem_is_reg == 1) { 1907 SOC_IF_ERROR_RETURN(soc_reg_set(unit, d_mem, 1908 REG_PORT_ANY, 0, rdata64)); 1909 } else { 1910 SOC_IF_ERROR_RETURN(soc_mem_write(unit, d_mem, 1911 MEM_BLOCK_ALL, d_ind, entbuf)); 1912 } 1913 } 1914 } 1915 1916 return SOC_E_NONE; 1917 1918 } 1919 1920 int _soc_cancun_cch_dest_set (int unit, 1921 soc_cancun_cch_map_t *cch_map, uint64 data) { 1922 return _soc_cancun_cch_dest_set_with_idx (unit, cch_map, data, 0x0); 1923 } 1924 1925 /* 1926 * Function: 1927 * soc_cancun_cch_app_set 1928 * Purpose: 1929 * Configure memory field values according to application 1930 * Parameters: 1931 * unit - (IN) Unit ID 1932 * src_app - (IN) Source application ID 1933 * data - (IN) Memory field value 1934 * 1935 * Returns: 1936 * SOC_E_NONE 1937 * SOC_E_FAIL 1938 * SOC_E_INTERNAL - CCH tables are not loaded 1939 * SOC_E_PARAM - Input parameters are invalid 1940 * SOC_E_NOT_FOUND - Input mem/reg/field are not found in CCH 1941 * 1942 * Note: 1943 * CCH entry format 4 is shown as following. * 1944 * +----------+-----------------+-------------------+--------------+ 1945 * | size | format | src_mem | src_field | 1946 * +----------+-----------------+-------------------+--------------+ 1947 * | src_app | val_num | dest_tab_num | ... | 1948 * +----------+-----------------+-------------------+--------------+ 1949 * | dest_tab | dest_index_num | dest_field_num | ... | 1950 * +----------+-----------------+-------------------+--------------+ 1951 * | index | dest_field | field_max_min_bit | ... | 1952 * +----------+-----------------+-------------------+--------------+ 1953 */ 1954 int soc_cancun_cch_app_set (int unit, uint32 src_app, uint64 data) { 1955 1956 soc_cancun_t *cc = NULL; 1957 soc_cancun_cch_t *cch = NULL; 1958 soc_cancun_cch_map_t *cch_map = NULL; 1959 soc_cancun_hash_table_t *hash_table_header = NULL; 1960 uint32 *hash_table_entry = NULL; 1961 uint32 *hash_entry = NULL; 1962 uint32 offset = 0; 1963 uint32 key = 0; 1964 int rv = 0; 1965 1966 cc = soc_cancun_info[unit]; 1967 if (cc == NULL) { 1968 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1969 "CANCUN is not initialized\n"))); 1970 return SOC_E_INIT; 1971 } else if (!(cc->flags & SOC_CANCUN_FLAG_CCH_LOADED)) { 1972 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 1973 "CCH file is not loaded\n"))); 1974 return SOC_E_INIT; 1975 } 1976 1977 cch = cc->cch; 1978 hash_table_header = (soc_cancun_hash_table_t*) cch->cch_table; 1979 hash_table_entry = &hash_table_header->table_entry; 1980 rv = _soc_cancun_hash (hash_table_header, 0, src_app, &key); 1981 if (rv != SOC_E_NONE) { 1982 return rv; 1983 } 1984 offset = *(hash_table_entry + key); 1985 if (offset == 0) { 1986 return SOC_E_NOT_FOUND; 1987 } 1988 hash_table_entry = &hash_table_header->table_entry + offset; 1989 hash_entry = _soc_cancun_hash_find_entry(hash_table_entry, INVALIDm, 1990 INVALIDf, src_app); 1991 if (hash_entry == NULL) { 1992 return SOC_E_NOT_FOUND; 1993 } 1994 1995 cch_map = (soc_cancun_cch_map_t *) hash_entry; 1996 SOC_IF_ERROR_RETURN(_soc_cancun_cch_dest_set (unit, cch_map, data)); 1997 1998 return SOC_E_NONE; 1999 } 2000 2001 2002 int _soc_cancun_load_status_clear(int unit, soc_cancun_file_type_e file_type) { 2003 soc_cancun_t *cc = soc_cancun_info[unit]; 2004 uint32 *status; 2005 2006 if(cc == NULL) { 2007 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2008 "CANCUN is not initialized\n"))); 2009 return SOC_E_INIT; 2010 } else { 2011 status = NULL; 2012 switch (file_type) { 2013 case CANCUN_SOC_FILE_TYPE_CIH: 2014 status = &cc->cih->status; 2015 break; 2016 case CANCUN_SOC_FILE_TYPE_CMH: 2017 status = &cc->cmh->status; 2018 break; 2019 case CANCUN_SOC_FILE_TYPE_CCH: 2020 status = &cc->cch->status; 2021 break; 2022 default: 2023 return SOC_E_PARAM; 2024 } 2025 } 2026 2027 if(status == NULL) { 2028 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2029 "CANCUN %s is not loaded\n"), 2030 soc_chip_type_names[file_type])); 2031 return SOC_E_INIT; 2032 } 2033 2034 *status = SOC_CANCUN_LOAD_STATUS_NOT_LOADED; 2035 2036 return SOC_E_NONE; 2037 } 2038 2039 int soc_cancun_access_scan(int unit, soc_cancun_file_type_e file_type) { 2040 soc_cancun_t *cc = soc_cancun_info[unit]; 2041 soc_cancun_cmh_t *cmh = NULL; 2042 soc_cancun_cch_t *cch = NULL; 2043 soc_cancun_cmh_map_t *cmh_map = NULL; 2044 soc_cancun_cch_map_t *cch_map = NULL; 2045 soc_cancun_hash_table_t *hash_table_header; 2046 uint32 *hash_table_entry, *p; 2047 uint32 i, j, k, l, offset, entry_num, field_num, index_num, dest_mem, pass = 1; 2048 2049 if(cc == NULL) { 2050 return SOC_E_UNIT; 2051 } else if (!(cc->flags & SOC_CANCUN_FLAG_INITIALIZED)) { 2052 return SOC_E_INIT; 2053 } 2054 2055 if(file_type == CANCUN_SOC_FILE_TYPE_CMH) { 2056 cmh = cc->cmh; 2057 hash_table_header = (soc_cancun_hash_table_t*) cmh->cmh_table; 2058 for(i = 0; i < hash_table_header->pd; i++) { 2059 hash_table_entry = &hash_table_header->table_entry; 2060 offset = *(hash_table_entry + i); 2061 if(offset == 0) { 2062 continue; 2063 } 2064 hash_table_entry = &hash_table_header->table_entry + offset; 2065 entry_num = *hash_table_entry++; 2066 cmh_map = (soc_cancun_cmh_map_t *) hash_table_entry; 2067 for(j = 0; j < entry_num; j++) { 2068 if (cmh_map->format == 1) { 2069 pass &= _soc_cancun_enum_check(unit, 0, cmh_map->src_mem, 2070 SOC_CANCUN_ENUM_TYPE_MEM); 2071 pass &= _soc_cancun_enum_check(unit, cmh_map->src_mem, 2072 cmh_map->src_field, 2073 SOC_CANCUN_ENUM_TYPE_MEM_FIELD); 2074 p = &cmh_map->dest_map_entry + cmh_map->src_value_num; 2075 for(k = 0; k < cmh_map->dest_mem_num; k++) { 2076 dest_mem = *p++; 2077 pass &= _soc_cancun_enum_check(unit, 0, dest_mem, 2078 SOC_CANCUN_ENUM_TYPE_MEM); 2079 field_num = *p++; 2080 for(l = 0; l < field_num; l++) { 2081 pass &= _soc_cancun_enum_check(unit, dest_mem, *p++, 2082 SOC_CANCUN_ENUM_TYPE_MEM_FIELD); 2083 } 2084 p += field_num * cmh_map->src_value_num; 2085 } 2086 /* TO-DO: Add format 2~4 */ 2087 } else { 2088 LOG_DEBUG(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2089 "Scan for CMH format %d is not yet supported\n"), 2090 cmh_map->format)); 2091 continue; 2092 } 2093 } 2094 } 2095 } else if(file_type == CANCUN_SOC_FILE_TYPE_CCH) { 2096 cch = cc->cch; 2097 hash_table_header = (soc_cancun_hash_table_t*) cch->cch_table; 2098 for(i = 0; i < hash_table_header->pd; i++) { 2099 hash_table_entry = &hash_table_header->table_entry; 2100 offset = *(hash_table_entry + i); 2101 if(offset == 0) { 2102 continue; 2103 } 2104 hash_table_entry = &hash_table_header->table_entry + offset; 2105 entry_num = *hash_table_entry++; 2106 cch_map = (soc_cancun_cch_map_t *) hash_table_entry; 2107 for(j = 0; j < entry_num; j++) { 2108 if(cch_map->src_mem != 0 && cch_map->src_field != 0) { 2109 pass &= _soc_cancun_enum_check(unit, 0, cch_map->src_mem, 2110 SOC_CANCUN_ENUM_TYPE_REG); 2111 if (cch_map->format == 1 || 2112 cch_map->format == 2 || 2113 cch_map->format == 3) { 2114 pass &= _soc_cancun_enum_check(unit, cch_map->src_mem, 2115 cch_map->src_field, 2116 SOC_CANCUN_ENUM_TYPE_REG_FIELD); 2117 p = &cch_map->dest_map_entry + cch_map->src_value_num; 2118 for(k = 0; k < cch_map->dest_mem_num; k++) { 2119 dest_mem = *p++; 2120 pass &= _soc_cancun_enum_check(unit, 0, dest_mem, 2121 SOC_CANCUN_ENUM_TYPE_MEM); 2122 index_num = *p++; 2123 field_num = *p; 2124 p += 2; 2125 for(l = 0; l < field_num; l++) { 2126 pass &= _soc_cancun_enum_check(unit, dest_mem, *p, 2127 SOC_CANCUN_ENUM_TYPE_MEM_FIELD); 2128 p += (cch_map->src_value_num + 2); 2129 } 2130 if(index_num > 1) { 2131 p += (index_num - 1) * field_num * 2132 (2 + cch_map->src_value_num) + 1; 2133 } 2134 } 2135 } else { 2136 LOG_DEBUG(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2137 "Scan for CCH format %d is not yet supported\n"), 2138 cch_map->format)); 2139 continue; 2140 } 2141 } 2142 hash_table_entry += cch_map->entry_size; 2143 cch_map = (soc_cancun_cch_map_t *) hash_table_entry; 2144 } 2145 } 2146 } else { 2147 return SOC_E_PARAM; 2148 } 2149 2150 if(pass) { 2151 return SOC_E_NONE; 2152 } else { 2153 return SOC_E_FAIL; 2154 } 2155 } 2156 2157 /* 2158 * Internal Functions 2159 */ 2160 static int _soc_cancun_alloc(soc_cancun_t** cancun) { 2161 soc_cancun_t* cc; 2162 2163 cc = sal_alloc(sizeof(soc_cancun_t), "soc_cancun_info"); 2164 if(cc == NULL) { 2165 goto _soc_cancun_alloc_error; 2166 } 2167 sal_memset(cc, 0, sizeof(soc_cancun_t)); 2168 2169 cc->cih = sal_alloc(sizeof(soc_cancun_cih_t), "soc_cancun_cih"); 2170 if(cc->cih == NULL) { 2171 goto _soc_cancun_alloc_error; 2172 } 2173 sal_memset(cc->cih, 0, sizeof(soc_cancun_cih_t)); 2174 2175 cc->cmh = sal_alloc(sizeof(soc_cancun_cmh_t), "soc_cancun_cmh"); 2176 if(cc->cmh == NULL) { 2177 goto _soc_cancun_alloc_error; 2178 } 2179 sal_memset(cc->cmh, 0, sizeof(soc_cancun_cmh_t)); 2180 2181 cc->cch = sal_alloc(sizeof(soc_cancun_cch_t), "soc_cancun_cch"); 2182 if(cc->cch == NULL) { 2183 goto _soc_cancun_alloc_error; 2184 } 2185 2186 sal_memset(cc->cch, 0, sizeof(soc_cancun_cch_t)); 2187 cc->flow_db = sal_alloc(sizeof(soc_flow_db_t), "soc_flow_db"); 2188 if(cc->flow_db == NULL) { 2189 goto _soc_cancun_alloc_error; 2190 } 2191 sal_memset(cc->flow_db, 0, sizeof(soc_flow_db_t)); 2192 2193 cc->ceh = sal_alloc(sizeof(soc_cancun_ceh_t), "soc_cancun_ceh"); 2194 if(cc->ceh == NULL) { 2195 goto _soc_cancun_alloc_error; 2196 } 2197 sal_memset(cc->ceh, 0, sizeof(soc_cancun_ceh_t)); 2198 2199 *cancun = cc; 2200 2201 return 0; 2202 2203 _soc_cancun_alloc_error: 2204 if(cc) { 2205 if(cc->cih) { 2206 sal_free(cc->cih); 2207 } 2208 if(cc->cmh) { 2209 sal_free(cc->cmh); 2210 } 2211 if(cc->cch) { 2212 sal_free(cc->cch); 2213 } 2214 if (cc->flow_db) { 2215 sal_free(cc->flow_db); 2216 } 2217 if(cc->ceh) { 2218 sal_free(cc->ceh); 2219 } 2220 sal_free(cc); 2221 } 2222 2223 return -1; 2224 } 2225 2226 static int _soc_cancun_file_pio_load(int unit, uint8* buf, int buf_words) { 2227 long schan_msg_len_words, msg_num, i; 2228 schan_msg_t* msg; 2229 int index; 2230 2231 schan_msg_len_words = CMIC_SCHAN_WORDS(unit); 2232 msg_num = buf_words / schan_msg_len_words; 2233 msg = (schan_msg_t*) buf; 2234 2235 for(i = 0; i < msg_num; i++) { 2236 #if _PCID_TEST 2237 { 2238 int j; 2239 for(j = 0; j< schan_msg_len_words; j++) { 2240 msg->dwords[j] = soc_htonl(msg->dwords[j]); 2241 cli_out("0x%x ", msg->dwords[j]); 2242 } 2243 cli_out("\n"); 2244 index = 0; 2245 } 2246 #else 2247 index = soc_schan_op(unit, msg, schan_msg_len_words, 2248 schan_msg_len_words, 0); 2249 #endif 2250 if (index < 0) { 2251 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2252 "S-Channel operation failed: %s\n"), soc_errmsg(index))); 2253 return SOC_E_FAIL; 2254 } 2255 msg++; 2256 } 2257 2258 return SOC_E_NONE; 2259 } 2260 2261 static int _soc_cancun_file_cmh_load(int unit, uint8* buf, int buf_words) { 2262 soc_cancun_cmh_t *cmh = soc_cancun_info[unit]->cmh; 2263 2264 if(cmh == NULL) { 2265 return SOC_E_INIT; 2266 } else if (buf_words <= 0) { 2267 return SOC_E_PARAM; 2268 } 2269 2270 /* NOTE: We do not have sal_realloc in our libc so need to free and then 2271 * re-alloc here for a new CMH load*/ 2272 if(cmh->cmh_table) { 2273 sal_free(cmh->cmh_table); 2274 } 2275 cmh->cmh_table = sal_alloc((BYTES_PER_UINT32 * buf_words), 2276 "soc_cancun_cmh_table"); 2277 if(cmh->cmh_table == NULL) { 2278 return SOC_E_MEMORY; 2279 } 2280 2281 _soc_cancun_memcpy_letohl((uint32 *)cmh->cmh_table, (uint32 *)buf, buf_words); 2282 2283 return _soc_cancun_cmh_list_update(cmh); 2284 2285 } 2286 2287 static int _soc_cancun_cmh_list_update(soc_cancun_cmh_t *cmh) { 2288 soc_cancun_hash_table_t *hash_table; 2289 soc_cancun_cmh_map_t *cmh_map_entry; 2290 uint32 *p_hask_key, *p_entry, *p_list; 2291 uint32 entry_num, list_element_count = 0; 2292 int i; 2293 2294 hash_table = (soc_cancun_hash_table_t*) cmh->cmh_table; 2295 2296 if(cmh->cmh_list) { 2297 sal_free(cmh->cmh_list); 2298 } 2299 cmh->cmh_list = sal_alloc((BYTES_PER_UINT32 * 2300 (hash_table->entry_num * 3 + 1)), 2301 "soc_cancun_cmh_list"); 2302 if(cmh->cmh_list == NULL) { 2303 return SOC_E_MEMORY; 2304 } 2305 2306 p_hask_key = &hash_table->table_entry; 2307 p_list = cmh->cmh_list + 1; 2308 for(i = 0; i < hash_table->pd; i++) { 2309 if(p_hask_key[i] != 0) { 2310 p_entry = p_hask_key + p_hask_key[i]; 2311 entry_num = *p_entry++; 2312 cmh_map_entry = (soc_cancun_cmh_map_t*) p_entry; 2313 while(entry_num-- > 0) { 2314 *p_list++ = cmh_map_entry->src_mem; 2315 *p_list++ = cmh_map_entry->src_field; 2316 *p_list++ = cmh_map_entry->src_app; 2317 list_element_count++; 2318 if(entry_num > 0) { 2319 p_entry += cmh_map_entry->entry_size; 2320 cmh_map_entry = (soc_cancun_cmh_map_t*) p_entry; 2321 } 2322 } 2323 } 2324 } 2325 *cmh->cmh_list = list_element_count; 2326 2327 return SOC_E_NONE; 2328 } 2329 2330 static int _soc_cancun_file_cch_load(int unit, uint8* buf, int buf_words) { 2331 soc_cancun_cch_t *cch = soc_cancun_info[unit]->cch; 2332 2333 if(cch == NULL) { 2334 return SOC_E_INIT; 2335 } else if (buf_words <= 0) { 2336 return SOC_E_PARAM; 2337 } 2338 2339 /* NOTE: We do not have sal_realloc in our libc so need to free and then 2340 * re-alloc here for a new CCH load*/ 2341 if(cch->cch_table) { 2342 sal_free(cch->cch_table); 2343 } 2344 cch->cch_table = sal_alloc((BYTES_PER_UINT32 * buf_words), 2345 "soc_cancun_cch_table"); 2346 if(cch->cch_table == NULL) { 2347 return SOC_E_MEMORY; 2348 } 2349 2350 if(cch->pseudo_regs) { 2351 sal_free(cch->pseudo_regs); 2352 } 2353 cch->pseudo_regs = (uint64*) sal_alloc(SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE, 2354 "soc_cancun_cch_pseudo_regs"); 2355 if(cch->pseudo_regs == NULL) { 2356 return SOC_E_MEMORY; 2357 } 2358 sal_memset(cch->pseudo_regs, 0, SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE); 2359 2360 #ifdef BCM_WARM_BOOT_SUPPORT 2361 if (SOC_WARM_BOOT(unit)) { 2362 (void)soc_cancun_scache_recovery(unit); 2363 } 2364 #endif /* BCM_WARM_BOOT_SUPPORT */ 2365 2366 _soc_cancun_memcpy_letohl((uint32 *)cch->cch_table, (uint32 *)buf, buf_words); 2367 2368 return SOC_E_NONE; 2369 2370 } 2371 2372 static int _soc_cancun_file_ceh_load(int unit, uint8* buf, int buf_words) 2373 { 2374 uint8 *cur_dst; 2375 uint8 *cur_src; 2376 int cur_len; 2377 int str_tbl_len; 2378 int rem_len; 2379 soc_cancun_ceh_t *ceh = soc_cancun_info[unit]->ceh; 2380 2381 if(ceh == NULL) { 2382 return SOC_E_INIT; 2383 } else if (buf_words <= 0) { 2384 return SOC_E_PARAM; 2385 } 2386 2387 /* NOTE: We do not have sal_realloc in our libc so need to free and then 2388 * re-alloc here for a new CEH load*/ 2389 if(ceh->ceh_table) { 2390 sal_free(ceh->ceh_table); 2391 } 2392 ceh->ceh_table = sal_alloc((BYTES_PER_UINT32 * buf_words), 2393 "soc_cancun_ceh_table"); 2394 if(ceh->ceh_table == NULL) { 2395 return SOC_E_MEMORY; 2396 } 2397 2398 cur_dst = (uint8 *)ceh->ceh_table; 2399 cur_src = buf; 2400 cur_len = SOC_CANCUN_CEH_BLOCK_HASH_HEADER_LEN * BYTES_PER_UINT32; 2401 rem_len = buf_words * BYTES_PER_UINT32; 2402 2403 /* load block and hash header */ 2404 sal_memcpy(cur_dst, cur_src,cur_len); 2405 soc_cancun_buf_swap32(cur_dst, cur_len); 2406 2407 /* next, string table len */ 2408 cur_dst += cur_len; 2409 cur_src += cur_len; 2410 rem_len -= cur_len; 2411 cur_len = BYTES_PER_UINT32; 2412 sal_memcpy(cur_dst, cur_src,cur_len); 2413 soc_cancun_buf_swap32(cur_dst, cur_len); 2414 2415 /* no endianness to convert for string table. Just copy */ 2416 str_tbl_len = *(uint32 *)cur_dst; 2417 cur_dst += cur_len; 2418 cur_src += cur_len; 2419 rem_len -= cur_len; 2420 cur_len = str_tbl_len - BYTES_PER_UINT32; 2421 sal_memcpy(cur_dst,cur_src, cur_len); 2422 2423 /* convert rest of buffer */ 2424 cur_dst += cur_len; 2425 cur_src += cur_len; 2426 rem_len -= cur_len; 2427 sal_memcpy(cur_dst, cur_src,rem_len); 2428 soc_cancun_buf_swap32(cur_dst, rem_len); 2429 2430 return SOC_E_NONE; 2431 } 2432 2433 static int _soc_cancun_hash(soc_cancun_hash_table_t* t, uint32 mem, 2434 soc_field_t field, uint32* key) { 2435 2436 if((t == NULL) || (key == NULL)) { 2437 return SOC_E_PARAM; 2438 } 2439 2440 /* generalized hash function */ 2441 *key = (t->pa * field + t->pa * mem + t->pc) % t->pd; 2442 2443 return SOC_E_NONE; 2444 } 2445 2446 static int _soc_cancun_cih_load(int unit, uint8* buf, int num_data_blobs) { 2447 int i; 2448 uint32 length, flags; 2449 2450 for (i = 0; i < num_data_blobs; i++) { 2451 /* Length and flags fields are offset by 8 and 12 bytes from start of 2452 * each data blob */ 2453 length = *(uint32 *)(buf + SOC_CANCUN_CIH_LENGTH_OFFSET); 2454 flags = *(uint32 *)(buf + SOC_CANCUN_CIH_FLAG_OFFSET); 2455 2456 /* Blob data format */ 2457 switch (flags & SOC_CANCUN_BLOB_FORMAT_MASK) { 2458 case SOC_CANCUN_BLOB_FORMAT_PIO: 2459 SOC_IF_ERROR_RETURN 2460 (_soc_cancun_cih_pio_load(unit, buf, length, flags)); 2461 buf += (sizeof(uint32) * SOC_CANCUN_CIH_PIO_DATA_BLOB_SIZE); 2462 break; 2463 case SOC_CANCUN_BLOB_FORMAT_DMA: 2464 break; 2465 case SOC_CANCUN_BLOB_FORMAT_FIFO: 2466 break; 2467 case SOC_CANCUN_BLOB_FORMAT_RSVD: 2468 break; 2469 default: 2470 return SOC_E_PARAM; 2471 } 2472 } 2473 return SOC_E_NONE; 2474 } 2475 2476 static int _soc_cancun_cih_pio_load(int unit, uint8* buf, int length, 2477 uint32 flags) { 2478 schan_msg_t msg; 2479 int i, index; 2480 uint32 *p = (uint32 *) buf; 2481 int rv; 2482 2483 sal_memset(&msg, 0, sizeof(schan_msg_t)); 2484 2485 if (flags & SOC_CANCUN_BLOB_FLAG_MEM_ID_PRESENT) { 2486 return _soc_cancun_cih_mem_load(unit, buf); 2487 } 2488 2489 /* Special case of TCAM memory loading */ 2490 if (flags & SOC_CANCUN_BLOB_FLAG_TCAM) { 2491 rv = _soc_cancun_cih_tcam_write(unit, buf); 2492 return rv; 2493 } 2494 2495 /* Copy destination address to schan msg structure */ 2496 msg.dwords[1] = *p++; 2497 2498 /* Copy opcode to schan msg structure */ 2499 msg.dwords[0] = *p++; 2500 2501 /* Copy data to schan msg structure */ 2502 p += 2; /* skip length and flag */ 2503 for(i = 0; i < length ; i++) { 2504 msg.dwords[2+i] = *p++; 2505 } 2506 2507 for(i = 0; i < length + 2; i++) { 2508 LOG_VERBOSE(BSL_LS_SOC_CANCUN, 2509 (BSL_META_U(unit, "0x%x "), msg.dwords[i])); 2510 } 2511 LOG_VERBOSE(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "\n"))); 2512 2513 #if _PCID_TEST 2514 { 2515 int j; 2516 for(j = 0; j < length+2; j++) { 2517 msg.dwords[j] = soc_htonl(msg.dwords[j]); 2518 cli_out("0x%x ", msg.dwords[j]); 2519 } 2520 cli_out("\n"); 2521 index = 0; 2522 } 2523 #else 2524 index = soc_schan_op(unit, &msg, length+2, length+2, 0); 2525 #endif 2526 2527 if (index < 0) { 2528 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2529 "S-Channel operation failed: %s\n"), soc_errmsg(index))); 2530 return SOC_E_FAIL; 2531 } 2532 2533 return SOC_E_NONE; 2534 2535 } 2536 2537 static int _soc_cancun_cih_tcam_write(int unit, uint8 *buf) { 2538 #define SOC_SBUS_V4_BLOCK_ID_BIT_OFFSET (19) 2539 #define SOC_SBUS_V4_BLOCK_ID_BIT_MASK (0x7F) 2540 uint32 entry[SOC_MAX_MEM_WORDS]; 2541 soc_mem_t mem; 2542 uint32 index; 2543 uint32 offset; 2544 uint32 block = -1; 2545 uint32 len; 2546 uint32 *p = (uint32*) buf; 2547 2548 if(!buf) { 2549 return SOC_E_INTERNAL; 2550 } 2551 2552 if (soc_feature(unit, soc_feature_xy_tcam)) { 2553 if (soc_feature(unit, soc_feature_sbus_format_v4)) { 2554 block = (*(p + SOC_CANCUN_BLOB_OPCODE_OFFSET) >> 2555 SOC_SBUS_V4_BLOCK_ID_BIT_OFFSET) 2556 & SOC_SBUS_V4_BLOCK_ID_BIT_MASK; 2557 } else { 2558 return SOC_E_UNAVAIL; 2559 } 2560 2561 mem = soc_addr_to_mem_extended(unit, block, -1, *p); 2562 if(mem == INVALIDm) { 2563 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2564 "can't find TCAM memory for addr = 0x%x\n"), *p)); 2565 return SOC_E_INTERNAL; 2566 } 2567 2568 index = SOC_MEM_INFO(unit, mem).index_min + 2569 ((*p - SOC_MEM_INFO(unit, mem).base) / 2570 SOC_MEM_INFO(unit, mem).gran); 2571 if(index > SOC_MEM_INFO(unit, mem).index_max) { 2572 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2573 "ERROR: index = %d exceeds max of %s (%d)\n"), index, 2574 SOC_MEM_NAME(unit, mem), 2575 SOC_MEM_INFO(unit, mem).index_max)); 2576 return SOC_E_INTERNAL; 2577 } 2578 2579 offset = *p - (SOC_MEM_INFO(unit, mem).base + 2580 (index * SOC_MEM_INFO(unit, mem).gran)); 2581 2582 len = *(p + SOC_CANCUN_BLOB_LEN_OFFSET); 2583 2584 SOC_IF_ERROR_RETURN( 2585 soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 2586 2587 _soc_cancun_memcpy_letohl((entry + offset), (p + SOC_CANCUN_BLOB_DATA_OFFSET), len); 2588 2589 SOC_IF_ERROR_RETURN( 2590 soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 2591 2592 return SOC_E_NONE; 2593 2594 } else { 2595 return SOC_E_UNAVAIL; 2596 } 2597 } 2598 2599 static int _soc_cancun_cih_mem_load(int unit, uint8 *buf) { 2600 uint32 entry[SOC_MAX_MEM_WORDS]; 2601 uint32 addr; 2602 soc_mem_t mem; 2603 uint32 index; 2604 uint32 len; 2605 uint32 *p = (uint32*)buf; 2606 2607 addr = *p; 2608 mem = addr >> SOC_CANCUN_BLOB_ADDR_MEM_ID_SHIFT; 2609 index = addr & SOC_CANCUN_BLOB_ADDR_MEM_IDX_MASK; 2610 2611 len = *(p + SOC_CANCUN_BLOB_LEN_OFFSET); 2612 sal_memset(entry, 0, sizeof(entry)); 2613 sal_memcpy(entry, (p + SOC_CANCUN_BLOB_DATA_OFFSET), len*4); 2614 2615 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry); 2616 } 2617 2618 static uint32* _soc_cancun_hash_find_entry(uint32 *hash_entry, uint32 src_mem, 2619 uint32 src_field, int src_app) { 2620 2621 soc_cancun_entry_hdr_t *p_hdr; 2622 uint32 entry_num, i; 2623 uint32 *p; 2624 2625 if(hash_entry == NULL) { 2626 return NULL; 2627 } 2628 2629 entry_num = *hash_entry; 2630 p = hash_entry + 1; 2631 p_hdr = (soc_cancun_entry_hdr_t*) p; 2632 2633 for(i = 0; i < entry_num; i++) { 2634 if(p_hdr->src_mem == src_mem) { 2635 2636 if(src_field == INVALIDf || 2637 p_hdr->src_field == src_field) { 2638 2639 if(src_app == CANCUN_APP_INVALID || 2640 p_hdr->src_app == src_app) { 2641 return p; 2642 } 2643 } 2644 } 2645 2646 p = p + p_hdr->entry_size; 2647 p_hdr = (soc_cancun_entry_hdr_t*) p; 2648 2649 } 2650 2651 return NULL; 2652 } 2653 2654 static int _soc_cancun_memcpy_letohl(uint32 *des, uint32 *src, uint32 word_len) { 2655 uint32 i; 2656 2657 if (des == NULL || src == NULL) { 2658 return SOC_E_INTERNAL; 2659 } 2660 2661 for (i = 0; i < word_len; i++) { 2662 *des++ = *src++; 2663 } 2664 2665 return SOC_E_NONE; 2666 } 2667 2668 static int _soc_cancun_enum_check(int unit, int regmem, int enum_val, int enum_type) { 2669 if(enum_type == SOC_CANCUN_ENUM_TYPE_APP) { 2670 if(enum_val >= CANCUN_APP_NUM) { 2671 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "app: %d\n"), 2672 enum_val)); 2673 return 0; 2674 } 2675 return 1; 2676 } 2677 2678 if(enum_type == SOC_CANCUN_ENUM_TYPE_MEM) { 2679 if(!SOC_MEM_IS_VALID(unit, enum_val)) { 2680 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "%sm\n"), 2681 SOC_MEM_NAME(unit, enum_val))); 2682 return 0; 2683 } 2684 return 1; 2685 } 2686 2687 if(enum_type == SOC_CANCUN_ENUM_TYPE_REG) { 2688 if(!SOC_REG_IS_VALID(unit, enum_val)) { 2689 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "%sr\n"), 2690 SOC_REG_NAME(unit, enum_val))); 2691 return 0; 2692 } 2693 return 1; 2694 } 2695 2696 if(enum_type == SOC_CANCUN_ENUM_TYPE_MEM_FIELD) { 2697 if(!SOC_MEM_FIELD_VALID(unit, regmem, enum_val)) { 2698 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "%sm.%sf\n"), 2699 SOC_MEM_NAME(unit, regmem), SOC_FIELD_NAME(unit, enum_val))); 2700 return 0; 2701 } 2702 return 1; 2703 } 2704 if(enum_type == SOC_CANCUN_ENUM_TYPE_REG_FIELD) { 2705 if(!SOC_REG_FIELD_VALID(unit, regmem, enum_val)) { 2706 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "%sr.%sf\n"), 2707 SOC_REG_NAME(unit, regmem), SOC_FIELD_NAME(unit, enum_val))); 2708 return 0; 2709 } 2710 return 1; 2711 } 2712 2713 LOG_INFO(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "enum type %d not valid\n"), 2714 enum_type)); 2715 return 0; 2716 } 2717 2718 /* ZLIB CRC-32 routine */ 2719 uint32 soc_cancun_crc32(uint32 crc, uint8 *buf, int len_bytes) { 2720 2721 #define DO1(buf) crc = soc_crc32_tab[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); 2722 #define DO2(buf) DO1(buf); DO1(buf); 2723 #define DO4(buf) DO2(buf); DO2(buf); 2724 #define DO8(buf) DO4(buf); DO4(buf); 2725 2726 if (buf == NULL) return 0L; 2727 crc = crc ^ 0xffffffffL; 2728 2729 while (len_bytes >= 8) 2730 { 2731 DO8(buf); 2732 len_bytes -= 8; 2733 } 2734 2735 if (len_bytes) do { 2736 DO1(buf); 2737 } while (--len_bytes); 2738 2739 return crc ^ 0xffffffffL; 2740 } 2741 2742 #ifdef BCM_WARM_BOOT_SUPPORT 2743 /* Version_1_0: 2744 * 60 registers * 256 bytes each 2745 * Version_1_1: 2746 * Newly added: 100 registers * 256 bytes each 2747 */ 2748 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 2749 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1, 1) 2750 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 2751 2752 int 2753 soc_cancun_scache_alloc(int unit) 2754 { 2755 int stable_size; 2756 int rv = SOC_E_NONE; 2757 soc_scache_handle_t scache_handle; 2758 uint8 *cancun_scache_ptr; 2759 uint32 alloc_size; 2760 2761 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2762 2763 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 2764 return SOC_E_NONE; 2765 } 2766 2767 alloc_size = SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE; 2768 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_CANCUN_HANDLE, 0); 2769 2770 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 2771 TRUE, &alloc_size, 2772 &cancun_scache_ptr, 2773 BCM_WB_DEFAULT_VERSION, 2774 NULL); 2775 2776 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 2777 return rv; 2778 } 2779 2780 return SOC_E_NONE; 2781 } 2782 2783 int 2784 soc_cancun_scache_sync(int unit) 2785 { 2786 int stable_size; 2787 int rv = SOC_E_NONE; 2788 soc_scache_handle_t scache_handle; 2789 uint8 *cancun_scache_ptr; 2790 uint32 alloc_size; 2791 soc_cancun_cch_t *cch = soc_cancun_info[unit]->cch; 2792 2793 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2794 2795 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 2796 return SOC_E_NONE; 2797 } 2798 2799 alloc_size = SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE; 2800 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_CANCUN_HANDLE, 0); 2801 2802 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 2803 FALSE, &alloc_size, 2804 &cancun_scache_ptr, 2805 BCM_WB_DEFAULT_VERSION, 2806 NULL); 2807 2808 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 2809 return rv; 2810 } 2811 2812 if((cch != NULL) && (cch->pseudo_regs != NULL)) { 2813 sal_memcpy(cancun_scache_ptr, cch->pseudo_regs, alloc_size); 2814 } 2815 2816 return SOC_E_NONE; 2817 } 2818 2819 int 2820 soc_cancun_scache_recovery(int unit) 2821 { 2822 int stable_size; 2823 int rv = SOC_E_NONE; 2824 soc_scache_handle_t scache_handle; 2825 uint8 *cancun_scache_ptr; 2826 uint32 alloc_size; 2827 uint16 recovered_ver = 0; 2828 soc_cancun_cch_t *cch = soc_cancun_info[unit]->cch; 2829 uint32 tmp_size = 0; 2830 2831 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2832 2833 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 2834 return SOC_E_NONE; 2835 } 2836 2837 alloc_size = SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE; 2838 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_CANCUN_HANDLE, 0); 2839 2840 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 2841 FALSE, &tmp_size, 2842 &cancun_scache_ptr, 2843 BCM_WB_DEFAULT_VERSION, 2844 &recovered_ver); 2845 2846 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 2847 return rv; 2848 } else if (rv == SOC_E_NOT_FOUND) { 2849 return soc_cancun_scache_alloc(unit); 2850 } else { 2851 if (tmp_size < alloc_size ) { 2852 SOC_IF_ERROR_RETURN(soc_cancun_scache_alloc(unit)); 2853 } 2854 } 2855 if (cancun_scache_ptr != NULL) { 2856 if ((cch != NULL) && (cch->pseudo_regs != NULL)) { 2857 if (recovered_ver >= BCM_WB_VERSION_1_1) { 2858 tmp_size = SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE; 2859 } else if (recovered_ver >= BCM_WB_VERSION_1_0) { 2860 tmp_size = SOC_CANCUN_PSEUDO_REGS_BLOCK_BYTE_SIZE_V0; 2861 } 2862 sal_memcpy(cch->pseudo_regs, cancun_scache_ptr, tmp_size); 2863 } 2864 } 2865 2866 return SOC_E_NONE; 2867 } 2868 #endif /* BCM_WARM_BOOT_SUPPORT */ 2869 2870 int soc_cancun_branch_id_get(int unit, uint32 cancun_type, 2871 soc_cancun_file_branch_id_e *branch_id) { 2872 int rv = SOC_E_NONE; 2873 2874 if ((cancun_type < CANCUN_SOC_FILE_TYPE_CIH) || 2875 (cancun_type > CANCUN_SOC_FILE_TYPE_CEH)) { 2876 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2877 "Unsupported cancun type\n"))); 2878 return SOC_E_PARAM; 2879 } 2880 2881 #ifndef NO_FILEIO 2882 { 2883 soc_cancun_t *cc = NULL; 2884 uint32 version = 0; 2885 2886 rv = soc_cancun_status_get(unit, &cc); 2887 if(rv != SOC_E_NONE) { 2888 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2889 "can't get CANCUN status. (%s)\n"), soc_errmsg(rv))); 2890 return rv; 2891 } 2892 if (cancun_type == CANCUN_SOC_FILE_TYPE_CCH) { 2893 version = cc->cch->version; 2894 } else if (cancun_type == CANCUN_SOC_FILE_TYPE_CMH) { 2895 version = cc->cmh->version; 2896 } else if (cancun_type == CANCUN_SOC_FILE_TYPE_CEH) { 2897 version = cc->ceh->version; 2898 } else if (cancun_type == CANCUN_SOC_FILE_TYPE_CFH) { 2899 version = cc->flow_db->version; 2900 } else { 2901 /* return CIH version by default */ 2902 version = cc->cih->version; 2903 } 2904 2905 *branch_id = (version >> CANCUN_VERSION_OFFSET_BRANCH_ID) & 0xF; 2906 } 2907 #else 2908 { 2909 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "No file system\n"))); 2910 2911 return SOC_E_UNAVAIL; 2912 } 2913 #endif 2914 2915 return rv; 2916 } 2917 2918 2919 /* 2920 * Function: 2921 * soc_cancun_udf_abstr_type_info_get 2922 * Purpose: 2923 * Get udf abstact packet type info 2924 * Parameters: 2925 * unit - (IN) Unit ID 2926 * abstract_type - (IN) abstract type 2927 * parser - (IN) parser identifier 2928 * max_stages - (IN) size of stage info array 2929 * hfe_prof_ptr_arr - (IN) HFE profile pointer array associated to 2930 * each stage for a given abstract type. 2931 * stage_info_arr - (OUT) Array of Stage Info structures 2932 * actual_stage_num - (OUT) num of stages associated given abstract type. 2933 * hfe_prof_ptr_arr_len - (OUT) HFE prof pointer array len. 2934 * 2935 * Returns: 2936 * SOC_E_NONE 2937 * SOC_E_FAIL 2938 * SOC_E_INTERNAL - UDF DB is not loaded 2939 * SOC_E_PARAM - Input parameters are invalid 2940 * SOC_E_NOT_FOUND - stage info is not found 2941 * 2942 * Note: 2943 * CCH entry format 5 (UDF) is shown as following. * 2944 * +------------+-----------------+-------------------+-------------------+ 2945 * | size | format | src_mem(INVALID) | src_field(INVALID)| 2946 * +------------+-----------------+-------------------+-------------------+ 2947 * | src_app | stage_info_num | size | policy_mem | 2948 * +------------+-----------------+-------------------+-------------------+ 2949 * |hfe_pro_ptr | start_pos | flags | size | 2950 * +------------+-----------------+-------------------+-------------------+ 2951 * | policy_mem | hfe_pro_ptr | start_pos | flags | 2952 * +------------+-----------------+-------------------+-------------------+ 2953 */ 2954 int soc_cancun_udf_abstr_type_info_get(int unit, 2955 uint32 abstract_type, 2956 uint32 parser, 2957 uint32 max_stages, 2958 uint32 **hfe_prof_ptr_arr, 2959 soc_cancun_udf_stage_info_t *stage_info_arr, 2960 uint32 *actual_stage_num, 2961 uint32 *hfe_prof_ptr_arr_len) { 2962 2963 soc_cancun_t *cc = NULL; 2964 soc_cancun_cch_t *cch = NULL; 2965 soc_cancun_hash_table_t *hash_table_header = NULL; 2966 soc_cancun_cch_map_t *cch_map = NULL; 2967 uint32 *hash_table_entry = NULL; 2968 uint32 *hash_entry = NULL; 2969 uint32 offset = 0; 2970 uint32 key = 0; 2971 uint8 stg; 2972 int rv = 0; 2973 uint32 src_app = 0; 2974 uint32 stage_info_num = 0; 2975 2976 cc = soc_cancun_info[unit]; 2977 if (cc == NULL) { 2978 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2979 "CANCUN is not initialized\n"))); 2980 return SOC_E_INIT; 2981 } else if (!(cc->flags & SOC_CANCUN_FLAG_CCH_LOADED)) { 2982 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 2983 "CCH file is not loaded\n"))); 2984 return SOC_E_INIT; 2985 } 2986 2987 cch = cc->cch; 2988 hash_table_header = (soc_cancun_hash_table_t*) cch->cch_table; 2989 hash_table_entry = &hash_table_header->table_entry; 2990 /* combine parse and abstract type as "srcapp" */ 2991 src_app = (parser << 16) + abstract_type; 2992 rv = _soc_cancun_hash (hash_table_header, 0, src_app, &key); 2993 if (rv != SOC_E_NONE) { 2994 return rv; 2995 } 2996 offset = *(hash_table_entry + key); 2997 if (offset == 0) { 2998 return SOC_E_NOT_FOUND; 2999 } 3000 hash_table_entry = &hash_table_header->table_entry + offset; 3001 hash_entry = _soc_cancun_hash_find_entry(hash_table_entry, INVALIDm, 3002 INVALIDf, src_app); 3003 if (hash_entry == NULL) { 3004 return SOC_E_NOT_FOUND; 3005 } 3006 3007 cch_map = (soc_cancun_cch_map_t *) hash_entry; 3008 3009 stage_info_num = cch_map->src_value_num; 3010 if (actual_stage_num != NULL) { 3011 *actual_stage_num = stage_info_num; 3012 } 3013 3014 if (max_stages > stage_info_num) { 3015 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 3016 "stage_info_num (%d) less than expected (%d)\n"), 3017 stage_info_num, max_stages)); 3018 return SOC_E_PARAM; 3019 } 3020 3021 if (hfe_prof_ptr_arr_len != NULL) { 3022 uint32 *info_ptr; 3023 soc_cancun_udf_stage_info_t *abstr_type_info; 3024 3025 info_ptr = &(cch_map->dest_mem_num); 3026 for (stg = 0; stg < stage_info_num; stg++) { 3027 abstr_type_info = (soc_cancun_udf_stage_info_t *)info_ptr; 3028 hfe_prof_ptr_arr_len[stg] = abstr_type_info->hfe_prof_ptr_arr_len; 3029 info_ptr += 6; /* increment till hfe_prof_ptr */ 3030 info_ptr += hfe_prof_ptr_arr_len[stg]; 3031 } 3032 } 3033 3034 if (stage_info_arr != NULL) { 3035 uint8 ct; 3036 uint32 *info_ptr; 3037 soc_cancun_udf_stage_info_t *info_arr = stage_info_arr; 3038 3039 info_ptr = &(cch_map->dest_mem_num); 3040 for (stg = 0; stg < max_stages; stg++) { 3041 info_arr->size = *info_ptr; 3042 info_ptr++; 3043 info_arr->policy_mem = *info_ptr; 3044 info_ptr++; 3045 info_arr->start_pos = *info_ptr; 3046 info_ptr++; 3047 info_arr->unavail_contbmap = *info_ptr; 3048 info_ptr++; 3049 info_arr->flags = *info_ptr; 3050 info_ptr++; 3051 info_arr->hfe_prof_ptr_arr_len = *info_ptr; 3052 info_ptr++; 3053 3054 if (hfe_prof_ptr_arr[stg] == NULL) { 3055 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 3056 "NULL hfe_prof_ptr for stage:%d\n"), stg)); 3057 return SOC_E_PARAM; 3058 } 3059 3060 info_arr->hfe_profile_ptr = hfe_prof_ptr_arr[stg]; 3061 for (ct = 0; ct < info_arr->hfe_prof_ptr_arr_len; ct++) { 3062 info_arr->hfe_profile_ptr[ct] = *info_ptr; 3063 info_ptr++; 3064 } 3065 info_arr++; 3066 } 3067 } 3068 3069 return SOC_E_NONE; 3070 } 3071 3072 int soc_cancun_version_get(int unit, uint32* cancun_ver) { 3073 int rv = SOC_E_NONE; 3074 3075 #ifndef NO_FILEIO 3076 { 3077 soc_cancun_t *cc = NULL; 3078 3079 rv = soc_cancun_status_get(unit, &cc); 3080 if(rv != SOC_E_NONE) { 3081 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 3082 "can't get CANCUN status. (%s)\n"), soc_errmsg(rv))); 3083 return rv; 3084 } 3085 *cancun_ver = (cc->cih->version & (~CANCUN_VERSION_REVISION_MASK)); 3086 } 3087 #else 3088 { 3089 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "No file system\n"))); 3090 3091 return SOC_E_UNAVAIL; 3092 } 3093 #endif 3094 3095 return rv; 3096 } 3097 3098 int soc_cancun_revision_get(int unit, uint32* revision) { 3099 int rv = SOC_E_NONE; 3100 3101 #ifndef NO_FILEIO 3102 { 3103 soc_cancun_t *cc = NULL; 3104 3105 rv = soc_cancun_status_get(unit, &cc); 3106 if(rv != SOC_E_NONE) { 3107 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, 3108 "can't get CANCUN status. (%s)\n"), soc_errmsg(rv))); 3109 return rv; 3110 } 3111 *revision = (cc->cih->version >> CANCUN_VERSION_OFFSET_REVISION) & 0xF; 3112 } 3113 #else 3114 { 3115 LOG_ERROR(BSL_LS_SOC_CANCUN, (BSL_META_U(unit, "No file system\n"))); 3116 3117 return SOC_E_UNAVAIL; 3118 } 3119 #endif 3120 3121 return rv; 3122 }