cmicsim.c (149518B)
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 * The part of PCID that simulates the cmic 8 * 9 * Requires: 10 * 11 * Provides: 12 * soc_internal_pcic_init 13 * soc_internal_read 14 * soc_internal_write 15 * soc_internal_reset 16 * soc_internal_vlan_tab_init 17 * soc_internal_memory_fetch 18 * soc_internal_memory_store 19 * soc_internal_manual_hash 20 * soc_internal_vlan_tab_init 21 * soc_internal_manual_hash 22 * soc_internal_send_int 23 * soc_internal_table_dma 24 * soc_internal_schan_ctrl_write 25 */ 26 27 #include <shared/bsl.h> 28 29 #include <unistd.h> 30 #include <stdlib.h> 31 32 #include <sys/types.h> 33 #include <sys/time.h> 34 #include <soc/mem.h> 35 #include <soc/hash.h> 36 37 #include <soc/cmic.h> 38 #ifdef BCM_CMICM_SUPPORT 39 #include <soc/cmicm.h> 40 #endif 41 #include <soc/drv.h> 42 #include <soc/debug.h> 43 #include <sal/appl/io.h> 44 #include <bde/pli/verinet.h> 45 46 #include "pcid.h" 47 #include "mem.h" 48 #include "cmicsim.h" 49 #include "dma.h" 50 #ifdef BCM_ISM_SUPPORT 51 #include "ism.h" 52 #endif 53 54 /* 55 * PCI Config Space Simulation 56 */ 57 58 void 59 soc_internal_pcic_init(pcid_info_t *pcid_info, uint16 pci_dev_id, 60 uint16 pci_ven_id, uint8 pci_rev_id, uint32 pci_mbar0) 61 { 62 /* PCI ID's translated at higher level */ 63 64 /* Device ID (16b), Vendor ID (16b) */ 65 PCIC(pcid_info, 0x00) = (pci_dev_id << 16) | pci_ven_id; 66 67 /* Status (16b), Command (16b) */ 68 PCIC(pcid_info, 0x04) = 0x04800046; 69 70 /* Class Code (24b), Rev ID (8b) */ 71 PCIC(pcid_info, 0x08) = 0x02800000 | pci_rev_id; 72 73 /* BIST, Hdr Type, Lat Timer, Cache Line Size */ 74 PCIC(pcid_info, 0x0c) = 0x00002008; 75 76 /* BAR0 */ 77 PCIC(pcid_info, 0x10) = pci_mbar0; 78 79 /* BAR1 */ 80 PCIC(pcid_info, 0x14) = 0x00000000; 81 82 /* BAR2 */ 83 PCIC(pcid_info, 0x18) = 0x00000000; 84 85 /* BAR3 */ 86 PCIC(pcid_info, 0x1c) = 0x00000000; 87 88 /* BAR4 */ 89 PCIC(pcid_info, 0x20) = 0x00000000; 90 91 /* BAR5 */ 92 PCIC(pcid_info, 0x24) = 0x00000000; 93 94 /* Cardbus CIS Pointer */ 95 PCIC(pcid_info, 0x28) = 0x00000000; 96 97 /* Subsystem ID (16b), Subsystem Vendor ID (16b) */ 98 PCIC(pcid_info, 0x2c) = 0x00000000; 99 100 /* Expansion ROM base addr */ 101 PCIC(pcid_info, 0x30) = 0x00000000; 102 103 /* Reserved (24b), Capabilities Ptr (8b) */ 104 PCIC(pcid_info, 0x34) = 0x00000000; 105 106 /* Reserved */ 107 PCIC(pcid_info, 0x38) = 0x00000000; 108 109 /* Max_Lat, Min_Gnt, Int Pin, Int Line */ 110 PCIC(pcid_info, 0x3c) = 0x0000010b; 111 112 /* Retry_Timeout, TRDY_Timeout */ 113 PCIC(pcid_info, 0x40) = 0x00008080; 114 115 /* Retry_Timeout, TRDY_Timeout */ 116 PCIC(pcid_info, 0x44) = 0x00000000; 117 } 118 119 int 120 soc_internal_write_reg(pcid_info_t *pcid_info, uint32 address, uint32 *data) 121 { 122 soc_regaddrinfo_t ainfo; 123 int rv; 124 125 soc_regaddrinfo_get(pcid_info->unit, &ainfo, address); 126 127 if (!ainfo.valid || ainfo.reg < 0) { 128 LOG_WARN(BSL_LS_SOC_COMMON, 129 (BSL_META("Attempt to write to unknown S-channel address 0x%x\n"), 130 address)); 131 } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 132 SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & 133 SOC_REG_FLAG_RO) { 134 LOG_WARN(BSL_LS_SOC_COMMON, 135 (BSL_META("Attempt to write to read-only S-channel address 0x%x\n"), 136 address)); 137 } 138 139 #if defined(BCM_FIREBOLT_SUPPORT) 140 /* 141 ** Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block 142 */ 143 if (SOC_IS_FB_FX_HX(pcid_info->unit)) { 144 int blk; 145 int unit = pcid_info->unit; 146 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20; 147 if (((address & 0x00f80000) == blk) 148 && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12))) { 149 if ((ainfo.reg == ICOS_SELr) || 150 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASKr) || 151 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASKr) || 152 (ainfo.reg == IBCAST_BLOCK_MASKr) || 153 (ainfo.reg == IEMIRROR_CONTROLr) || 154 (ainfo.reg == IMIRROR_CONTROLr) || 155 #if defined(BCM_RAPTOR_SUPPORT) 156 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASK_HIr) || 157 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASK_HIr) || 158 (ainfo.reg == IBCAST_BLOCK_MASK_HIr) || 159 (ainfo.reg == IEMIRROR_CONTROL_HIr) || 160 #endif /* BCM_RAPTOR_SUPPORT */ 161 0) { 162 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20; 163 address = (address & ~(0x00f00000)) | blk; 164 } 165 } 166 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20; 167 if (((address & 0x00f80000) == blk) 168 && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12))) { 169 blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20; 170 address = (address & ~(0x00f00000)) | blk; 171 } 172 } 173 #endif /* BCM_FIREBOLT_SUPPORT */ 174 175 #if defined(BCM_RAVEN_SUPPORT) 176 if (SOC_IS_RAVEN(pcid_info->unit)) { 177 if (ainfo.reg == COMMAND_CONFIGr) { 178 uint32 old_data[2]; 179 if (soc_internal_read_reg(pcid_info, address, old_data) >= 0) { 180 if (soc_reg_field_get(pcid_info->unit, COMMAND_CONFIGr, 181 data[0], SW_RESETf) == 0) { 182 /* 183 * Warn if any field is modified without UNIMAC in reset. 184 */ 185 uint32 cc_rst; 186 cc_rst = data[0] ^ old_data[0]; 187 soc_reg_field_set(pcid_info->unit, COMMAND_CONFIGr, 188 &cc_rst, SW_RESETf, 0); 189 if (cc_rst) { 190 LOG_WARN(BSL_LS_SOC_COMMON, 191 (BSL_META("UNIMAC: Attempt to Modify COMMAND_CONFIG without MAC in reset old = 0x%08X new = 0x%08X\n"), old_data[0], data[0])); 192 } 193 } 194 } 195 } 196 } 197 #endif /* BCM_RAVEN_SUPPORT */ 198 199 #ifdef BCM_TRIDENT_SUPPORT 200 if (soc_feature(pcid_info->unit, soc_feature_logical_port_num)) { 201 soc_info_t *si; 202 int phy_port; 203 int blk; 204 205 si = &SOC_INFO(pcid_info->unit); 206 switch (ainfo.reg) { 207 case EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr: 208 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, data[0], 209 PHYSICAL_PORT_NUMBERf); 210 if (phy_port != 0x7f) { 211 si->port_p2l_mapping[phy_port] = ainfo.port; 212 si->port_l2p_mapping[ainfo.port] = phy_port; 213 blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port); 214 si->port_type[ainfo.port] = 215 SOC_BLOCK_INFO(pcid_info->unit, blk).type; 216 if (ainfo.port > si->port.max) { 217 si->port.max = ainfo.port; 218 } 219 } 220 break; 221 case MMU_TO_PHY_PORT_MAPPINGr: 222 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, data[0], 223 PHY_PORTf); 224 if (phy_port != 0x7f) { 225 si->port_p2m_mapping[phy_port] = ainfo.idx & 0x7f; 226 si->port_m2p_mapping[ainfo.idx & 0x7f] = phy_port; 227 } 228 break; 229 default: 230 break; 231 } 232 } 233 #endif /* BCM_TRIDENT_SUPPORT */ 234 235 rv = soc_datum_reg_write(pcid_info, ainfo, 0, address, data); 236 237 return rv; 238 } 239 240 int 241 soc_internal_read_reg(pcid_info_t *pcid_info, uint32 address, uint32 *data) 242 { 243 soc_regaddrinfo_t ainfo; 244 int rv; 245 246 soc_regaddrinfo_get(pcid_info->unit, &ainfo, address); 247 248 if (!ainfo.valid || ainfo.reg < 0) { 249 LOG_ERROR(BSL_LS_SOC_COMMON, 250 (BSL_META("Attempt to read from unknown S-channel address 0x%x\n"), 251 address)); 252 } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 253 SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & SOC_REG_FLAG_WO) { 254 LOG_WARN(BSL_LS_SOC_COMMON, 255 (BSL_META("Attempt to read from write-only S-channel address 0x%x\n"), 256 address)); 257 } 258 259 #if defined(BCM_FIREBOLT_SUPPORT) 260 /* 261 ** Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block 262 ** Well not really. Some of the registers are Higig only. 263 */ 264 if (SOC_IS_FB_FX_HX(pcid_info->unit)) { 265 int blk; 266 int unit = pcid_info->unit; 267 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20; 268 if (((address & 0x00f80000) == blk) 269 && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12))) { 270 if ((ainfo.reg == ICOS_SELr) || 271 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASKr) || 272 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASKr) || 273 (ainfo.reg == IBCAST_BLOCK_MASKr) || 274 (ainfo.reg == IEMIRROR_CONTROLr) || 275 (ainfo.reg == IMIRROR_CONTROLr) || 276 #if defined(BCM_RAPTOR_SUPPORT) 277 (ainfo.reg == IUNKNOWN_UCAST_BLOCK_MASK_HIr) || 278 (ainfo.reg == IUNKNOWN_MCAST_BLOCK_MASK_HIr) || 279 (ainfo.reg == IBCAST_BLOCK_MASK_HIr) || 280 (ainfo.reg == IEMIRROR_CONTROL_HIr) || 281 #endif /* BCM_RAPTOR_SUPPORT */ 282 0) { 283 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20; 284 address = (address & ~(0x00f00000)) | blk; 285 soc_regaddrinfo_get(pcid_info->unit, &ainfo, address); 286 } 287 } 288 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20; 289 if (((address & 0x00f80000) == blk) 290 && ((address & 0x0001f000) != (CMIC_PORT(unit) << 12))) { 291 blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20; 292 address = (address & ~(0x00f00000)) | blk; 293 soc_regaddrinfo_get(pcid_info->unit, &ainfo, address); 294 } 295 } 296 #endif /* BCM_FIREBOLT_SUPPORT */ 297 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \ 298 || defined(BCM_RAPTOR_SUPPORT) 299 /* 300 ** Patch over array registers with different reset values 301 */ 302 if (SOC_IS_FIREBOLT2(pcid_info->unit) || SOC_IS_TRX(pcid_info->unit) || 303 SOC_IS_RAVEN(pcid_info->unit) || SOC_IS_HAWKEYE(pcid_info->unit)) { 304 if (ainfo.reg == EGR_OUTER_TPIDr) { 305 switch (address & 0x3) { 306 case 0: 307 ainfo.reg = EGR_OUTER_TPID_0r; 308 break; 309 case 1: 310 ainfo.reg = EGR_OUTER_TPID_1r; 311 break; 312 case 2: 313 ainfo.reg = EGR_OUTER_TPID_2r; 314 break; 315 case 3: 316 ainfo.reg = EGR_OUTER_TPID_3r; 317 break; 318 /* coverity[dead_error_begin] */ 319 default: 320 break; 321 } 322 ainfo.idx = -1; 323 } 324 if (ainfo.reg == ING_OUTER_TPIDr) { 325 switch (address & 0x3) { 326 case 0: 327 ainfo.reg = ING_OUTER_TPID_0r; 328 break; 329 case 1: 330 ainfo.reg = ING_OUTER_TPID_1r; 331 break; 332 case 2: 333 ainfo.reg = ING_OUTER_TPID_2r; 334 break; 335 case 3: 336 ainfo.reg = ING_OUTER_TPID_3r; 337 break; 338 /* coverity[dead_error_begin] */ 339 default: 340 break; 341 } 342 ainfo.idx = -1; 343 } 344 } 345 #if defined(BCM_TRIUMPH_SUPPORT) 346 if (SOC_IS_TR_VL(pcid_info->unit)) { 347 if (ainfo.reg == ING_MPLS_TPIDr) { 348 switch (address & 0x3) { 349 case 0: 350 ainfo.reg = ING_MPLS_TPID_0r; 351 break; 352 case 1: 353 ainfo.reg = ING_MPLS_TPID_1r; 354 break; 355 case 2: 356 ainfo.reg = ING_MPLS_TPID_2r; 357 break; 358 case 3: 359 ainfo.reg = ING_MPLS_TPID_3r; 360 break; 361 /* coverity[dead_error_begin] */ 362 default: 363 break; 364 } 365 ainfo.idx = -1; 366 } 367 } 368 #endif /* BCM_TRIUMPH_SUPPORT */ 369 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT 370 || BCM_RAPTOR_SUPPORT */ 371 rv = soc_datum_reg_read(pcid_info, ainfo, 0, address, data); 372 373 if (SOC_E_NONE == rv) { 374 /* Chip specific register value patches */ 375 #if defined(BCM_FIREBOLT_SUPPORT) 376 if (SOC_IS_TRX(pcid_info->unit)) { 377 /* 378 * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1 379 * returns DONE=1 380 */ 381 if (SOC_IS_TD_TT(pcid_info->unit)) { 382 if (address == 0x180003) { /* ING_HW_RESET_CONTROL_2 */ 383 data[0] |= (1 << 18); 384 } 385 if (address == 0x280001) { /* EGR_HW_RESET_CONTROL_1 */ 386 data[0] |= (1 << 18); 387 } 388 } else if (SOC_IS_TRIUMPH2(pcid_info->unit) || 389 SOC_IS_APOLLO(pcid_info->unit)) { 390 if (address == 0x080003) { /* ING_HW_RESET_CONTROL_2 */ 391 data[0] |= (1 << 18); 392 } 393 if (address == 0x180001) { /* EGR_HW_RESET_CONTROL_1 */ 394 data[0] |= (1 << 18); 395 } 396 } else { 397 if (address == 0xa80003) { /* ING_HW_RESET_CONTROL_2 */ 398 data[0] |= (1 << 18); 399 } 400 if (address == 0xb80001) { /* EGR_HW_RESET_CONTROL_1 */ 401 data[0] |= (1 << 18); 402 } 403 } 404 } 405 else if (SOC_IS_FB_FX_HX(pcid_info->unit)) { 406 /* 407 * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1 408 * returns DONE=1 409 */ 410 if (address == 0x780002) { /* ING_HW_RESET_CONTROL_2 */ 411 data[0] |= (1 << 18); 412 } 413 if (address == 0x980001) { /* EGR_HW_RESET_CONTROL_1 */ 414 data[0] |= (1 << 18); 415 } 416 } 417 else if (SOC_IS_HBX(pcid_info->unit)) { 418 /* 419 * Reading ING_HW_RESET_CONTROL_2/EGR_HW_RESET_CONTROL_1 420 * returns DONE=1 421 */ 422 if (address == 0x180203) { /* ING_HW_RESET_CONTROL_2_X */ 423 data[0] |= (1 << 18); 424 } 425 if (address == 0x180403) { /* ING_HW_RESET_CONTROL_2_Y */ 426 data[0] |= (1 << 18); 427 } 428 if (address == 0x180603) { /* ING_HW_RESET_CONTROL_2 */ 429 data[0] |= (1 << 18); 430 } 431 if (address == 0x480601) { /* EGR_HW_RESET_CONTROL_1 */ 432 data[0] |= (1 << 18); 433 } 434 } 435 #endif /* BCM_FIREBOLT_SUPPORT */ 436 return 0; 437 } else if (SOC_E_NOT_FOUND == rv) { 438 439 /* 440 * The register is not in the hash table, so it has not been written 441 * before. Provide a default value. 442 */ 443 if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 444 (ainfo.valid && ainfo.reg >= 0)) { 445 /*This macro handle both 64 and above_64 regs*/ 446 SOC_REG_ABOVE_64_RST_VAL_GET(pcid_info->unit, ainfo.reg, data); 447 } else { 448 data[0] = 0xffffffff; 449 data[1] = 0xffffffff; 450 } 451 452 rv = SOC_E_NONE; 453 454 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) 455 if (SOC_IS_FX_HX(pcid_info->unit)) { 456 if (address == 0xb80210) { /* BSAFE_GLB_DEV_STATUS */ 457 data[0] |= (1 << 7); /* PROD_CFG_VLD */ 458 } 459 if (address == 0xb8020c) { /* BSAFE_GLB_PROD_CFG */ 460 data[0] |= (pcid_info->opt_gbp_wid << 8); /* LMD_ENABLE */ 461 } 462 } 463 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT */ 464 #ifdef BCM_HERCULES_SUPPORT 465 if (SOC_IS_HERCULES15(pcid_info->unit) && 466 (address & 0xff0fffff) == 0x00000202) { 467 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */ 468 data[0] |= 0x00000008; 469 } 470 #endif /* BCM_HERCULES_SUPPORT */ 471 472 #if defined(BCM_FIREBOLT_SUPPORT) 473 if (SOC_IS_FB(pcid_info->unit) || 474 SOC_IS_HELIX(pcid_info->unit) || 475 SOC_IS_FELIX(pcid_info->unit)) { 476 if (address == 0x00200002 || /* MAC_XGXS_STAT.XE0 */ 477 address == 0x00300002 || /* MAC_XGXS_STAT.XE1 */ 478 address == 0x00400002 || /* MAC_XGXS_STAT.XE2 */ 479 address == 0x00500002) { /* MAX_XGXS_STAT_XE3 */ 480 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */ 481 data[0] |= 0x00000008; 482 } 483 } 484 #endif /* BCM_FIREBOLT_SUPPORT */ 485 #if defined(BCM_BRADLEY_SUPPORT) 486 if (SOC_IS_HBX(pcid_info->unit)) { 487 if ((address & 0xfff00fff) == 0x000002) { /* MAX_XGXS_STAT */ 488 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */ 489 data[0] |= 0x00000020; 490 } 491 } 492 #endif /* BCM_BRADLEY_SUPPORT */ 493 #if defined(BCM_TRIUMPH_SUPPORT) 494 if (SOC_IS_TR_VL(pcid_info->unit)) { 495 if (address == 0x00200002 || /* MAC_XGXS_STAT.XE0 */ 496 address == 0x00300002 || /* MAC_XGXS_STAT.XE1 */ 497 address == 0x00400002 || /* MAC_XGXS_STAT.XE2 */ 498 address == 0x00500002 || /* MAC_XGXS_STAT.XE3 */ 499 address == 0x00600002 || /* MAC_XGXS_STAT.XE4 */ 500 address == 0x00700002 || /* MAC_XGXS_STAT.XE5 */ 501 address == 0x00800002 || /* MAC_XGXS_STAT.XE6 */ 502 address == 0x00900002) { /* MAX_XGXS_STAT.XE7 */ 503 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */ 504 data[0] |= 0x00000020; 505 } 506 } 507 #endif /* BCM_TRIUMPH_SUPPORT */ 508 #if defined(BCM_TRIUMPH2_SUPPORT) 509 if (SOC_IS_TRIUMPH2(pcid_info->unit) || SOC_IS_APOLLO(pcid_info->unit) || 510 SOC_IS_VALKYRIE2(pcid_info->unit)) { 511 if (address == 0x800002 || /* MAC_XGXS_STAT.XP0 */ 512 address == 0x900002 || /* MAC_XGXS_STAT.XP1 */ 513 address == 0xa00002 || /* MAC_XGXS_STAT.XP2 */ 514 address == 0xb00002 || /* MAC_XGXS_STAT.XP3 */ 515 address == 0x40000002 || /* MAC_XGXS_STAT.XQ0 */ 516 address == 0x40100002 || /* MAC_XGXS_STAT.XQ1 */ 517 address == 0x40200002 || /* MAC_XGXS_STAT.XQ2 */ 518 address == 0x40300002 || /* MAC_XGXS_STAT.XQ3 */ 519 address == 0x40400002 || /* MAC_XGXS_STAT.XQ4 */ 520 address == 0x40500002) { /* MAX_XGXS_STAT.XQ5 */ 521 /* Reading MAC_XGXS_STAT returns PLL_LOCK=1 */ 522 data[0] |= 0x00000020; 523 } 524 } 525 #endif /* BCM_TRIUMPH2_SUPPORT */ 526 } else { 527 LOG_ERROR(BSL_LS_SOC_COMMON, 528 (BSL_META("RPC error: soc_internalreg_read failed %d. \n"), rv)); 529 } 530 531 return rv; 532 } 533 534 int 535 soc_internal_write_bytes(pcid_info_t *pcid_info, uint32 address, uint8 *data, 536 int len) 537 { 538 uint32 temp[SOC_MAX_MEM_WORDS]; 539 540 if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) { 541 return 1; 542 } 543 544 /* writing bytes is supported only for bcmsim */ 545 if ((pcid_info->regmem_cb) && 546 (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, 547 (uint32 *)data, (len * 8)) == 0)) { 548 return 0; 549 } 550 551 /* if no registered call-back, default to write_mem */ 552 sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32))); 553 sal_memcpy(temp, data, len); 554 return soc_internal_write_mem(pcid_info, address, temp); 555 556 } 557 558 int 559 soc_internal_write_mem(pcid_info_t *pcid_info, uint32 address, uint32 *data) 560 { 561 soc_mem_t mem; 562 int rv; 563 564 if ((pcid_info->regmem_cb) 565 && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, data, 566 ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) { 567 return 0; 568 } 569 570 if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) { 571 #ifdef BCM_FIREBOLT_SUPPORT 572 if (SOC_IS_FBX(pcid_info->unit)) { 573 if (SOC_IS_FB_FX_HX(pcid_info->unit)) { 574 /* 575 * Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block 576 */ 577 int blk; 578 int unit = pcid_info->unit; 579 int cpu_port = CMIC_PORT(unit); 580 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20; 581 if (((address & 0x00f00000) == blk) 582 && ((address & 0x0000001f) != cpu_port ) 583 && (mem != IFP_PORT_FIELD_SELm)) { 584 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20; 585 address = (address & ~(0x00f00000)) | blk; 586 } 587 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20; 588 if (((address & 0x00f00000) == blk) 589 && ((address & 0x0000001f) != cpu_port)) { 590 blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20; 591 address = (address & ~(0x00f00000)) | blk; 592 } 593 } 594 595 switch(mem) { 596 case L3_ENTRY_IPV4_UNICASTm: 597 case L3_ENTRY_IPV4_MULTICASTm: 598 case L3_ENTRY_IPV6_UNICASTm: 599 case L3_ENTRY_IPV6_MULTICASTm: 600 if(SOC_IS_HAWKEYE(pcid_info->unit)){ 601 break; 602 } 603 return (soc_internal_l3x2_write(pcid_info, mem, 604 address, data)); 605 default: break; 606 } 607 } 608 #endif /* BCM_FIREBOLT_SUPPORT */ 609 #if defined(BCM_TRX_SUPPORT) 610 if (SOC_IS_TRX(pcid_info->unit)) { 611 if (mem == VLAN_MACm) { 612 /* In real HW, VLAN_MAC table is overlaid on VLAN_XLATE table */ 613 return (soc_internal_vlan_xlate_entry_write(pcid_info, address, 614 (vlan_xlate_entry_t *) data)); 615 } 616 } 617 #endif 618 619 if (soc_mem_is_aggr(pcid_info->unit, mem)) { 620 return soc_internal_write_aggrmem(pcid_info, address, data); 621 } 622 } 623 624 rv = soc_datum_mem_write(pcid_info, 0, address, data); 625 return rv; 626 } 627 628 int 629 soc_internal_read_bytes(pcid_info_t *pcid_info, uint32 address, uint8 *data, 630 int len) 631 { 632 uint32 temp[SOC_MAX_MEM_WORDS]; 633 int rv; 634 635 if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) { 636 return 1; 637 } 638 639 /* reading bytes is supported only for bcmsim */ 640 if ((pcid_info->regmem_cb) && 641 (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, 642 (uint32 *) data, (len * 8)) == 0)) { 643 return 0; 644 } 645 646 /* if no registered call-back, default to read_mem */ 647 sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32))); 648 rv = soc_internal_read_mem(pcid_info, address, temp); 649 if (!rv) { 650 sal_memcpy(data, temp, len); 651 } 652 return rv; 653 } 654 int 655 soc_internal_read_mem(pcid_info_t *pcid_info, uint32 address, uint32 *data) 656 { 657 int i, rv; 658 soc_mem_t mem; 659 660 if ((pcid_info->regmem_cb) 661 && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, data, 662 ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) { 663 return 0; 664 } 665 666 if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) { 667 #ifdef BCM_FIREBOLT_SUPPORT 668 if (SOC_IS_FBX(pcid_info->unit)) { 669 if (SOC_IS_FB_FX_HX(pcid_info->unit)) { 670 /* 671 * Map EPIPE_HI/IPIPE_HI port registers to EPIPE/IPIPE block 672 */ 673 int blk; 674 int unit = pcid_info->unit; 675 int cpu_port = CMIC_PORT(unit); 676 blk = SOC_BLOCK2OFFSET(unit, IPIPE_HI_BLOCK(unit)) << 20; 677 if (((address & 0x00f00000) == blk) 678 && ((address & 0x0000001f) != cpu_port ) 679 && (mem != IFP_PORT_FIELD_SELm)) { 680 blk = SOC_BLOCK2OFFSET(unit, IPIPE_BLOCK(unit)) << 20; 681 address = (address & ~(0x00f00000)) | blk; 682 } 683 blk = SOC_BLOCK2OFFSET(unit, EPIPE_HI_BLOCK(unit)) << 20; 684 if (((address & 0x00f00000) == blk) 685 && ((address & 0x0000001f) != cpu_port)) { 686 blk = SOC_BLOCK2OFFSET(unit, EPIPE_BLOCK(unit)) << 20; 687 address = (address & ~(0x00f00000)) | blk; 688 } 689 } 690 691 switch(mem) { 692 case L3_ENTRY_IPV4_UNICASTm: 693 case L3_ENTRY_IPV4_MULTICASTm: 694 case L3_ENTRY_IPV6_UNICASTm: 695 case L3_ENTRY_IPV6_MULTICASTm: 696 if(SOC_IS_HAWKEYE(pcid_info->unit)){ 697 break; 698 } 699 return (soc_internal_l3x2_read(pcid_info, mem, 700 address, data)); 701 default: break; 702 } 703 } 704 #endif /* BCM_FIREBOLT_SUPPORT */ 705 #if defined(BCM_TRX_SUPPORT) 706 if (SOC_IS_TRX(pcid_info->unit)) { 707 if (mem == VLAN_MACm) { 708 /* In real HW, VLAN_MAC table is overlaid on VLAN_XLATE table */ 709 return (soc_internal_vlan_xlate_entry_read(pcid_info, address, 710 (vlan_xlate_entry_t *) data)); 711 } 712 } 713 #endif 714 if (soc_mem_is_aggr(pcid_info->unit, mem)) { 715 return soc_internal_read_aggrmem(pcid_info, address, data); 716 } 717 } 718 719 rv = soc_datum_mem_read(pcid_info, 0, address, data); 720 721 if (SOC_E_NOT_FOUND == rv) { 722 /* Return null entry value if recognize, otherwise 0xf's */ 723 if ((mem = soc_addr_to_mem(pcid_info->unit, address, NULL)) != INVALIDm) { 724 if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) { 725 memcpy(data, /* Memory */ 726 soc_mem_entry_null(pcid_info->unit, mem), 727 4 * soc_mem_entry_words(pcid_info->unit, mem)); 728 } else { 729 memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem)); 730 } 731 } else { /* Other */ 732 for (i = 0; i < SOC_MAX_MEM_WORDS; i++) { 733 data[i] = 0xffffffff; 734 } 735 } 736 } 737 738 return SOC_E_NONE; 739 } 740 741 /* 742 * Re-sort fields of aggregate mems based on bit position 743 */ 744 void 745 _soc_internal_fields_sort(soc_field_info_t *src, uint32 count, soc_field_info_t *dst) 746 { 747 uint32 i, j; 748 soc_field_info_t tmp; 749 750 sal_memcpy(dst, src, count * sizeof(soc_field_info_t)); 751 for (i = 0; i < count; i++) { 752 for (j = 0; j < count - i - 1; j++) { 753 if (dst[j].bp < dst[j+1].bp) { 754 sal_memcpy(&tmp, &dst[j], 755 sizeof(soc_field_info_t)); 756 sal_memcpy(&dst[j], &dst[j+1], 757 sizeof(soc_field_info_t)); 758 sal_memcpy(&dst[j+1], &tmp, 759 sizeof(soc_field_info_t)); 760 } 761 } 762 } 763 } 764 765 /* 766 ** This is a generic function to handle aggregate memories. Memories 767 ** made up of unequal depth and field mismatch between unified view 768 ** and individual component memories require special handling. 769 ** For example L2 table has HIT bits which are packet into 1/8 size table 770 */ 771 int 772 soc_internal_read_aggrmem(pcid_info_t *pcid_info, uint32 addr, uint32 *data) 773 { 774 int unit = pcid_info->unit; 775 uint32 ent[SOC_MAX_MEM_WORDS]; 776 uint32 fv[SOC_MAX_MEM_WORDS]; 777 soc_mem_t *m = NULL; 778 int index, i; 779 int offset; 780 int adj_offset = 0; 781 int f; 782 int nfield; 783 int pck_factor; 784 soc_mem_t mem; 785 soc_mem_info_t *amemp; 786 soc_mem_info_t *memp; 787 soc_field_info_t *fieldp; 788 soc_field_info_t *asflds; /* array for aggregate mem sorted fields */ 789 soc_field_info_t *sflds; /* array for partial mem sorted fields */ 790 791 mem = soc_addr_to_mem(pcid_info->unit, addr, NULL); 792 793 if (mem == INVALIDm) 794 { 795 return SOC_E_PARAM; 796 } 797 798 offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0xfffff; 799 index = 0; 800 memset(data, 0, 4 * soc_mem_entry_words(unit, mem)); 801 do { 802 m = SOC_MEM_AGGR(unit, index); 803 if (m[0] == mem) { 804 /* Fetch the individual components */ 805 nfield = 1; 806 for(i = 1; m[i] != INVALIDm; i++) { 807 /* 808 ** Multiple entries compacted into one entry like HIT 809 ** requires special handling. 810 */ 811 amemp = &SOC_MEM_INFO(unit, mem); 812 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) { 813 continue; 814 } 815 pck_factor = (soc_mem_index_max(unit, mem) / 816 soc_mem_index_max(unit, m[i])); 817 assert(pck_factor != 0); 818 adj_offset = offset / pck_factor; 819 soc_internal_read_mem(pcid_info, 820 soc_mem_addr(unit, m[i], 0, 821 SOC_MEM_BLOCK_ANY(unit, m[i]), 822 adj_offset), ent); 823 824 /* Iterate thru' the fields in this View */ 825 memp = &SOC_MEM_INFO(unit, m[i]); 826 if (pck_factor == 1) { 827 for (f = memp->nFields - 1; f >= 0; f--) { 828 fieldp = &memp->fields[f]; 829 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 830 if (soc_mem_field_valid(unit, mem, fieldp->field) && 831 soc_mem_field_valid(unit, m[i], fieldp->field)) { 832 soc_mem_field_set(unit, mem, data, fieldp->field, 833 fv); 834 } 835 nfield++; 836 } 837 } else if (memp->nFields == pck_factor) { 838 asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 839 "aggregate fields"); 840 if (!asflds) { 841 return SOC_E_INTERNAL; 842 } 843 sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 844 "mem fields"); 845 if (!sflds) { 846 sal_free(asflds); 847 return SOC_E_INTERNAL; 848 } 849 _soc_internal_fields_sort(amemp->fields, amemp->nFields, 850 asflds); 851 _soc_internal_fields_sort(memp->fields, memp->nFields, 852 sflds); 853 fieldp = &sflds[memp->nFields - 854 (offset % pck_factor) - 1]; 855 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 856 fieldp = &asflds[(amemp->nFields - nfield)]; 857 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 858 nfield++; 859 sal_free(asflds); sal_free(sflds); 860 } else if (memp->nFields == (pck_factor * 2)) { 861 asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 862 "aggregate fields"); 863 if (!asflds) { 864 return SOC_E_INTERNAL; 865 } 866 sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 867 "mem fields"); 868 if (!sflds) { 869 sal_free(asflds); 870 return SOC_E_INTERNAL; 871 } 872 _soc_internal_fields_sort(amemp->fields, amemp->nFields, 873 asflds); 874 _soc_internal_fields_sort(memp->fields, memp->nFields, 875 sflds); 876 fieldp = &sflds[memp->nFields - 877 (offset % pck_factor) - 1]; 878 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 879 fieldp = &asflds[(amemp->nFields - nfield)]; 880 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 881 nfield++; 882 883 fieldp = &sflds[memp->nFields - pck_factor - 884 (offset % pck_factor) - 1]; 885 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 886 fieldp = &asflds[(amemp->nFields - nfield)]; 887 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 888 nfield++; 889 sal_free(asflds); sal_free(sflds); 890 } else { 891 LOG_ERROR(BSL_LS_SOC_COMMON, 892 (BSL_META_U(unit, 893 "soc_internal_read_aggrmem:mem=%d" 894 "Unable to handle Aggregate Mem component %d\n"), 895 mem, m[i])); 896 } 897 } 898 return(0); 899 } 900 index++; 901 } while (m[0] != INVALIDm); 902 903 /* Not found in the table of aggregate memories */ 904 LOG_ERROR(BSL_LS_SOC_COMMON, 905 (BSL_META_U(unit, 906 "soc_internal_read_aggrmem:mem=%d missing in Aggregate Mem List\n"), 907 mem)); 908 if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) { 909 memcpy(data, /* Memory */ 910 soc_mem_entry_null(pcid_info->unit, mem), 911 4 * soc_mem_entry_words(pcid_info->unit, mem)); 912 } else { 913 memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem)); 914 } 915 return(0); 916 } 917 918 int 919 soc_internal_write_aggrmem(pcid_info_t *pcid_info, uint32 addr, uint32 *data) 920 { 921 int unit = pcid_info->unit; 922 uint32 ent[SOC_MAX_MEM_WORDS]; 923 uint32 fv[SOC_MAX_MEM_WORDS]; 924 soc_mem_t *m = NULL; 925 int index, i; 926 int offset; 927 int adj_offset = 0; 928 int f; 929 int nfield; 930 int pck_factor; 931 soc_mem_t mem; 932 soc_mem_info_t *amemp; 933 soc_mem_info_t *memp; 934 soc_field_info_t *fieldp; 935 soc_field_info_t *asflds; /* array for aggregate mem sorted fields */ 936 soc_field_info_t *sflds; /* array for partial mem sorted fields */ 937 938 mem = soc_addr_to_mem(pcid_info->unit, addr, NULL); 939 940 if (mem == INVALIDm) 941 { 942 return SOC_E_PARAM; 943 } 944 945 memset(ent, 0, 4 * soc_mem_entry_words(unit, mem)); 946 offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0xfffff; 947 index = 0; 948 do { 949 m = SOC_MEM_AGGR(unit, index); 950 if (m[0] == mem) { 951 /* Fetch the individual components */ 952 nfield = 1; 953 for(i = 1; m[i] != INVALIDm; i++) { 954 /* 955 ** Multiple entries compacted into one entry like HIT 956 ** requires special handling. 957 */ 958 amemp = &SOC_MEM_INFO(unit, mem); 959 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) { 960 continue; 961 } 962 pck_factor = (soc_mem_index_max(unit, mem) / 963 soc_mem_index_max(unit, m[i])); 964 assert(pck_factor != 0); 965 adj_offset = offset / pck_factor; 966 memp = &SOC_MEM_INFO(unit, m[i]); 967 968 /* Iterate thru' the fields in this View */ 969 if (pck_factor == 1) { 970 for (f = memp->nFields - 1; f >= 0; f--) { 971 fieldp = &memp->fields[f]; 972 if (soc_mem_field_valid(unit, mem, fieldp->field) && 973 soc_mem_field_valid(unit, m[i], fieldp->field)) { 974 soc_mem_field_get(unit, mem, data, fieldp->field, 975 fv); 976 soc_mem_field_set(unit, m[i], ent, fieldp->field, 977 fv); 978 } 979 nfield++; 980 } 981 } else if (memp->nFields == pck_factor) { 982 asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 983 "aggregate fields"); 984 if (!asflds) { 985 return SOC_E_INTERNAL; 986 } 987 sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 988 "mem fields"); 989 if (!sflds) { 990 sal_free(asflds); 991 return SOC_E_INTERNAL; 992 } 993 _soc_internal_fields_sort(amemp->fields, amemp->nFields, 994 asflds); 995 _soc_internal_fields_sort(memp->fields, memp->nFields, 996 sflds); 997 fieldp = &asflds[(amemp->nFields - nfield)]; 998 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 999 fieldp = &sflds[memp->nFields - 1000 (offset % pck_factor) - 1]; 1001 soc_internal_read_mem(pcid_info, 1002 soc_mem_addr(unit, m[i], 0, 1003 SOC_MEM_BLOCK_ANY(unit, m[i]), 1004 adj_offset), ent); 1005 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 1006 nfield++; 1007 sal_free(asflds); sal_free(sflds); 1008 } else if (memp->nFields == (pck_factor * 2)) { 1009 asflds = sal_alloc(amemp->nFields * sizeof(soc_field_info_t), 1010 "aggregate fields"); 1011 if (!asflds) { 1012 return SOC_E_INTERNAL; 1013 } 1014 sflds = sal_alloc(memp->nFields * sizeof(soc_field_info_t), 1015 "mem fields"); 1016 if (!sflds) { 1017 sal_free(asflds); 1018 return SOC_E_INTERNAL; 1019 } 1020 _soc_internal_fields_sort(amemp->fields, amemp->nFields, 1021 asflds); 1022 _soc_internal_fields_sort(memp->fields, memp->nFields, 1023 sflds); 1024 fieldp = &asflds[(amemp->nFields - nfield)]; 1025 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 1026 fieldp = &sflds[memp->nFields - 1027 (offset % pck_factor) - 1]; 1028 soc_internal_read_mem(pcid_info, 1029 soc_mem_addr(unit, m[i], 0, 1030 SOC_MEM_BLOCK_ANY(unit, m[i]), 1031 adj_offset), ent); 1032 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 1033 nfield++; 1034 1035 fieldp = &asflds[(amemp->nFields - nfield)]; 1036 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 1037 fieldp = &sflds[memp->nFields - pck_factor - 1038 (offset % pck_factor) - 1]; 1039 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 1040 nfield++; 1041 sal_free(asflds); sal_free(sflds); 1042 } else { 1043 LOG_ERROR(BSL_LS_SOC_COMMON, 1044 (BSL_META_U(unit, 1045 "soc_internal_write_aggrmem:mem=%d" 1046 "Unable to handle Aggregate Mem component %d\n"), 1047 mem, m[i])); 1048 } 1049 soc_internal_write_mem(pcid_info, 1050 soc_mem_addr(unit, m[i], 0, 1051 SOC_MEM_BLOCK_ANY(unit, m[i]), 1052 adj_offset), ent); 1053 } 1054 return(0); 1055 } 1056 index++; 1057 } while (m[0] != INVALIDm); 1058 1059 /* Not found in the table of aggregate memories */ 1060 LOG_ERROR(BSL_LS_SOC_COMMON, 1061 (BSL_META_U(unit, 1062 "soc_internal_write_aggrmem:mem=%d missing in Aggregate Mem List\n"), 1063 mem)); 1064 return(0); 1065 } 1066 1067 #ifdef BCM_FIREBOLT_SUPPORT 1068 void 1069 _soc_l2x2_nak_check(int unit, schan_msg_t *msg) 1070 { 1071 int op_fail_pos; 1072 1073 /* 1074 * ================================================== 1075 * | MFIFO_FULL | OP_FAIL | Index | L2x entry data | 1076 * ================================================== 1077 */ 1078 op_fail_pos = (_shr_popcount(soc_mem_index_max(unit, L2Xm)) + 1079 soc_mem_entry_bits(unit, L2Xm)) % 32; 1080 1081 if (msg->readresp.data[3] & (0x3 << op_fail_pos)) { 1082 msg->readresp.header.v2.nack = 1; 1083 } 1084 } 1085 #endif /* BCM_FIREBOLT_SUPPORT */ 1086 1087 #ifdef BCM_TRX_SUPPORT 1088 static int ing_ipfix_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 }; 1089 static int egr_ipfix_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 }; 1090 static int ext_l2mod_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 }; 1091 static int l2mod_fifo_count[SOC_MAX_NUM_DEVICES] = { 0 }; 1092 1093 /* 1094 * soc_internal_ing_ipfix_fifo_pop 1095 */ 1096 static int 1097 soc_internal_fifo_pop(pcid_info_t * pcid_info, soc_mem_t mem, uint32 *result) 1098 { 1099 int *count, i; 1100 uint32 tmp[SOC_MAX_MEM_WORDS]; 1101 int unit = pcid_info->unit; 1102 1103 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1104 (BSL_META_U(unit, 1105 "Ingress IPFIX fifo pop\n"))); 1106 1107 *result = 0; 1108 switch (mem) { 1109 case ING_IPFIX_EXPORT_FIFOm: 1110 count = &ing_ipfix_fifo_count[unit]; 1111 break; 1112 case EGR_IPFIX_EXPORT_FIFOm: 1113 count = &egr_ipfix_fifo_count[unit]; 1114 break; 1115 case EXT_L2_MOD_FIFOm: 1116 count = &ext_l2mod_fifo_count[unit]; 1117 break; 1118 case L2_MOD_FIFOm: 1119 count = &l2mod_fifo_count[unit]; 1120 break; 1121 default: 1122 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1123 (BSL_META_U(unit, 1124 "Pop not supported on this memory\n"))); 1125 /* PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; */ 1126 pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST); 1127 return 0; 1128 } 1129 1130 if (*count > 0) { 1131 soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1132 SOC_MEM_BLOCK_ANY(unit, mem), 1133 0), result); 1134 1135 /* Shift up the remaining entries */ 1136 for (i = 0; i < *count; i++) { 1137 soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1138 SOC_MEM_BLOCK_ANY(unit, mem), 1139 i + 1), tmp); 1140 soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1141 SOC_MEM_BLOCK_ANY(unit, mem), 1142 i), tmp); 1143 } 1144 *count -= 1; 1145 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1146 (BSL_META_U(unit, 1147 "Fifo entry popped.\n"))); 1148 } else { 1149 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1150 (BSL_META_U(unit, 1151 "Fifo Empty\n"))); 1152 return 1; 1153 } 1154 return 0; 1155 } 1156 1157 /* 1158 * soc_internal_ing_ipfix_fifo_push 1159 */ 1160 static int 1161 soc_internal_fifo_push(pcid_info_t * pcid_info, soc_mem_t mem, uint32 *entry) 1162 { 1163 int *count, i; 1164 uint32 tmp[SOC_MAX_MEM_WORDS]; 1165 int unit = pcid_info->unit; 1166 1167 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1168 (BSL_META_U(unit, 1169 "Ingress IPFIX fifo push\n"))); 1170 1171 switch (mem) { 1172 case ING_IPFIX_EXPORT_FIFOm: 1173 count = &ing_ipfix_fifo_count[unit]; 1174 break; 1175 case EGR_IPFIX_EXPORT_FIFOm: 1176 count = &egr_ipfix_fifo_count[unit]; 1177 break; 1178 case EXT_L2_MOD_FIFOm: 1179 count = &ext_l2mod_fifo_count[unit]; 1180 break; 1181 case L2_MOD_FIFOm: 1182 count = &l2mod_fifo_count[unit]; 1183 break; 1184 default: 1185 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1186 (BSL_META_U(unit, 1187 "Pop not supported on this memory\n"))); 1188 /* PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST; */ 1189 pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST); 1190 return 0; 1191 } 1192 1193 if (*count == soc_mem_index_count(unit, mem)) { 1194 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1195 (BSL_META_U(unit, 1196 "Fifo Full\n"))); 1197 return 1; 1198 } else { 1199 /* Shift down the existing entries */ 1200 for (i = *count; i > 0; i--) { 1201 soc_internal_read_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1202 SOC_MEM_BLOCK_ANY(unit, mem), 1203 i - 1), tmp); 1204 soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1205 SOC_MEM_BLOCK_ANY(unit, mem), 1206 i), tmp); 1207 } 1208 soc_internal_write_mem(pcid_info, soc_mem_addr(unit, mem, 0, 1209 SOC_MEM_BLOCK_ANY(unit, mem), 1210 0), entry); 1211 *count += 1; 1212 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1213 (BSL_META_U(unit, 1214 "Fifo entry pushed.\n"))); 1215 } 1216 return 0; 1217 } 1218 1219 #endif /* BCM_TRX_SUPPORT */ 1220 1221 /* 1222 * schan_op 1223 * 1224 * Look at schan header, perform action(s), and make response. 1225 */ 1226 1227 int 1228 schan_op(pcid_info_t *pcid_info, int unit, schan_msg_t* data) 1229 { 1230 schan_msg_t *msg; 1231 int opcode, dst_blk, src_blk, acc_type, data_byte_len, dma; 1232 uint32 bank_ignore_mask; 1233 int rv = -1; 1234 #ifdef BCM_TRX_SUPPORT 1235 int32 banks = 0; 1236 #endif 1237 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 1238 soc_mem_t mem; 1239 #endif 1240 1241 #ifdef BCM_CMICM_SUPPORT 1242 if (pcid_info->cmicm >= CMC0) { 1243 msg = (schan_msg_t *)&PCIM(pcid_info, CMIC_CMCx_SCHAN_MESSAGEn(CMC0, 0)); 1244 } else 1245 #endif 1246 { 1247 msg = (schan_msg_t *)&PCIM(pcid_info, CMIC_SCHAN_MESSAGE(unit, 0)); 1248 } 1249 1250 if(data) { 1251 *msg = *data; 1252 } 1253 1254 /* Clear nak bit in schan control */ 1255 #ifdef BCM_CMICM_SUPPORT 1256 if (pcid_info->cmicm >= CMC0) { 1257 /* PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= ~SC_CMCx_MSG_NAK; */ 1258 pcid_reg_and_write(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET, SC_CMCx_MSG_NAK); 1259 1260 } else 1261 #endif 1262 { 1263 /* PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST; */ 1264 pcid_reg_and_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_NAK_TST); 1265 } 1266 1267 soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode, 1268 &dst_blk, &src_blk, &acc_type, &data_byte_len, 1269 &dma, &bank_ignore_mask); 1270 switch (opcode) { 1271 case WRITE_REGISTER_CMD_MSG: 1272 if (pcid_info->opt_pli_verbose) 1273 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1274 (BSL_META_U(unit, 1275 "S-Channel operation: WRITE_REGISTER_CMD 0x%x\n"), 1276 msg->writecmd.address)); 1277 opcode = WRITE_REGISTER_ACK_MSG; 1278 rv = soc_internal_extended_write_reg(pcid_info, dst_blk, acc_type, 1279 msg->writecmd.address, 1280 msg->writecmd.data); 1281 break; 1282 case READ_REGISTER_CMD_MSG: 1283 if (pcid_info->opt_pli_verbose) 1284 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1285 (BSL_META_U(unit, 1286 "S-Channel operation: READ_REGISTER_CMD 0x%x\n"), 1287 msg->readcmd.address)); 1288 opcode = READ_REGISTER_ACK_MSG; 1289 rv = soc_internal_extended_read_reg(pcid_info, dst_blk, acc_type, 1290 msg->readcmd.address, 1291 msg->readresp.data); 1292 break; 1293 case WRITE_MEMORY_CMD_MSG: 1294 if (pcid_info->opt_pli_verbose) 1295 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1296 (BSL_META_U(unit, 1297 "S-Channel operation: WRITE_MEMORY_CMD 0x%x\n"), 1298 msg->writecmd.address)); 1299 opcode = WRITE_MEMORY_ACK_MSG; 1300 rv = soc_internal_extended_write_mem(pcid_info, dst_blk, acc_type, 1301 msg->writecmd.address, 1302 msg->writecmd.data); 1303 break; 1304 case READ_MEMORY_CMD_MSG: 1305 if (pcid_info->opt_pli_verbose) 1306 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1307 (BSL_META_U(unit, 1308 "S-Channel operation: READ_MEMORY_CMD 0x%x\n"), 1309 msg->readcmd.address)); 1310 opcode = READ_MEMORY_ACK_MSG; 1311 rv = soc_internal_extended_read_mem(pcid_info, dst_blk, acc_type, 1312 msg->readcmd.address, 1313 msg->readresp.data); 1314 break; 1315 case ARL_INSERT_CMD_MSG: 1316 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1317 (BSL_META_U(unit, 1318 "S-Channel operation: ARL_INSERT_CMD_MSG\n"))); 1319 #ifdef BCM_FIREBOLT_SUPPORT 1320 if (SOC_IS_FBX(pcid_info->unit)) { 1321 opcode = ARL_INSERT_DONE_MSG; 1322 rv = soc_internal_l2x2_entry_ins(pcid_info, bank_ignore_mask, 1323 (l2x_entry_t *)msg->l2x2.data, 1324 msg->readresp.data); 1325 _soc_l2x2_nak_check(pcid_info->unit, msg); 1326 break; 1327 } 1328 #endif /* BCM_FIREBOLT_SUPPORT */ 1329 if (SOC_IS_XGS_FABRIC(pcid_info->unit)) { 1330 LOG_WARN(BSL_LS_SOC_COMMON, 1331 (BSL_META_U(unit, 1332 "Bad call for Hercules: ARL_INSERT_CMD_MSG\n"))); 1333 break; 1334 } 1335 break; 1336 case ARL_DELETE_CMD_MSG: 1337 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1338 (BSL_META_U(unit, 1339 "S-Channel operation: ARL_DELETE_CMD_MSG\n"))); 1340 #ifdef BCM_FIREBOLT_SUPPORT 1341 if (SOC_IS_FBX(pcid_info->unit)) { 1342 opcode = ARL_DELETE_DONE_MSG; 1343 rv = soc_internal_l2x2_entry_del(pcid_info, bank_ignore_mask, 1344 (l2x_entry_t *)msg->l2x2.data, 1345 msg->readresp.data); 1346 _soc_l2x2_nak_check(pcid_info->unit, msg); 1347 break; 1348 } 1349 #endif /* BCM_FIREBOLT_SUPPORT */ 1350 if (SOC_IS_XGS_FABRIC(pcid_info->unit)) { 1351 LOG_WARN(BSL_LS_SOC_COMMON, 1352 (BSL_META_U(unit, 1353 "Bad call for Hercules: ARL_DELETE_CMD_MSG\n"))); 1354 break; 1355 } 1356 break; 1357 case L2_LOOKUP_CMD_MSG: 1358 #ifdef BCM_FIREBOLT_SUPPORT 1359 if (SOC_IS_FBX(pcid_info->unit)) { 1360 opcode = L2_LOOKUP_ACK_MSG; 1361 rv = soc_internal_l2x2_entry_lkup(pcid_info, bank_ignore_mask, 1362 (l2x_entry_t *)msg->l2x2.data, 1363 msg->readresp.data); 1364 _soc_l2x2_nak_check(pcid_info->unit, msg); 1365 break; 1366 } 1367 break; 1368 #endif /* BCM_FIREBOLT_SUPPORT */ 1369 case ARL_LOOKUP_CMD_MSG: 1370 if (SOC_IS_XGS_FABRIC(pcid_info->unit)) { 1371 LOG_WARN(BSL_LS_SOC_COMMON, 1372 (BSL_META_U(unit, 1373 "Bad call for Hercules: ARL_LOOKUP_CMD_MSG\n"))); 1374 break; 1375 } 1376 break; 1377 case L3_INSERT_CMD_MSG: 1378 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1379 (BSL_META_U(unit, 1380 "S-Channel operation: L3_INSERT_CMD_MSG\n"))); 1381 #ifdef BCM_FIREBOLT_SUPPORT 1382 if (SOC_IS_FBX(pcid_info->unit)) { 1383 opcode = L3_INSERT_DONE_MSG; 1384 /* Coverity 1385 * This is being called under #ifdef FIREBOLT 1386 * The coverity is reporting error 1387 * from the called function in case of TRIDENT2 1388 * which will not be called 1389 */ 1390 /* coverity[overrun-buffer-val] */ 1391 rv = soc_internal_l3x2_entry_ins(pcid_info, bank_ignore_mask, 1392 (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data, 1393 msg->readresp.data); 1394 break; 1395 } 1396 #endif /* BCM_FIREBOLT_SUPPORT */ 1397 LOG_WARN(BSL_LS_SOC_COMMON, 1398 (BSL_META_U(unit, 1399 "Bad call for Non-XGS3: L3_INSERT_CMD_MSG\n"))); 1400 rv = -1; 1401 break; 1402 case L3_DELETE_CMD_MSG: 1403 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1404 (BSL_META_U(unit, 1405 "S-Channel operation: L3_DELETE_CMD_MSG\n"))); 1406 #ifdef BCM_FIREBOLT_SUPPORT 1407 if (SOC_IS_FBX(pcid_info->unit)) { 1408 opcode = L3_DELETE_DONE_MSG; 1409 rv = soc_internal_l3x2_entry_del(pcid_info, bank_ignore_mask, 1410 (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data, 1411 msg->readresp.data); 1412 break; 1413 } 1414 #endif /* BCM_FIREBOLT_SUPPORT */ 1415 LOG_WARN(BSL_LS_SOC_COMMON, 1416 (BSL_META_U(unit, 1417 "Bad call for Non-XGS3: L3_DELETE_CMD_MSG\n"))); 1418 rv = -1; 1419 break; 1420 case L3X2_LOOKUP_CMD_MSG: 1421 #ifdef BCM_FIREBOLT_SUPPORT 1422 if (SOC_IS_FBX(pcid_info->unit)) { 1423 opcode = L3X2_LOOKUP_ACK_MSG; 1424 rv = soc_internal_l3x2_entry_lkup(pcid_info, bank_ignore_mask, 1425 (l3_entry_ipv6_multicast_entry_t *)msg->l3x2.data, 1426 msg->readresp.data); 1427 if (msg->readresp.data[0] == -1) { 1428 msg->readresp.header.v2.nack = 1; 1429 } 1430 break; 1431 } 1432 break; 1433 #endif /* BCM_FIREBOLT_SUPPORT */ 1434 1435 #if defined(BCM_TRX_SUPPORT) 1436 case TABLE_INSERT_CMD_MSG: 1437 if (soc_feature(unit, soc_feature_generic_table_ops)) { 1438 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1439 (BSL_META_U(unit, 1440 "S-Channel operation: TABLE_INSERT_CMD_MSG\n"))); 1441 1442 opcode = TABLE_INSERT_DONE_MSG; 1443 banks = bank_ignore_mask; 1444 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 1445 uint32 address; 1446 address = msg->gencmd.address; 1447 if (soc_feature(unit, soc_feature_ism_memory)) { 1448 address &= ~SOC_HASH_BANK_MASK_ISM; 1449 } 1450 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1451 address &= ~SOC_HASH_BANK_MASK_SHARED; 1452 } 1453 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk, 1454 acc_type, address); 1455 } else { 1456 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL); 1457 } 1458 #ifdef BCM_ISM_SUPPORT 1459 if (soc_feature(unit, soc_feature_ism_memory)) { 1460 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM; 1461 if (!banks) { 1462 banks = SOC_MEM_HASH_BANK_ALL; 1463 } else { 1464 banks = ~banks & SOC_HASH_BANK_MASK_ISM; 1465 } 1466 rv = soc_internal_generic_hash_insert(pcid_info, mem, banks, 1467 msg->gencmd.data, 1468 (uint32 *)&msg->genresp.response); 1469 } else 1470 #endif 1471 if (mem == L2Xm) { 1472 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1473 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1474 } 1475 /* coverity[overrun-buffer-val] */ 1476 rv = soc_internal_l2_tr_entry_ins(pcid_info, banks, 1477 (l2x_entry_t *)msg->gencmd.data, 1478 (uint32 *)&msg->genresp.response); 1479 } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) { 1480 rv = soc_internal_vlan_xlate_entry_ins(pcid_info, banks, 1481 (vlan_xlate_entry_t *)msg->gencmd.data, 1482 (uint32 *)&msg->genresp.response); 1483 } else if (mem == EGR_VLAN_XLATEm) { 1484 rv = soc_internal_egr_vlan_xlate_entry_ins(pcid_info, banks, 1485 (egr_vlan_xlate_entry_t *)msg->gencmd.data, 1486 (uint32 *)&msg->genresp.response); 1487 #ifdef BCM_TRIUMPH_SUPPORT 1488 } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) || mem == MPLS_ENTRYm) { 1489 rv = soc_internal_mpls_entry_ins(pcid_info, banks, 1490 (mpls_entry_entry_t *)msg->gencmd.data, 1491 (uint32 *)&msg->genresp.response); 1492 #endif 1493 #ifdef BCM_TRIDENT2_SUPPORT 1494 } else if (mem == ING_VP_VLAN_MEMBERSHIPm) { 1495 rv = soc_internal_ing_vp_vlan_member_ins 1496 (pcid_info, banks, msg->gencmd.data, 1497 (uint32 *)&msg->genresp.response); 1498 } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) { 1499 rv = soc_internal_egr_vp_vlan_member_ins 1500 (pcid_info, banks, msg->gencmd.data, 1501 (uint32 *)&msg->genresp.response); 1502 } else if (mem == ING_DNAT_ADDRESS_TYPEm) { 1503 rv = soc_internal_ing_dnat_address_type_ins 1504 (pcid_info, banks, msg->gencmd.data, 1505 (uint32 *)&msg->genresp.response); 1506 } else if (mem == L2_ENDPOINT_IDm) { 1507 rv = soc_internal_l2_endpoint_id_ins 1508 (pcid_info, banks, msg->gencmd.data, 1509 (uint32 *)&msg->genresp.response); 1510 } else if (mem == ENDPOINT_QUEUE_MAPm) { 1511 rv = soc_internal_endpoint_queue_map_ins 1512 (pcid_info, banks, msg->gencmd.data, 1513 (uint32 *)&msg->genresp.response); 1514 #endif 1515 #ifdef BCM_TOMAHAWK_SUPPORT 1516 } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) { 1517 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1518 rv = soc_internal_exact_match_ins 1519 (pcid_info, banks, msg->gencmd.data, 1520 (uint32 *)&msg->genresp.response); 1521 #endif /* BCM_TOMAHAWK_SUPPORT */ 1522 #ifdef BCM_TOMAHAWK3_SUPPORT 1523 } else if (mem == L3_TUNNEL_SINGLEm || 1524 mem == L3_TUNNEL_DOUBLEm || mem == L3_TUNNEL_QUADm) { 1525 rv = soc_internal_tunnel_entry_ins(pcid_info, 1526 banks, 1527 (void *)msg->gencmd.data, 1528 (uint32 *)&msg->genresp.response); 1529 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1530 } else { 1531 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1532 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1533 } 1534 /* coverity[overrun-buffer-val] */ 1535 rv = soc_internal_l3x2_entry_ins(pcid_info, banks, 1536 (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data, 1537 (uint32 *)&msg->genresp.response); 1538 } 1539 if (soc_feature(unit, soc_feature_new_sbus_format) && 1540 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1541 if ((msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_INSERTED) && 1542 (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_REPLACED)) { 1543 msg->genresp_v2.header.v2.nack = 1; 1544 } 1545 } else { 1546 if ((msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_INSERTED) && 1547 (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_REPLACED)) { 1548 msg->genresp.header.v2.nack = 1; 1549 } 1550 } 1551 break; 1552 } 1553 case TABLE_DELETE_CMD_MSG: 1554 if (soc_feature(unit, soc_feature_generic_table_ops)) { 1555 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1556 (BSL_META_U(unit, 1557 "S-Channel operation: TABLE_DELETE_CMD_MSG\n"))); 1558 1559 opcode = TABLE_DELETE_DONE_MSG; 1560 banks = bank_ignore_mask; 1561 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 1562 uint32 address; 1563 address = msg->gencmd.address; 1564 if (soc_feature(unit, soc_feature_ism_memory)) { 1565 address &= ~SOC_HASH_BANK_MASK_ISM; 1566 } 1567 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1568 address &= ~SOC_HASH_BANK_MASK_SHARED; 1569 } 1570 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk, 1571 acc_type, address); 1572 } else { 1573 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL); 1574 } 1575 #ifdef BCM_ISM_SUPPORT 1576 if (soc_feature(unit, soc_feature_ism_memory)) { 1577 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM; 1578 if (!banks) { 1579 banks = SOC_MEM_HASH_BANK_ALL; 1580 } else { 1581 banks = ~banks & SOC_HASH_BANK_MASK_ISM; 1582 } 1583 rv = soc_internal_generic_hash_delete(pcid_info, mem, banks, 1584 msg->gencmd.data, 1585 (uint32 *)&msg->genresp.response); 1586 } else 1587 #endif 1588 if (mem == L2Xm) { 1589 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1590 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1591 } 1592 rv = soc_internal_l2_tr_entry_del(pcid_info, banks, 1593 (l2x_entry_t *)msg->gencmd.data, 1594 (uint32 *)&msg->genresp.response); 1595 } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) { 1596 rv = soc_internal_vlan_xlate_entry_del(pcid_info, banks, 1597 (vlan_xlate_entry_t *)msg->gencmd.data, 1598 (uint32 *)&msg->genresp.response); 1599 } else if (mem == EGR_VLAN_XLATEm) { 1600 rv = soc_internal_egr_vlan_xlate_entry_del(pcid_info, banks, 1601 (egr_vlan_xlate_entry_t *)msg->gencmd.data, 1602 (uint32 *)&msg->genresp.response); 1603 #ifdef BCM_TRIUMPH_SUPPORT 1604 } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) || 1605 mem == MPLS_ENTRYm) { 1606 /* coverity[callee_ptr_arith] */ 1607 rv = soc_internal_mpls_entry_del(pcid_info, banks, 1608 (mpls_entry_entry_t *)msg->gencmd.data, 1609 (uint32 *)&msg->genresp.response); 1610 #endif 1611 #ifdef BCM_TRIDENT2_SUPPORT 1612 } else if (mem == ING_VP_VLAN_MEMBERSHIPm) { 1613 rv = soc_internal_ing_vp_vlan_member_del 1614 (pcid_info, banks, msg->gencmd.data, 1615 (uint32 *)&msg->genresp.response); 1616 } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) { 1617 rv = soc_internal_egr_vp_vlan_member_del 1618 (pcid_info, banks, msg->gencmd.data, 1619 (uint32 *)&msg->genresp.response); 1620 } else if (mem == ING_DNAT_ADDRESS_TYPEm) { 1621 rv = soc_internal_ing_dnat_address_type_del 1622 (pcid_info, banks, msg->gencmd.data, 1623 (uint32 *)&msg->genresp.response); 1624 } else if (mem == L2_ENDPOINT_IDm) { 1625 rv = soc_internal_l2_endpoint_id_del 1626 (pcid_info, banks, msg->gencmd.data, 1627 (uint32 *)&msg->genresp.response); 1628 } else if (mem == ENDPOINT_QUEUE_MAPm) { 1629 rv = soc_internal_endpoint_queue_map_del 1630 (pcid_info, banks, msg->gencmd.data, 1631 (uint32 *)&msg->genresp.response); 1632 #endif 1633 #ifdef BCM_TOMAHAWK_SUPPORT 1634 } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) { 1635 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1636 rv = soc_internal_exact_match_del 1637 (pcid_info, banks, msg->gencmd.data, 1638 (uint32 *)&msg->genresp.response); 1639 #endif /* BCM_TOMAHAWK_SUPPORT */ 1640 } else { 1641 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1642 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1643 } 1644 rv = soc_internal_l3x2_entry_del(pcid_info, banks, 1645 (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data, 1646 (uint32 *)&msg->genresp.response); 1647 } 1648 if (soc_feature(unit, soc_feature_new_sbus_format) && 1649 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1650 if (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_DELETED) { 1651 msg->genresp_v2.header.v2.nack = 1; 1652 } 1653 } else { 1654 if (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_DELETED) { 1655 msg->genresp.header.v2.nack = 1; 1656 } 1657 } 1658 break; 1659 } 1660 case TABLE_LOOKUP_CMD_MSG: 1661 if (soc_feature(unit, soc_feature_generic_table_ops)) { 1662 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1663 (BSL_META_U(unit, 1664 "S-Channel operation: TABLE_LOOKUP_CMD_MSG\n"))); 1665 1666 opcode = TABLE_LOOKUP_DONE_MSG; 1667 banks = bank_ignore_mask; 1668 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 1669 uint32 address; 1670 address = msg->gencmd.address; 1671 if (soc_feature(unit, soc_feature_ism_memory)) { 1672 address &= ~SOC_HASH_BANK_MASK_ISM; 1673 } 1674 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1675 address &= ~SOC_HASH_BANK_MASK_SHARED; 1676 } 1677 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk, 1678 acc_type, address); 1679 } else { 1680 mem = soc_addr_to_mem(pcid_info->unit, msg->gencmd.address, NULL); 1681 } 1682 assert(mem != INVALIDm); 1683 1684 #ifdef BCM_ISM_SUPPORT 1685 if (soc_feature(unit, soc_feature_ism_memory)) { 1686 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_ISM; 1687 if (!banks) { 1688 banks = SOC_MEM_HASH_BANK_ALL; 1689 } else { 1690 banks = ~banks & SOC_HASH_BANK_MASK_ISM; 1691 } 1692 rv = soc_internal_generic_hash_lookup(pcid_info, mem, banks, 1693 msg->gencmd.data, 1694 (uint32 *)&msg->genresp.response); 1695 } else 1696 #endif 1697 if (mem == L2Xm) { 1698 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1699 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1700 } 1701 rv = soc_internal_l2_tr_entry_lkup(pcid_info, banks, 1702 (l2x_entry_t *)msg->gencmd.data, 1703 (uint32 *)&msg->genresp.response); 1704 } else if ((mem == VLAN_MACm) || (mem == VLAN_XLATEm)) { 1705 rv = soc_internal_vlan_xlate_entry_lkup(pcid_info, banks, 1706 (vlan_xlate_entry_t *)msg->gencmd.data, 1707 (uint32 *)&msg->genresp.response); 1708 } else if (mem == EGR_VLAN_XLATEm) { 1709 rv = soc_internal_egr_vlan_xlate_entry_lkup(pcid_info, banks, 1710 (egr_vlan_xlate_entry_t *)msg->gencmd.data, 1711 (uint32 *)&msg->genresp.response); 1712 #ifdef BCM_TRIUMPH_SUPPORT 1713 } else if ((SOC_IS_TOMAHAWK3(unit) && mem == MPLS_ENTRY_SINGLEm) || 1714 mem == MPLS_ENTRYm) { 1715 rv = soc_internal_mpls_entry_lkup(pcid_info, banks, 1716 (mpls_entry_entry_t *)msg->gencmd.data, 1717 (uint32 *)&msg->genresp.response); 1718 #endif 1719 #ifdef BCM_TRIDENT2_SUPPORT 1720 } else if (mem == ING_VP_VLAN_MEMBERSHIPm) { 1721 rv = soc_internal_ing_vp_vlan_member_lkup 1722 (pcid_info, banks, msg->gencmd.data, 1723 (uint32 *)&msg->genresp.response); 1724 } else if (mem == EGR_VP_VLAN_MEMBERSHIPm) { 1725 rv = soc_internal_egr_vp_vlan_member_lkup 1726 (pcid_info, banks, msg->gencmd.data, 1727 (uint32 *)&msg->genresp.response); 1728 } else if (mem == ING_DNAT_ADDRESS_TYPEm) { 1729 rv = soc_internal_ing_dnat_address_type_lkup 1730 (pcid_info, banks, msg->gencmd.data, 1731 (uint32 *)&msg->genresp.response); 1732 } else if (mem == L2_ENDPOINT_IDm) { 1733 rv = soc_internal_l2_endpoint_id_lkup 1734 (pcid_info, banks, msg->gencmd.data, 1735 (uint32 *)&msg->genresp.response); 1736 } else if (mem == ENDPOINT_QUEUE_MAPm) { 1737 rv = soc_internal_endpoint_queue_map_lkup 1738 (pcid_info, banks, msg->gencmd.data, 1739 (uint32 *)&msg->genresp.response); 1740 #endif 1741 #ifdef BCM_TOMAHAWK_SUPPORT 1742 } else if (mem == EXACT_MATCH_2m || mem == EXACT_MATCH_4m) { 1743 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1744 rv = soc_internal_exact_match_lkup 1745 (pcid_info, banks, msg->gencmd.data, 1746 (uint32 *)&msg->genresp.response); 1747 #endif /* BCM_TOMAHAWK_SUPPORT */ 1748 } else { 1749 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1750 banks = msg->gencmd.address & SOC_HASH_BANK_MASK_SHARED; 1751 } 1752 rv = soc_internal_l3x2_entry_lkup(pcid_info, banks, 1753 (l3_entry_ipv6_multicast_entry_t *)msg->gencmd.data, 1754 (uint32 *)&msg->genresp.response); 1755 } 1756 if (soc_feature(unit, soc_feature_new_sbus_format) && 1757 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) { 1758 if (msg->genresp_v2.response.type != SCHAN_GEN_RESP_TYPE_FOUND) { 1759 msg->genresp_v2.header.v2.nack = 1; 1760 } 1761 } else { 1762 if (msg->genresp.response.type != SCHAN_GEN_RESP_TYPE_FOUND) { 1763 msg->genresp.header.v2.nack = 1; 1764 } 1765 } 1766 break; 1767 } 1768 case FIFO_POP_CMD_MSG: 1769 if (soc_feature(unit, soc_feature_mem_push_pop)) { 1770 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1771 (BSL_META_U(unit, 1772 "S-Channel operation: FIFO_POP_CMD_MSG\n"))); 1773 1774 mem = soc_addr_to_mem(pcid_info->unit, msg->popcmd.address, NULL); 1775 /* coverity[overrun-buffer-val] */ 1776 rv = soc_internal_fifo_pop(pcid_info, mem, msg->popresp.data); 1777 if (rv == 1) { 1778 /* Fifo empty */ 1779 msg->popresp.header.v2.nack = 1; 1780 rv = 0; 1781 } 1782 opcode = FIFO_POP_DONE_MSG; 1783 } 1784 break; 1785 case FIFO_PUSH_CMD_MSG: 1786 if (soc_feature(unit, soc_feature_mem_push_pop)) { 1787 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1788 (BSL_META_U(unit, 1789 "S-Channel operation: FIFO_PUSH_CMD_MSG\n"))); 1790 1791 mem = soc_addr_to_mem(pcid_info->unit, msg->pushcmd.address, NULL); 1792 /* coverity[overrun-buffer-val] */ 1793 rv = soc_internal_fifo_push(pcid_info, mem, msg->pushcmd.data); 1794 if (rv == 1) { 1795 /* Fifo full */ 1796 msg->popresp.header.v2.nack = 1; 1797 rv = 0; 1798 } 1799 opcode = FIFO_PUSH_DONE_MSG; 1800 } 1801 break; 1802 #endif /* BCM_TRX_SUPPORT */ 1803 default: 1804 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1805 (BSL_META_U(unit, 1806 "S-Channel operation: message not handled: %s (%d)\n"), 1807 soc_schan_op_name(opcode), opcode)); 1808 break; 1809 } 1810 1811 msg->header.v2.opcode = opcode; 1812 if (rv == 0) { 1813 #ifdef BCM_CMICM_SUPPORT 1814 if (pcid_info->cmicm >= CMC0) { 1815 /* PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) |= SC_CMCx_MSG_DONE; */ 1816 pcid_reg_or_write(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET, SC_CMCx_MSG_DONE); 1817 } else 1818 #endif 1819 { 1820 /* PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_DONE_TST; */ 1821 pcid_reg_or_write(pcid_info, CMIC_SCHAN_CTRL, SC_MSG_DONE_TST); 1822 } 1823 } 1824 1825 if (soc_feature(unit, soc_feature_schmsg_alias)) { 1826 /* Synchronize message buffer (at 0) with aliased memory */ 1827 memcpy(&(PCIM(pcid_info, 0)), 1828 &(PCIM(pcid_info, PCIM_ALIAS_OFFSET)), PCIM_ALIASED_BYTES); 1829 } 1830 1831 if(data) { 1832 *data = *msg; 1833 } 1834 1835 return rv; 1836 } 1837 1838 /* 1839 * soc_internal_table_dma 1840 * 1841 * Do a table DMA transfer 1842 */ 1843 1844 void 1845 soc_internal_table_dma(pcid_info_t *pcid_info) 1846 { 1847 uint32 entry[SOC_MAX_MEM_WORDS]; 1848 uint32 table_addr; 1849 uint32 dma_addr; 1850 uint32 dma_count; 1851 uint32 dma_beats; 1852 1853 table_addr = PCIM(pcid_info, CMIC_TABLE_DMA_START); 1854 dma_addr = PCIM(pcid_info, CMIC_ARL_DMA_ADDR); 1855 dma_count = PCIM(pcid_info, CMIC_ARL_DMA_CNT) & 0x1fffffff; 1856 dma_beats = PCIM(pcid_info, CMIC_ARL_DMA_CNT) >> 29; 1857 1858 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1859 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x beats=%d dest=0x%x\n"), 1860 table_addr, dma_count, dma_beats, dma_addr)); 1861 1862 while (dma_count-- > 0) { 1863 soc_internal_read_mem(pcid_info, table_addr, entry); 1864 table_addr++; 1865 1866 soc_internal_memory_store(pcid_info, dma_addr, 1867 (uint8 *)entry, dma_beats * 4, 1868 MF_ES_DMA_OTHER); 1869 dma_addr += dma_beats * 4; 1870 } 1871 1872 1873 1874 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_ARL_DMA_DONE_TST; 1875 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_ARL_DMA_CNT0; 1876 soc_internal_send_int(pcid_info); 1877 } 1878 1879 /* 1880 * soc_internal_xgs3_table_dma 1881 * 1882 * Do a table DMA transfer 1883 */ 1884 1885 #define DMA_BURST_SIZE 256 /* Max number of WORDS per DMA transfer */ 1886 1887 #if DMA_BURST_SIZE < SOC_MAX_MEM_WORDS 1888 #error Burst size is too small 1889 #endif 1890 1891 #define DMA_BURST_ALLOC (DMA_BURST_SIZE + SOC_MAX_MEM_WORDS) 1892 /* Max number of WORDS per DMA transfer + datum mem read overhead*/ 1893 1894 void 1895 soc_internal_xgs3_table_dma(pcid_info_t *pcid_info) 1896 { 1897 uint32 entry[DMA_BURST_ALLOC]; 1898 uint32 table_addr; 1899 uint32 dma_addr; 1900 uint32 dma_count; 1901 uint32 dma_incr; 1902 uint32 dma_beats; 1903 int i, burst_count; 1904 schan_msg_t *msg; 1905 int opcode, dst_blk, src_blk, acc_type, data_byte_len, dma; 1906 uint32 bank_ignore_mask; 1907 1908 msg = (schan_msg_t *)&PCIM(pcid_info, 1909 CMIC_SCHAN_MESSAGE(pcid_info->unit, 0)); 1910 1911 if (!(PCIM(pcid_info, CMIC_TABLE_DMA_CFG) & CMIC_TDMA_CFG_EN)) { 1912 return; 1913 } 1914 soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode, 1915 &dst_blk, &src_blk, &acc_type, &data_byte_len, 1916 &dma, &bank_ignore_mask); 1917 1918 table_addr = PCIM(pcid_info, CMIC_TABLE_DMA_SBUS_START_ADDR); 1919 dma_addr = PCIM(pcid_info, CMIC_TABLE_DMA_PCIMEM_START_ADDR); 1920 dma_count = PCIM(pcid_info, CMIC_TABLE_DMA_ENTRY_COUNT) & 0xffffff; 1921 dma_incr = (PCIM(pcid_info, CMIC_TABLE_DMA_ENTRY_COUNT) >> 24) & 0x1f; 1922 dma_beats = (PCIM(pcid_info, CMIC_TABLE_DMA_CFG) >> 16) & (0x1f); 1923 1924 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1925 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x inc=%d beats=%d dest=0x%x\n"), 1926 table_addr, dma_count, dma_incr, dma_beats, dma_addr)); 1927 1928 burst_count = DMA_BURST_SIZE / dma_beats; 1929 1930 while (dma_count > 0) { 1931 /* Adjust the burst size at the end of the table */ 1932 if (dma_count < burst_count) burst_count = dma_count; 1933 1934 /* Read as many entries as can fit in the burst buffer */ 1935 for (i = 0; i < burst_count; i++) { 1936 soc_internal_extended_read_bytes 1937 (pcid_info, dst_blk, 0, table_addr, 1938 (uint8 *) (entry + i * dma_beats), 1939 dma_beats * (sizeof(uint32))); 1940 table_addr += 1 << dma_incr; 1941 } 1942 1943 /* convert to CPU endian-ness */ 1944 for (i=0; i < (burst_count * dma_beats); i++) { 1945 *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 1946 MF_ES_DMA_OTHER); 1947 } 1948 1949 /* Send all these entries in one shot */ 1950 soc_internal_bytes_store(pcid_info, dma_addr, (uint8 *)entry, 1951 (dma_beats * sizeof(uint32) * burst_count)); 1952 dma_addr += dma_beats * sizeof(uint32) * burst_count; 1953 dma_count -= burst_count; 1954 } 1955 1956 PCIM(pcid_info, CMIC_TABLE_DMA_CFG) |= CMIC_TDMA_CFG_DONE; 1957 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_TDMA_DONE; 1958 soc_internal_send_int(pcid_info); 1959 } 1960 1961 #ifdef BCM_CMICM_SUPPORT 1962 void 1963 soc_internal_xgs3_cmicm_table_dma(pcid_info_t *pcid_info) 1964 { 1965 uint32 entry[DMA_BURST_ALLOC]; 1966 uint32 table_addr; 1967 uint32 dma_addr; 1968 uint32 dma_count; 1969 uint32 dma_incr; 1970 uint32 dma_beats; 1971 int i, burst_count; 1972 soc_block_t block; 1973 int acc_type; 1974 1975 if (!(PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_CFG_OFFSET) & CMIC_TDMA_CFG_EN)) { 1976 return; 1977 } 1978 1979 table_addr = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_START_ADDR_OFFSET); 1980 dma_addr = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_PCIMEM_START_ADDR_OFFSET); 1981 dma_count = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_ENTRY_COUNT_OFFSET) & 0xffffff; 1982 dma_incr = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_ENTRY_COUNT_OFFSET) >> 24) & 0x1f; 1983 dma_beats = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_CFG_OFFSET) >> 11) & (0x1f); 1984 1985 block = (PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIG_OFFSET) >> 3) & 0x3f; 1986 acc_type = PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIG_OFFSET) & 7; 1987 1988 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1989 (BSL_META("Table DMA: schan_addr=0x%x block: %d acc_type=%d " 1990 "count=0x%x inc=%d beats=%d dest=0x%x\n"), 1991 table_addr, block, acc_type, dma_count, dma_incr, dma_beats, 1992 dma_addr)); 1993 1994 burst_count = DMA_BURST_SIZE / dma_beats; 1995 1996 while (dma_count > 0) { 1997 /* Adjust the burst size at the end of the table */ 1998 if (dma_count < burst_count) burst_count = dma_count; 1999 2000 /* Read as many entries as can fit in the burst buffer */ 2001 for (i = 0; i < burst_count; i++) { 2002 soc_internal_extended_read_bytes(pcid_info, block, acc_type, 2003 table_addr, 2004 (uint8 *) (entry + i * dma_beats), 2005 dma_beats * (sizeof(uint32))); 2006 table_addr += 1 << dma_incr; 2007 } 2008 2009 /* convert to CPU endian-ness */ 2010 for (i=0; i < (burst_count * dma_beats); i++) { 2011 *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 2012 MF_ES_DMA_OTHER); 2013 } 2014 2015 /* Send all these entries in one shot */ 2016 soc_internal_bytes_store(pcid_info, dma_addr, (uint8 *)entry, 2017 (dma_beats * sizeof(uint32) * burst_count)); 2018 dma_addr += dma_beats * sizeof(uint32) * burst_count; 2019 dma_count -= burst_count; 2020 } 2021 2022 PCIM(pcid_info, CMIC_CMC0_TABLE_DMA_STAT_OFFSET) |= TDMA_DONE; 2023 PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_TDMA_DONE; 2024 soc_internal_cmicm_send_int(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET); 2025 } 2026 #endif 2027 2028 /* 2029 * soc_internal_xgs3_tslam_dma 2030 * 2031 * Do a table SLAM DMA transfer 2032 */ 2033 2034 void 2035 soc_internal_xgs3_tslam_dma(pcid_info_t *pcid_info) 2036 { 2037 uint32 entry[DMA_BURST_SIZE]; 2038 uint32 table_addr; 2039 uint32 dma_addr; 2040 uint32 dma_count; 2041 uint32 dma_incr; 2042 uint32 dma_beats; 2043 int direction; 2044 int i, burst_count, entry_idx; 2045 schan_msg_t *msg; 2046 int opcode, dst_blk, src_blk, acc_type, data_byte_len, dma; 2047 uint32 bank_ignore_mask; 2048 2049 msg = (schan_msg_t *)&PCIM(pcid_info, 2050 CMIC_SCHAN_MESSAGE(pcid_info->unit, 0)); 2051 2052 if (!(PCIM(pcid_info, CMIC_SLAM_DMA_CFG) & CMIC_SLAM_CFG_EN)) { 2053 return; 2054 } 2055 2056 soc_schan_header_cmd_get(pcid_info->unit, &msg->header, &opcode, 2057 &dst_blk, &src_blk, &acc_type, &data_byte_len, 2058 &dma, &bank_ignore_mask); 2059 2060 table_addr = PCIM(pcid_info, CMIC_SLAM_DMA_SBUS_START_ADDR); 2061 dma_addr = PCIM(pcid_info, CMIC_SLAM_DMA_PCIMEM_START_ADDR); 2062 dma_count = PCIM(pcid_info, CMIC_SLAM_DMA_ENTRY_COUNT) & 0xffffff; 2063 dma_incr = (PCIM(pcid_info, CMIC_SLAM_DMA_ENTRY_COUNT) >> 24) & 0x1f; 2064 dma_beats = (PCIM(pcid_info, CMIC_SLAM_DMA_CFG) >> 16) & (0x1f); 2065 direction = (PCIM(pcid_info, CMIC_SLAM_DMA_CFG) & CMIC_SLAM_CFG_DIR); 2066 2067 if (direction) { 2068 /* Last entry */ 2069 dma_addr = dma_addr + dma_count * 4 * dma_beats; 2070 table_addr = table_addr + (dma_count - 1) * (1 << dma_incr); 2071 } 2072 2073 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2074 (BSL_META("Table DMA: schan_addr=0x%x count=0x%x inc=%d beats=%d dest=0x%x\n"), 2075 table_addr, dma_count, dma_incr, dma_beats, dma_addr)); 2076 2077 burst_count = DMA_BURST_SIZE / dma_beats; 2078 2079 while (dma_count > 0) { 2080 /* Adjust the burst size at the end of the table */ 2081 if (dma_count < burst_count) burst_count = dma_count; 2082 2083 /* Get as many entries as can fit in the burst buffer */ 2084 soc_internal_bytes_fetch(pcid_info, 2085 (direction ? 2086 (dma_addr - burst_count * dma_beats * 4) : 2087 dma_addr), 2088 (uint8 *)entry, 2089 dma_beats * 4 * burst_count); 2090 2091 /* convert to chip (same as host for sim) endian-ness */ 2092 for (i=0; i < (burst_count * dma_beats); i++) { 2093 *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 2094 MF_ES_DMA_OTHER); 2095 } 2096 2097 /* Write all the entries we've got */ 2098 for (i = 0; i < burst_count; i++) { 2099 entry_idx = direction ? burst_count - i - 1 : i; 2100 soc_internal_extended_write_bytes 2101 (pcid_info, dst_blk, 0, table_addr, 2102 (uint8 *)(entry + entry_idx * dma_beats), dma_beats * 4); 2103 table_addr += direction ? -(1 << dma_incr) : 1 << dma_incr; 2104 } 2105 2106 dma_addr += (direction ? -(dma_beats * 4 * burst_count) : 2107 (dma_beats * 4 * burst_count)); 2108 dma_count -= burst_count; 2109 } 2110 2111 PCIM(pcid_info, CMIC_SLAM_DMA_CFG) |= CMIC_SLAM_CFG_DONE; 2112 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_TSLAM_DONE; 2113 soc_internal_send_int(pcid_info); 2114 } 2115 2116 #ifdef BCM_CMICM_SUPPORT 2117 void 2118 soc_internal_xgs3_cmicm_tslam_dma(pcid_info_t *pcid_info) 2119 { 2120 uint32 entry[DMA_BURST_SIZE]; 2121 uint32 table_addr; 2122 uint32 dma_addr; 2123 uint32 dma_count; 2124 uint32 dma_incr; 2125 uint32 dma_beats; 2126 int direction; 2127 int i, burst_count, entry_idx; 2128 soc_block_t block; 2129 int acc_type; 2130 2131 if (!(PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) & CMIC_SLAM_CFG_EN)) { 2132 return; 2133 } 2134 2135 table_addr = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_START_ADDR_OFFSET); 2136 dma_addr = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_PCIMEM_START_ADDR_OFFSET); 2137 dma_count = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_ENTRY_COUNT_OFFSET) & 0xffffff; 2138 dma_incr = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_ENTRY_COUNT_OFFSET) >> 24) & 0x1f; 2139 dma_beats = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) >> 11) & (0x1f); 2140 direction = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_CFG_OFFSET) & SLDMA_CFG_DIR); 2141 2142 block = (PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIG_OFFSET) >> 3) & 0x3f; 2143 acc_type = PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIG_OFFSET) & 7; 2144 2145 if (direction) { 2146 /* Last entry */ 2147 dma_addr = dma_addr + dma_count * 4 * dma_beats; 2148 table_addr = table_addr + (dma_count - 1) * (1 << dma_incr); 2149 } 2150 2151 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2152 (BSL_META("Table DMA: schan_addr=0x%x block=%d acc_type=%d " 2153 "count=0x%x inc=%d beats=%d dest=0x%x\n"), 2154 table_addr, block, acc_type, dma_count, dma_incr, dma_beats, 2155 dma_addr)); 2156 2157 burst_count = DMA_BURST_SIZE / dma_beats; 2158 2159 while (dma_count > 0) { 2160 /* Adjust the burst size at the end of the table */ 2161 if (dma_count < burst_count) burst_count = dma_count; 2162 2163 /* Get as many entries as can fit in the burst buffer */ 2164 soc_internal_bytes_fetch(pcid_info, 2165 (direction ? 2166 (dma_addr - burst_count * dma_beats * 4) : 2167 dma_addr), 2168 (uint8 *)entry, 2169 dma_beats * 4 * burst_count); 2170 2171 /* convert to chip (same as host for sim) endian-ness */ 2172 for (i=0; i < (burst_count * dma_beats); i++) { 2173 *(entry + i) = soc_internal_endian_swap(pcid_info, *(entry + i), 2174 MF_ES_DMA_OTHER); 2175 } 2176 2177 /* Write all the entries we've got */ 2178 for (i = 0; i < burst_count; i++) { 2179 entry_idx = direction ? burst_count - i - 1 : i; 2180 soc_internal_extended_write_bytes(pcid_info, block, acc_type, 2181 table_addr, 2182 (uint8 *)(entry + entry_idx * dma_beats), 2183 dma_beats * 4); 2184 table_addr += direction ? -(1 << dma_incr) : 1 << dma_incr; 2185 } 2186 2187 dma_addr += (direction ? -(dma_beats * 4 * burst_count) : 2188 (dma_beats * 4 * burst_count)); 2189 dma_count -= burst_count; 2190 } 2191 2192 PCIM(pcid_info, CMIC_CMC0_SLAM_DMA_STAT_OFFSET) |= SLDMA_DONE; 2193 PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_TSLAM_DONE; 2194 soc_internal_cmicm_send_int(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET); 2195 } 2196 2197 void 2198 soc_internal_cmicm_sbusdma(pcid_info_t *pcid_info, uint32 reg) 2199 { 2200 schan_msg_t msg; 2201 int opcode, dst_blk, src_blk, acc_type, data_byte_len, dma; 2202 uint32 bank_ignore_mask; 2203 uint32 buffer[DMA_BURST_ALLOC]; 2204 uint32 rval; 2205 uint32 host_addr, sbus_addr, index, offset; 2206 int host_incr, sbus_incr, index_incr, offset_incr; 2207 uint32 dma_count, beats; 2208 int i, burst_count, burst_size; 2209 int8 ch; 2210 int cmc; 2211 soc_mem_t mem; 2212 soc_field_t field; 2213 2214 cmc = ((reg >> 12) & 0x3) - 1; 2215 ch = ((reg & 0xfff) - 0x600) / 0x50; 2216 2217 rval = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch)); 2218 if (!soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, 2219 rval, STARTf)) { 2220 return; 2221 } 2222 2223 msg.header_dword = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_OPCODE(cmc, ch)); 2224 soc_schan_header_cmd_get(pcid_info->unit, &msg.header, &opcode, 2225 &dst_blk, &src_blk, &acc_type, &data_byte_len, 2226 &dma, &bank_ignore_mask); 2227 2228 switch (opcode) { 2229 case WRITE_MEMORY_CMD_MSG: 2230 field = REQ_WORDSf; 2231 break; 2232 case READ_MEMORY_CMD_MSG: 2233 field = REP_WORDSf; 2234 break; 2235 default: 2236 return; 2237 } 2238 host_addr = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_HOSTADDR(cmc, ch)); 2239 sbus_addr = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_ADDRESS(cmc, ch)); 2240 dma_count = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_COUNT(cmc, ch)); 2241 2242 mem = soc_addr_to_mem_extended(pcid_info->unit, dst_blk, acc_type, sbus_addr); 2243 assert(mem != INVALIDm); 2244 index = sbus_addr ^ SOC_MEM_INFO(pcid_info->unit, mem).base; 2245 2246 rval = PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch)); 2247 beats = soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, 2248 rval, field); 2249 offset_incr = soc_reg_field_get(pcid_info->unit, 2250 CMIC_CMC0_SBUSDMA_CH0_REQUESTr, rval, 2251 REQ_SINGLEf) ? 0 : beats; 2252 host_incr = offset_incr * sizeof(uint32); 2253 if (soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, 2254 rval, INCR_NOADDf)) { 2255 sbus_incr = 0; 2256 index_incr = 0; 2257 } else { 2258 sbus_incr = 2259 1 << soc_reg_field_get(pcid_info->unit, 2260 CMIC_CMC0_SBUSDMA_CH0_REQUESTr, 2261 rval, INCR_SHIFTf); 2262 index_incr = 1; 2263 } 2264 2265 if (host_incr == 0) { 2266 burst_count = dma_count; 2267 burst_size = beats * sizeof(uint32); 2268 } else { 2269 burst_count = DMA_BURST_SIZE / beats; 2270 burst_size = burst_count * beats * sizeof(uint32); 2271 } 2272 2273 if (soc_reg_field_get(pcid_info->unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, 2274 rval, DECRf)) { 2275 sbus_addr += (dma_count - 1) * sbus_incr; 2276 sbus_incr = -sbus_incr; 2277 index_incr = -index_incr; 2278 } 2279 2280 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2281 (BSL_META("SBUS DMA: mem=%d index=0x%x sbus_addr=0x%x dst_blk=%d acc_type=%d" 2282 "dma_cout=0x%x beats=%d sbus_incr=%d host_addr=0x%x host_incr=%d\n"), 2283 mem, index, sbus_addr, dst_blk, acc_type, dma_count, beats, sbus_incr, 2284 host_addr, host_incr)); 2285 2286 if (opcode == WRITE_MEMORY_CMD_MSG) { 2287 while (dma_count > 0) { 2288 /* Adjust the burst size at the end of the table */ 2289 if (dma_count < burst_count) { 2290 burst_count = dma_count; 2291 burst_size = burst_count * beats * sizeof(uint32); 2292 } 2293 2294 /* Fill the burst buffer from S-chan socket */ 2295 soc_internal_bytes_fetch(pcid_info, host_addr, (uint8 *)buffer, 2296 burst_size); 2297 2298 /* Convert to device (same as host for sim) endian-ness */ 2299 for (i = 0; i < burst_size / sizeof(uint32); i++) { 2300 buffer[i] = soc_internal_endian_swap(pcid_info, buffer[i], 2301 MF_ES_DMA_OTHER); 2302 } 2303 2304 /* Write entries from burst buffer to sim storage */ 2305 offset = 0; 2306 for (i = 0; i < burst_count; i++) { 2307 soc_internal_extended_write_mem_index(pcid_info, mem, index, 2308 &buffer[offset]); 2309 index += index_incr; 2310 offset += offset_incr; 2311 } 2312 2313 sbus_addr += sbus_incr * burst_count; 2314 host_addr += host_incr * burst_count; 2315 dma_count -= burst_count; 2316 } 2317 } else { 2318 while (dma_count > 0) { 2319 /* Adjust the burst size at the end of the table */ 2320 if (dma_count < burst_count) { 2321 burst_count = dma_count; 2322 burst_size = burst_count * beats * sizeof(uint32); 2323 } 2324 2325 /* Read entries sim storage into burst buffer */ 2326 offset = 0; 2327 for (i = 0; i < burst_count; i++) { 2328 soc_internal_extended_read_mem_index(pcid_info, mem, index, 2329 &buffer[offset]); 2330 index += index_incr; 2331 offset += offset_incr; 2332 } 2333 2334 /* Convert to host (same as device for sim) endian-ness */ 2335 for (i = 0; i < burst_size / sizeof(uint32); i++) { 2336 buffer[i] = soc_internal_endian_swap(pcid_info, buffer[i], 2337 MF_ES_DMA_OTHER); 2338 } 2339 2340 /* Flush the burst buffer into S-chan socket */ 2341 soc_internal_bytes_store(pcid_info, host_addr, (uint8 *)buffer, 2342 burst_size); 2343 2344 sbus_addr += sbus_incr * burst_count; 2345 host_addr += host_incr * burst_count; 2346 dma_count -= burst_count; 2347 } 2348 } 2349 2350 PCIM(pcid_info, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)) |= 2351 ST_CMCx_SBUSDMA_DONE; 2352 PCIM(pcid_info, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)) |= 2353 IRQ_CMCx_SBUSDMA_CH_DONE(ch); 2354 soc_internal_cmicm_send_int(pcid_info, 2355 CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc)); 2356 } 2357 #endif 2358 2359 void 2360 soc_internal_schan_ctrl_write(pcid_info_t *pcid_info, uint32 value) 2361 { 2362 if (value & 0x80) { 2363 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2364 (BSL_META("Set SCHAN_CTRL bit %d\n"), value & 0x1f)); 2365 switch (value & 0xff) { 2366 case SC_MSG_START_SET: 2367 if ((pcid_info->schan_cb) && 2368 (pcid_info->schan_cb(pcid_info, pcid_info->unit, NULL) == 0)) { 2369 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_SCH_MSG_DONE; 2370 soc_internal_send_int(pcid_info); 2371 break; 2372 } else { 2373 if (schan_op(pcid_info, pcid_info->unit, NULL) == 0) { 2374 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_SCH_MSG_DONE; 2375 soc_internal_send_int(pcid_info); 2376 } 2377 } 2378 break; 2379 case SC_MIIM_RD_START_SET: 2380 soc_internal_miim_op(pcid_info, 1); 2381 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_MIIM_OP_DONE; 2382 soc_internal_send_int(pcid_info); 2383 break; 2384 case SC_MIIM_WR_START_SET: 2385 soc_internal_miim_op(pcid_info, 0); 2386 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_MIIM_OP_DONE; 2387 soc_internal_send_int(pcid_info); 2388 break; 2389 case SC_ARL_DMA_EN_SET: 2390 if (SOC_IS_XGS_SWITCH(pcid_info->unit)) { 2391 soc_internal_table_dma(pcid_info); 2392 PCIM(pcid_info, CMIC_IRQ_STAT) |= IRQ_ARL_DMA_CNT0; 2393 soc_internal_send_int(pcid_info); 2394 } else { 2395 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= 1 << (value & 0x1f); 2396 } 2397 break; 2398 default: 2399 PCIM(pcid_info, CMIC_SCHAN_CTRL) |= 1 << (value & 0x1f); 2400 break; 2401 } 2402 } else { 2403 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2404 (BSL_META("Clear SCHAN_CTRL bit %d\n"), value & 0x1f)); 2405 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~(1 << (value & 0x1f)); 2406 switch (value & 0xff) { 2407 case SC_MSG_DONE_CLR: 2408 PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_SCH_MSG_DONE; 2409 break; 2410 case SC_MIIM_OP_DONE_CLR: 2411 PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_MIIM_OP_DONE; 2412 break; 2413 case SC_ARL_DMA_EN_CLR: 2414 PCIM(pcid_info, CMIC_IRQ_STAT) &= ~IRQ_ARL_DMA_CNT0; 2415 break; 2416 default: 2417 break; 2418 } 2419 } 2420 } 2421 2422 #ifdef BCM_CMICM_SUPPORT 2423 void 2424 soc_internal_cmicm_schan_ctrl_write(pcid_info_t *pcid_info, uint32 reg, uint32 value) 2425 { 2426 if (value & SC_CMCx_MSG_START) { 2427 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2428 (BSL_META("SCHAN_CTRL msg start.\n"))); 2429 if ((pcid_info->schan_cb) && 2430 (pcid_info->schan_cb(pcid_info, pcid_info->unit, NULL) == 0)) { 2431 PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_SCH_OP_DONE; 2432 soc_internal_cmicm_send_int(pcid_info, reg); 2433 } else { 2434 if (schan_op(pcid_info, pcid_info->unit, NULL) == 0) { 2435 PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= 2436 ~(SC_CMCx_MSG_SER_CHECK_FAIL | SC_CMCx_MSG_NAK | SC_CMCx_MSG_TIMEOUT_TST); 2437 PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) |= IRQ_CMCx_SCH_OP_DONE; 2438 soc_internal_cmicm_send_int(pcid_info, reg); 2439 } 2440 } 2441 } else { 2442 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2443 (BSL_META("SCHAN_CTRL msg done.\n"))); 2444 PCIM(pcid_info, CMIC_CMC0_SCHAN_CTRL_OFFSET) &= 2445 ~(SC_CMCx_MSG_DONE | SC_CMCx_MSG_SER_CHECK_FAIL | 2446 SC_CMCx_MSG_NAK | SC_CMCx_MSG_TIMEOUT_TST); 2447 } 2448 } 2449 #endif 2450 2451 void 2452 soc_internal_reset(pcid_info_t *pcid_info) 2453 { 2454 int index; 2455 soc_datum_t *d; 2456 2457 memset(&PCIM(pcid_info, 0), 0, PCIM_SIZE(0)); 2458 2459 #ifdef BCM_CMICM_SUPPORT 2460 if (pcid_info->single_mode) { 2461 pcid_info->cmicm = CMC0; 2462 } else { 2463 if (soc_feature(pcid_info->unit, soc_feature_cmicm)) { 2464 pcid_info->cmicm = CMC0; 2465 2466 } else 2467 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 2468 if (soc_feature(pcid_info->unit, soc_feature_cmicx) && 2469 (SOC_IS_DNX(pcid_info->unit) || SOC_IS_DNXF(pcid_info->unit))) { 2470 /* Use CMICM simulation instead of CMICX simulation */ 2471 pcid_info->cmicm = CMC0; 2472 } else 2473 #endif /* BCM_DNX_SUPPORT || BCM_DNXF_SUPPORT */ 2474 #endif 2475 { 2476 pcid_info->cmicm = -1; 2477 PCIM(pcid_info, CMIC_SCHAN_CTRL) = 0x48002; 2478 } 2479 #ifdef BCM_CMICM_SUPPORT 2480 } 2481 #endif 2482 /* 2483 * Delete all register values from hash table, which effectively 2484 * returns them to their reset default values. 2485 */ 2486 for (index = 0; index < SOC_DATUM_HASH_SIZE; index++) { 2487 while ((d = pcid_info->reg_ht[index]) != NULL) { 2488 pcid_info->reg_ht[index] = d->next; 2489 sal_free(d); 2490 } 2491 } 2492 2493 /* 2494 * Delete all memory entries from hash table, which effectively 2495 * returns them to their null entry values. 2496 */ 2497 for (index = 0; index < SOC_DATUM_HASH_SIZE; index++) { 2498 while ((d = pcid_info->mem_ht[index]) != NULL) { 2499 pcid_info->mem_ht[index] = d->next; 2500 sal_free(d); 2501 } 2502 } 2503 2504 /* 2505 * Invoke reset callback if installed. 2506 */ 2507 if (pcid_info->reset_cb) { 2508 pcid_info->reset_cb(pcid_info, pcid_info->unit); 2509 } 2510 } 2511 2512 uint32 2513 soc_internal_endian_swap(pcid_info_t *pcid_info, uint32 data, int mode) 2514 { 2515 if (((mode == MF_ES_DMA_PACKET) && 2516 (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_DMA_PACKET)) 2517 || 2518 ((mode == MF_ES_DMA_OTHER) && 2519 (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_DMA_OTHER)) 2520 || 2521 ((mode == MF_ES_PIO) && 2522 (PCIM(pcid_info, CMIC_ENDIAN_SELECT) & ES_BIG_ENDIAN_PIO))) { 2523 data = (data << 16) | (data >> 16); 2524 return (data & 0xff00ffff) >> 8 | (data & 0xffff00ff) << 8; 2525 } else { 2526 return(data); 2527 } 2528 } 2529 2530 void 2531 soc_internal_memory_fetch(pcid_info_t *pcid_info, uint32 addr, uint8 *b, 2532 int length, int mode) 2533 { 2534 uint32 offset; 2535 2536 if (pcid_info->opt_rpc_error) { 2537 return; 2538 } 2539 2540 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2541 (BSL_META("soc_internal_memory_fetch: addr=0x%08x length=%d\n"), 2542 addr, length)); 2543 2544 /* 2545 * For memory fetch, any alignment is allowed, but 4-byte accesses 2546 * are always made. This is slow but .... 2547 */ 2548 offset = addr & 3; 2549 2550 addr &= ~3; /* Only read 4-bytes */ 2551 2552 while (length) { 2553 uint32 data; 2554 int tl; 2555 int rv; 2556 2557 rv = dma_readmem(pcid_info->client->dmasock, addr, &data); 2558 if (rv != RPC_OK) { 2559 LOG_ERROR(BSL_LS_SOC_COMMON, 2560 (BSL_META("RPC error: soc_internal_memory_fetch failed. \n"))); 2561 pcid_info->opt_rpc_error = 1; 2562 break; 2563 } 2564 2565 data = 2566 soc_internal_endian_swap(pcid_info, 2567 data, 2568 mode); 2569 tl = (sizeof(uint32) - offset); 2570 if (length < tl) { 2571 tl = length; 2572 } 2573 2574 sal_memcpy(b, ((uint8 *)&data) + offset, tl); 2575 length -= tl; 2576 addr += 4; 2577 b += 4 - offset; 2578 offset = 0; 2579 } 2580 } 2581 2582 /* Get a string of bytes from memory addr given length; store in buf. */ 2583 void 2584 soc_internal_bytes_fetch(pcid_info_t *pcid_info, uint32 addr, uint8 *buf, 2585 int length) 2586 { 2587 int read_len; 2588 2589 if (pcid_info->opt_rpc_error) { 2590 return; 2591 } 2592 2593 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2594 (BSL_META("soc_internal_bytes_fetch: addr=0x%08x length=%d\n"), 2595 addr, length)); 2596 2597 read_len = dma_read_bytes(pcid_info->client->dmasock, addr, buf, length); 2598 2599 if (read_len != length) { 2600 LOG_ERROR(BSL_LS_SOC_COMMON, 2601 (BSL_META("soc_internal_bytes_fetch: length mismatch. want %d. got %d\n"), 2602 length, read_len)); 2603 } 2604 2605 if (read_len < 0) { 2606 LOG_ERROR(BSL_LS_SOC_COMMON, 2607 (BSL_META("RPC error: soc_internal_bytes_fetch failed. \n"))); 2608 pcid_info->opt_rpc_error = 1; 2609 } 2610 } 2611 2612 /* Get a string of bytes from memory addr given length; store in buf. */ 2613 void 2614 soc_internal_bytes_store(pcid_info_t *pcid_info, uint32 addr, uint8 *buf, 2615 int length) 2616 { 2617 int rv; 2618 2619 if (pcid_info->opt_rpc_error) { 2620 return; 2621 } 2622 2623 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2624 (BSL_META("soc_internal_bytes_store: addr=0x%08x length=%d\n"), 2625 addr, length)); 2626 2627 rv = dma_write_bytes(pcid_info->client->dmasock, addr, buf, length); 2628 if (rv < 0) { 2629 LOG_ERROR(BSL_LS_SOC_COMMON, 2630 (BSL_META("RPC error: soc_internal_bytes_store failed. \n"))); 2631 pcid_info->opt_rpc_error = 1; 2632 } 2633 } 2634 2635 void 2636 soc_internal_memory_store(pcid_info_t *pcid_info, uint32 addr, uint8 *b, 2637 int length, int mode) 2638 { 2639 uint32 data; 2640 int rv; 2641 2642 if (pcid_info->opt_rpc_error) { 2643 return; 2644 } 2645 2646 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2647 (BSL_META("soc_internal_memory_store: addr=0x%08x length=%d\n"), 2648 addr, length)); 2649 2650 /* 2651 * Strata (and friends) only support 4-byte aligned writes 2652 */ 2653 2654 addr &= ~3; 2655 2656 while (length > 0) { 2657 sal_memcpy(&data, b, length < sizeof(data) ? length : sizeof(data)); 2658 rv = dma_writemem(pcid_info->client->dmasock, 2659 addr, soc_internal_endian_swap(pcid_info, data, mode)); 2660 if (rv != RPC_OK) { 2661 LOG_ERROR(BSL_LS_SOC_COMMON, 2662 (BSL_META("RPC error: soc_internal_memory_store failed. \n"))); 2663 pcid_info->opt_rpc_error = 1; 2664 break; 2665 } 2666 b += sizeof(uint32); 2667 addr += sizeof(uint32); 2668 length -= sizeof(uint32); 2669 } 2670 } 2671 2672 /* 2673 * soc_internal_send_int 2674 * 2675 * Checks if any interrupt is pending, and if so, sends an interrupt 2676 * over the PLI socket. 2677 */ 2678 2679 void 2680 soc_internal_send_int(pcid_info_t *pcid_info) 2681 { 2682 int rv; 2683 2684 if (pcid_info->opt_rpc_error) { 2685 return; 2686 } 2687 if (PCIM(pcid_info, CMIC_IRQ_MASK) & PCIM(pcid_info, CMIC_IRQ_STAT)) { 2688 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2689 (BSL_META("Send interrupt: msk 0x%x stat 0x%x\n"), 2690 PCIM(pcid_info, CMIC_IRQ_MASK), PCIM(pcid_info, CMIC_IRQ_STAT))); 2691 rv = send_interrupt(pcid_info->client->intsock, 0); 2692 if (rv < 0) { 2693 LOG_ERROR(BSL_LS_SOC_COMMON, 2694 (BSL_META("RPC error: soc_internal_send_int failed. \n"))); 2695 pcid_info->opt_rpc_error = 1; 2696 } 2697 } else { 2698 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2699 (BSL_META("Interrupt masked: msk 0x%x stat 0x%x\n"), 2700 PCIM(pcid_info, CMIC_IRQ_MASK), PCIM(pcid_info, CMIC_IRQ_STAT))); 2701 } 2702 } 2703 2704 #ifdef BCM_CMICM_SUPPORT 2705 void 2706 soc_internal_cmicm_send_int(pcid_info_t *pcid_info, uint32 reg) 2707 { 2708 int rv; 2709 2710 if (pcid_info->opt_rpc_error) { 2711 return; 2712 } 2713 switch (reg) { 2714 case CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET: 2715 if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET) & 2716 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET)) { 2717 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2718 (BSL_META("Send interrupt: msk0 0x%x stat0 0x%x\n"), 2719 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET), 2720 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET))); 2721 rv = send_interrupt(pcid_info->client->intsock, 0); 2722 if (rv < 0) { 2723 LOG_ERROR(BSL_LS_SOC_COMMON, 2724 (BSL_META("RPC error: soc_internal_send_int failed. \n"))); 2725 pcid_info->opt_rpc_error = 1; 2726 } 2727 } else { 2728 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2729 (BSL_META("Interrupt masked: msk0 0x%x stat0 0x%x\n"), 2730 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET), 2731 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET))); 2732 } 2733 break; 2734 case CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET: 2735 if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET) & 2736 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET)) { 2737 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2738 (BSL_META("Send interrupt: msk1 0x%x stat1 0x%x\n"), 2739 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET), 2740 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET))); 2741 rv = send_interrupt(pcid_info->client->intsock, 0); 2742 if (rv < 0) { 2743 LOG_ERROR(BSL_LS_SOC_COMMON, 2744 (BSL_META("RPC error: soc_internal_send_int failed. \n"))); 2745 pcid_info->opt_rpc_error = 1; 2746 } 2747 } else { 2748 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2749 (BSL_META("Interrupt masked: msk1 0x%x stat1 0x%x\n"), 2750 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET), 2751 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT1_OFFSET))); 2752 } 2753 break; 2754 case CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET: 2755 if (pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET) & 2756 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET)) { 2757 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2758 (BSL_META("Send interrupt: msk2 0x%x stat2 0x%x\n"), 2759 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET), 2760 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET))); 2761 rv = send_interrupt(pcid_info->client->intsock, 0); 2762 if (rv < 0) { 2763 LOG_ERROR(BSL_LS_SOC_COMMON, 2764 (BSL_META("RPC error: soc_internal_send_int failed. \n"))); 2765 pcid_info->opt_rpc_error = 1; 2766 } 2767 } else { 2768 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2769 (BSL_META("Interrupt masked: msk2 0x%x stat2 0x%x\n"), 2770 pcid_reg_read(pcid_info, CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET), 2771 pcid_reg_read(pcid_info, CMIC_CMC0_IRQ_STAT2_OFFSET))); 2772 } 2773 } 2774 } 2775 #endif 2776 2777 static const soc_reg_t ing_mpls_tpid_regs[] = { 2778 ING_MPLS_TPID_0r, ING_MPLS_TPID_1r, 2779 ING_MPLS_TPID_2r, ING_MPLS_TPID_3r 2780 }; 2781 static const soc_reg_t ing_outer_tpid_regs[] = { 2782 ING_OUTER_TPID_0r, ING_OUTER_TPID_1r, 2783 ING_OUTER_TPID_2r, ING_OUTER_TPID_3r 2784 }; 2785 static const soc_reg_t egr_outer_tpid_regs[] = { 2786 EGR_OUTER_TPID_0r, EGR_OUTER_TPID_1r, 2787 EGR_OUTER_TPID_2r, EGR_OUTER_TPID_3r 2788 }; 2789 2790 int 2791 soc_internal_extended_write_reg(pcid_info_t *pcid_info, 2792 soc_block_t block, int acc_type, 2793 uint32 address, uint32 *data) 2794 { 2795 soc_regaddrinfo_t ainfo; 2796 int rv; 2797 2798 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 2799 /* To fill in */ 2800 2801 soc_regaddrinfo_extended_get(pcid_info->unit, &ainfo, block, acc_type, 2802 address); 2803 2804 if (!ainfo.valid || ainfo.reg < 0) { 2805 LOG_ERROR(BSL_LS_SOC_COMMON, 2806 (BSL_META("Attempt to write to unknown S-channel " 2807 "block %d acc_type %d address 0x%x\n"), 2808 block, acc_type, address)); 2809 return SOC_E_NOT_FOUND; 2810 } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 2811 SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & 2812 SOC_REG_FLAG_RO) { 2813 LOG_ERROR(BSL_LS_SOC_COMMON, 2814 (BSL_META("Attempt to write to read-only S-channel address 0x%x\n"), 2815 address)); 2816 } 2817 2818 switch (ainfo.reg) { 2819 case EGR_OUTER_TPIDr: 2820 ainfo.reg = egr_outer_tpid_regs[(address >> 8) & 0x3]; 2821 ainfo.idx = -1; 2822 break; 2823 case ING_OUTER_TPIDr: 2824 ainfo.reg = ing_outer_tpid_regs[(address >> 8) & 0x3]; 2825 ainfo.idx = -1; 2826 break; 2827 case ING_MPLS_TPIDr: 2828 ainfo.reg = ing_mpls_tpid_regs[(address >> 8) & 0x3]; 2829 ainfo.idx = -1; 2830 break; 2831 } 2832 2833 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 2834 if (soc_feature(pcid_info->unit, soc_feature_logical_port_num)) { 2835 soc_info_t *si; 2836 int phy_port, num_phy_ports = SOC_MAX_NUM_PORTS; 2837 int blk; 2838 int field_len; 2839 2840 si = &SOC_INFO(pcid_info->unit); 2841 switch (ainfo.reg) { 2842 case EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr: 2843 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, 2844 data[0], PHYSICAL_PORT_NUMBERf); 2845 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg, 2846 PHYSICAL_PORT_NUMBERf); 2847 2848 if (SOC_MEM_IS_VALID(pcid_info->unit, ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm)) { 2849 num_phy_ports = soc_mem_index_count(pcid_info->unit, ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm); 2850 } 2851 2852 if ((phy_port != (1 << field_len) - 1) && 2853 (phy_port < num_phy_ports)){ 2854 si->port_p2l_mapping[phy_port] = ainfo.port; 2855 si->port_l2p_mapping[ainfo.port] = phy_port; 2856 blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port); 2857 si->port_type[ainfo.port] = 2858 SOC_BLOCK_INFO(pcid_info->unit, blk).type; 2859 if (ainfo.port > si->port.max) { 2860 si->port.max = ainfo.port; 2861 } 2862 } 2863 break; 2864 case MMU_TO_PHY_PORT_MAPPINGr: 2865 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, 2866 data[0], PHY_PORTf); 2867 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg, 2868 PHY_PORTf); 2869 if (phy_port != (1 << field_len) - 1) { 2870 si->port_p2m_mapping[phy_port] = ainfo.idx; 2871 /* coverity[negative_returns : FALSE] */ 2872 si->port_m2p_mapping[ainfo.idx] = phy_port; 2873 } 2874 break; 2875 case EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr: 2876 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, 2877 data[0], PHYSICAL_PORT_NUMBERf); 2878 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg, 2879 PHYSICAL_PORT_NUMBERf); 2880 if (phy_port != (1 << field_len) - 1) { 2881 si->port_p2l_mapping[phy_port] = ainfo.port; 2882 si->port_l2p_mapping[ainfo.port] = phy_port; 2883 blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port); 2884 si->port_type[ainfo.port] = 2885 SOC_BLOCK_INFO(pcid_info->unit, blk).type; 2886 if (ainfo.port > si->port.max) { 2887 si->port.max = ainfo.port; 2888 } 2889 } 2890 break; 2891 case MMU_PORT_TO_PHY_PORT_MAPPINGr: 2892 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, 2893 data[0], PHY_PORTf); 2894 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg, 2895 PHY_PORTf); 2896 if (phy_port != (1 << field_len) - 1) { 2897 si->port_p2m_mapping[phy_port] = address & 0xff; 2898 /* coverity[negative_returns : FALSE] */ 2899 si->port_m2p_mapping[address & 0xff] = phy_port; 2900 } 2901 break; 2902 case MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPINGr: 2903 phy_port = soc_reg_field_get(pcid_info->unit, ainfo.reg, 2904 data[0], PHY_PORT_NUMf); 2905 field_len = soc_reg_field_length(pcid_info->unit, ainfo.reg, 2906 PHY_PORT_NUMf); 2907 if (phy_port != (1 << field_len) - 1) { 2908 si->port_p2m_mapping[phy_port] = address & 0xff; 2909 /* coverity[negative_returns : FALSE] */ 2910 si->port_m2p_mapping[address & 0xff] = phy_port; 2911 } 2912 break; 2913 default: 2914 break; 2915 } 2916 } 2917 #endif /* BCM_TRIDENT_SUPPORT */ 2918 if (ainfo.acc_type < 0xff) { 2919 block |= acc_type << 24; 2920 } 2921 if (ainfo.reg == Q_SCHED_RQE_SNAPSHOTr) { 2922 *data &= ~0x1; /* always assume flush is finished. */ 2923 } 2924 rv = soc_datum_reg_write(pcid_info, ainfo, block, address, data); 2925 2926 return rv; 2927 } else { 2928 return soc_internal_write_reg(pcid_info, address, data); 2929 } 2930 } 2931 2932 int 2933 soc_internal_extended_read_reg(pcid_info_t *pcid_info, 2934 soc_block_t block, int acc_type, 2935 uint32 address, uint32 *data) 2936 { 2937 soc_regaddrinfo_t ainfo; 2938 int rv; 2939 2940 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 2941 /* To fill in */ 2942 2943 soc_regaddrinfo_extended_get(pcid_info->unit, &ainfo, block, acc_type, 2944 address); 2945 2946 if (!ainfo.valid || ainfo.reg < 0) { 2947 LOG_ERROR(BSL_LS_SOC_COMMON, 2948 (BSL_META("Attempt to read from unknown register S-channel " 2949 "block %d acc_type %d address 0x%x\n"), 2950 block, acc_type, address)); 2951 return SOC_E_NOT_FOUND; 2952 } else if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 2953 SOC_REG_INFO(pcid_info->unit, ainfo.reg).flags & SOC_REG_FLAG_WO) { 2954 LOG_ERROR(BSL_LS_SOC_COMMON, 2955 (BSL_META("Attempt to read from write-only S-channel address 0x%x\n"), 2956 address)); 2957 } 2958 2959 switch (ainfo.reg) { 2960 case EGR_OUTER_TPIDr: 2961 if (SOC_IS_GREYHOUND(pcid_info->unit) || 2962 SOC_IS_HURRICANE3(pcid_info->unit) || 2963 SOC_IS_GREYHOUND2(pcid_info->unit)){ 2964 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0x120013]; 2965 } else { 2966 ainfo.reg = egr_outer_tpid_regs[(address >> 8) & 0x3]; 2967 } 2968 ainfo.idx = -1; 2969 break; 2970 case ING_OUTER_TPIDr: 2971 if (SOC_IS_TRIUMPH3(pcid_info->unit)) { 2972 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa0016]; 2973 } else if (SOC_IS_KATANA2(pcid_info->unit)) { 2974 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa0017]; 2975 } else if (SOC_IS_HURRICANE2(pcid_info->unit) || 2976 SOC_IS_GREYHOUND(pcid_info->unit) || 2977 SOC_IS_HURRICANE3(pcid_info->unit) || 2978 SOC_IS_GREYHOUND2(pcid_info->unit)) { 2979 ainfo.reg = ing_outer_tpid_regs[(address >> 8) - 0xa000d]; 2980 } else { 2981 ainfo.reg = ing_outer_tpid_regs[(address >> 8) & 0x3]; 2982 } 2983 ainfo.idx = -1; 2984 break; 2985 case ING_MPLS_TPIDr: 2986 ainfo.reg = ing_mpls_tpid_regs[(address >> 8) & 0x3]; 2987 ainfo.idx = -1; 2988 break; 2989 } 2990 if (ainfo.acc_type < 0xff) { 2991 block |= acc_type << 24; 2992 } 2993 rv = soc_datum_reg_read(pcid_info, ainfo, block, address, data); 2994 if (SOC_E_NOT_FOUND == rv) { 2995 /* 2996 * The register is not in the hash table, so it has not been 2997 * written before. Provide a default value. 2998 */ 2999 if (SOC_REG_IS_VALID(pcid_info->unit, ainfo.reg) && 3000 (ainfo.valid && ainfo.reg >= 0)) { 3001 /*This macro handle both 64 and above_64 regs*/ 3002 SOC_REG_ABOVE_64_RST_VAL_GET(pcid_info->unit, ainfo.reg, data); 3003 } else { 3004 data[0] = 0xffffffff; 3005 data[1] = 0xffffffff; 3006 } 3007 rv = SOC_E_NONE; 3008 } 3009 3010 if (SOC_E_NONE == rv) { 3011 if (SOC_IS_TRIDENT3X(pcid_info->unit)) { 3012 static soc_field_t f_iter, field_done[] = { 3013 DONEf, 3014 INVALIDf 3015 }; 3016 for(f_iter = 0; field_done[f_iter] != INVALIDf; f_iter++) { 3017 if (soc_reg_field_valid(pcid_info->unit, ainfo.reg, 3018 field_done[f_iter])) { 3019 soc_reg_field_set(pcid_info->unit, ainfo.reg, 3020 data, field_done[f_iter], 1); 3021 } 3022 } 3023 } else if (SOC_IS_TOMAHAWK2(pcid_info->unit)) { 3024 soc_field_t f_iter; 3025 soc_field_t field_done[] = {DONEf, INVALIDf}; 3026 for(f_iter = 0; field_done[f_iter] != INVALIDf; f_iter++) { 3027 if (soc_reg_field_valid(pcid_info->unit, ainfo.reg, 3028 field_done[f_iter])) { 3029 soc_reg_field_set(pcid_info->unit, ainfo.reg, 3030 data, field_done[f_iter], 1); 3031 } 3032 } 3033 } else if (SOC_IS_TRIUMPH3(pcid_info->unit)) { 3034 /* ING/EGR/ISM_HW_RESET_CONTROL */ 3035 if (((address == 0x2010200) && (block == 1)) || 3036 ((address == 0x2010100) && (block == 2))) { 3037 data[0] |= (1 << 20); 3038 } 3039 if ((address == 0xfe000f00) && (block == 16)) { 3040 data[0] |= (1 << 31); 3041 } 3042 if ((address == 0x2000100) && (block == 3)) { 3043 data[0] |= 0x2; 3044 } 3045 if ((address == 0xfe000200) && (block == 16)) { 3046 data[0] |= 0x10; /* L2 ageing complete */ 3047 } 3048 if ((address == 0x5a000100) && (block == 3)) { 3049 data[0] |= 2; /* LLS init done */ 3050 } 3051 } else if (SOC_IS_TD2_TT2(pcid_info->unit)) { 3052 switch (ainfo.reg) { 3053 case ING_HW_RESET_CONTROL_2r: 3054 case ING_HW_RESET_CONTROL_2_Xr: 3055 case ING_HW_RESET_CONTROL_2_Yr: 3056 if(SOC_IS_TD2P_TT2P(pcid_info->unit) 3057 || SOC_IS_APACHE(pcid_info->unit)) { 3058 data[0] |= (1 << 22); 3059 } 3060 else { 3061 data[0] |= (1 << 21); 3062 } 3063 break; 3064 case EGR_HW_RESET_CONTROL_1r: 3065 case EGR_HW_RESET_CONTROL_1_Xr: 3066 case EGR_HW_RESET_CONTROL_1_Yr: 3067 data[0] |= (1 << 18); 3068 break; 3069 3070 case TOP_TSC_AFE_PLL_STATUSr: 3071 data[0] = 0xffffffff; 3072 break; 3073 default: 3074 break; 3075 } 3076 } 3077 } 3078 return rv; 3079 } else { 3080 return soc_internal_read_reg(pcid_info, address, data); 3081 } 3082 } 3083 3084 int 3085 _soc_internal_extended_write_mem(pcid_info_t *pcid_info, soc_mem_t mem, 3086 soc_block_t block, int acc_type, 3087 uint32 address, uint32 *data) 3088 { 3089 soc_mem_t alt_mem; 3090 uint32 offset, phy_port, field_len; 3091 uint8 alt_acc_type; 3092 int blk; 3093 soc_info_t *si; 3094 3095 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3096 if (mem != INVALIDm) { 3097 alt_mem = INVALIDm; 3098 switch(mem) { 3099 #ifdef BCM_XGS_SWITCH_SUPPORT 3100 case L3_ENTRY_IPV4_UNICASTm: 3101 case L3_ENTRY_IPV4_MULTICASTm: 3102 case L3_ENTRY_IPV6_UNICASTm: 3103 case L3_ENTRY_IPV6_MULTICASTm: 3104 return soc_internal_l3x2_write(pcid_info, mem, address, data); 3105 #ifdef BCM_TOMAHAWK_SUPPORT 3106 case EXACT_MATCH_2m: 3107 case EXACT_MATCH_4m: 3108 return soc_internal_exact_match_write(pcid_info, mem, address, 3109 data); 3110 #endif /* BCM_TOMAHAWK_SUPPORT */ 3111 case VLAN_MACm: 3112 alt_mem = VLAN_XLATEm; 3113 break; 3114 #endif 3115 default: 3116 break; 3117 } 3118 if (alt_mem != INVALIDm) { 3119 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base; 3120 mem = alt_mem; 3121 address = soc_mem_addr_get(pcid_info->unit, mem, 0, block, offset, 3122 &alt_acc_type); 3123 acc_type = alt_acc_type; 3124 } 3125 if (mem == EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm) { 3126 /* Update port mapping. */ 3127 si = &SOC_INFO(pcid_info->unit); 3128 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base; 3129 soc_mem_field_get(pcid_info->unit, mem, data, DATAf, &phy_port); 3130 field_len = soc_mem_field_length(pcid_info->unit, mem, DATAf); 3131 if (phy_port != (1 << field_len) - 1) { 3132 si->port_p2l_mapping[phy_port] = offset; 3133 si->port_l2p_mapping[offset] = phy_port; 3134 blk = SOC_PORT_BLOCK(pcid_info->unit, phy_port); 3135 si->port_type[offset] = 3136 SOC_BLOCK_INFO(pcid_info->unit, blk).type; 3137 if (offset > si->port.max) { 3138 si->port.max = offset; 3139 } 3140 } 3141 } 3142 if (soc_mem_is_aggr(pcid_info->unit, mem)) { 3143 return soc_internal_extended_write_aggrmem(pcid_info, block, 3144 acc_type, address, 3145 data); 3146 } 3147 } 3148 if (acc_type >= 0) { 3149 block |= acc_type << 24; 3150 } 3151 return soc_datum_mem_write(pcid_info, block, address, data); 3152 } else { 3153 return soc_internal_write_mem(pcid_info, address, data); 3154 } 3155 } 3156 3157 int 3158 _soc_internal_extended_read_mem(pcid_info_t *pcid_info, soc_mem_t mem, 3159 soc_block_t block, int acc_type, 3160 uint32 address, uint32 *data) 3161 { 3162 int i, rv; 3163 soc_mem_t alt_mem; 3164 uint32 offset; 3165 uint8 alt_acc_type; 3166 3167 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3168 if (mem != INVALIDm) { 3169 alt_mem = INVALIDm; 3170 switch(mem) { 3171 #ifdef BCM_XGS_SWITCH_SUPPORT 3172 case L3_ENTRY_IPV4_UNICASTm: 3173 case L3_ENTRY_IPV4_MULTICASTm: 3174 case L3_ENTRY_IPV6_UNICASTm: 3175 case L3_ENTRY_IPV6_MULTICASTm: 3176 return soc_internal_l3x2_read(pcid_info, mem, address, data); 3177 #ifdef BCM_TOMAHAWK_SUPPORT 3178 case EXACT_MATCH_2m: 3179 case EXACT_MATCH_4m: 3180 return soc_internal_exact_match_read(pcid_info, mem, address, 3181 data); 3182 #endif /* BCM_TOMAHAWK_SUPPORT */ 3183 case VLAN_MACm: 3184 alt_mem = VLAN_XLATEm; 3185 break; 3186 #endif 3187 default: 3188 break; 3189 } 3190 if (alt_mem != INVALIDm) { 3191 offset = address ^ SOC_MEM_INFO(pcid_info->unit, mem).base; 3192 mem = alt_mem; 3193 address = soc_mem_addr_get(pcid_info->unit, mem, 0, block, offset, 3194 &alt_acc_type); 3195 acc_type = alt_acc_type; 3196 } 3197 if (soc_mem_is_aggr(pcid_info->unit, mem)) { 3198 return soc_internal_extended_read_aggrmem(pcid_info, block, 3199 acc_type, address, 3200 data); 3201 } 3202 } 3203 if (acc_type >= 0) { 3204 block |= acc_type << 24; 3205 } 3206 rv = soc_datum_mem_read(pcid_info, block, address, data); 3207 if (SOC_E_NOT_FOUND == rv) { 3208 /* Return null entry value if recognized, otherwise 0xf's */ 3209 if (mem != INVALIDm) { 3210 if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) { 3211 memcpy(data, /* Memory */ 3212 soc_mem_entry_null(pcid_info->unit, mem), 3213 4 * soc_mem_entry_words(pcid_info->unit, mem)); 3214 } else { 3215 memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem)); 3216 } 3217 } else { /* Other */ 3218 for (i = 0; i < SOC_MAX_MEM_WORDS; i++) { 3219 data[i] = 0xffffffff; 3220 } 3221 } 3222 rv = SOC_E_NONE; 3223 } 3224 3225 return rv; 3226 } else { 3227 return soc_internal_read_mem(pcid_info, address, data); 3228 } 3229 } 3230 3231 int 3232 soc_internal_extended_write_mem(pcid_info_t *pcid_info, 3233 soc_block_t block, int acc_type, 3234 uint32 address, uint32 *data) 3235 { 3236 soc_mem_t mem; 3237 3238 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3239 if ((pcid_info->regmem_cb) 3240 && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, data, 3241 ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) { 3242 return 0; 3243 } 3244 3245 mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, address); 3246 return _soc_internal_extended_write_mem(pcid_info, mem, block, 3247 acc_type, address, data); 3248 } else { 3249 return soc_internal_write_mem(pcid_info, address, data); 3250 } 3251 } 3252 3253 int 3254 soc_internal_extended_read_mem(pcid_info_t *pcid_info, 3255 soc_block_t block, int acc_type, 3256 uint32 address, uint32 *data) 3257 { 3258 soc_mem_t mem; 3259 3260 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3261 /* To fill in */ 3262 if ((pcid_info->regmem_cb) 3263 && (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, data, 3264 ((SOC_MAX_MEM_WORDS * 4) * 8)) == 0)) { 3265 return 0; 3266 } 3267 3268 mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, address); 3269 return _soc_internal_extended_read_mem(pcid_info, mem, block, 3270 acc_type, address, data); 3271 } else { 3272 return soc_internal_read_mem(pcid_info, address, data); 3273 } 3274 } 3275 3276 int 3277 soc_internal_extended_read_aggrmem(pcid_info_t *pcid_info, 3278 soc_block_t block, int acc_type, 3279 uint32 addr, uint32 *data) 3280 { 3281 uint32 ent[SOC_MAX_MEM_WORDS]; 3282 uint32 fv[SOC_MAX_MEM_WORDS]; 3283 soc_mem_t *m = NULL; 3284 int index, i; 3285 int offset; 3286 int adj_offset = 0; 3287 int f; 3288 int nfield; 3289 int pck_factor; 3290 soc_mem_t mem; 3291 soc_mem_info_t *amemp; 3292 soc_mem_info_t *memp; 3293 soc_field_info_t *fieldp; 3294 soc_field_info_t *asflds; /* array for aggregate mem sorted fields */ 3295 soc_field_info_t *sflds; /* array for partial mem sorted fields */ 3296 uint8 acc_type_member; 3297 uint32 member_addr; 3298 int unit = pcid_info->unit; 3299 3300 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3301 /* To fill in */ 3302 mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, addr); 3303 3304 if (mem == INVALIDm) { 3305 return SOC_E_PARAM; 3306 } 3307 3308 offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0x3ffffff; 3309 index = 0; 3310 memset(data, 0, 4 * soc_mem_entry_words(unit, mem)); 3311 do { 3312 m = SOC_MEM_AGGR(unit, index); 3313 if (m[0] == mem) { 3314 /* Fetch the individual components */ 3315 nfield = 1; 3316 for(i = 1; m[i] != INVALIDm; i++) { 3317 /* 3318 ** Multiple entries compacted into one entry like HIT 3319 ** requires special handling. 3320 */ 3321 amemp = &SOC_MEM_INFO(unit, mem); 3322 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) { 3323 continue; 3324 } 3325 pck_factor = (soc_mem_index_max(unit, mem) / 3326 soc_mem_index_max(unit, m[i])); 3327 assert(pck_factor != 0); 3328 adj_offset = offset / pck_factor; 3329 member_addr = 3330 soc_mem_addr_get(unit, m[i], 0, 3331 SOC_MEM_BLOCK_ANY(unit, m[i]), 3332 adj_offset, &acc_type_member); 3333 soc_internal_extended_read_mem(pcid_info, block, 3334 acc_type_member, 3335 member_addr, ent); 3336 3337 /* Iterate thru' the fields in this View */ 3338 memp = &SOC_MEM_INFO(unit, m[i]); 3339 if (pck_factor == 1) { 3340 for (f = memp->nFields - 1; f >= 0; f--) { 3341 fieldp = &memp->fields[f]; 3342 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 3343 if (soc_mem_field_valid(unit, mem, fieldp->field) && 3344 soc_mem_field_valid(unit, m[i], fieldp->field)) { 3345 soc_mem_field_set(unit, mem, data, fieldp->field, 3346 fv); 3347 } 3348 nfield++; 3349 } 3350 } else if (memp->nFields == pck_factor) { 3351 asflds = sal_alloc(amemp->nFields * 3352 sizeof(soc_field_info_t), 3353 "aggregate fields"); 3354 if (!asflds) { 3355 return SOC_E_INTERNAL; 3356 } 3357 sflds = sal_alloc(memp->nFields * 3358 sizeof(soc_field_info_t), 3359 "mem fields"); 3360 if (!sflds) { 3361 sal_free(asflds); 3362 return SOC_E_INTERNAL; 3363 } 3364 _soc_internal_fields_sort(amemp->fields, 3365 amemp->nFields, asflds); 3366 _soc_internal_fields_sort(memp->fields, memp->nFields, 3367 sflds); 3368 fieldp = &sflds[memp->nFields - 3369 (offset % pck_factor) - 1]; 3370 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 3371 fieldp = &asflds[(amemp->nFields - nfield)]; 3372 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 3373 nfield++; 3374 sal_free(asflds); 3375 sal_free(sflds); 3376 } else if (memp->nFields == (pck_factor * 2)) { 3377 asflds = sal_alloc(amemp->nFields * 3378 sizeof(soc_field_info_t), 3379 "aggregate fields"); 3380 if (!asflds) { 3381 return SOC_E_INTERNAL; 3382 } 3383 sflds = sal_alloc(memp->nFields * 3384 sizeof(soc_field_info_t), 3385 "mem fields"); 3386 if (!sflds) { 3387 sal_free(asflds); 3388 return SOC_E_INTERNAL; 3389 } 3390 _soc_internal_fields_sort(amemp->fields, 3391 amemp->nFields, asflds); 3392 _soc_internal_fields_sort(memp->fields, memp->nFields, 3393 sflds); 3394 fieldp = &sflds[memp->nFields - 3395 (offset % pck_factor) - 1]; 3396 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 3397 fieldp = &asflds[(amemp->nFields - nfield)]; 3398 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 3399 nfield++; 3400 3401 fieldp = &sflds[memp->nFields - pck_factor - 3402 (offset % pck_factor) - 1]; 3403 soc_mem_field_get(unit, m[i], ent, fieldp->field, fv); 3404 fieldp = &asflds[(amemp->nFields - nfield)]; 3405 soc_mem_field_set(unit, mem, data, fieldp->field, fv); 3406 nfield++; 3407 sal_free(asflds); 3408 sal_free(sflds); 3409 } else { 3410 LOG_ERROR(BSL_LS_SOC_COMMON, 3411 (BSL_META_U(unit, 3412 "soc_internal_extended_read_aggrmem:mem=%d" 3413 "Unable to handle Aggregate Mem component %d\n"), 3414 mem, m[i])); 3415 } 3416 } 3417 return(0); 3418 } 3419 index++; 3420 } while (m[0] != INVALIDm); 3421 3422 /* Not found in the table of aggregate memories */ 3423 LOG_ERROR(BSL_LS_SOC_COMMON, 3424 (BSL_META_U(unit, 3425 "soc_internal_extended_read_aggrmem:mem=%d missing in Aggregate Mem List\n"), 3426 mem)); 3427 if((NULL != soc_mem_entry_null(pcid_info->unit, mem))) { 3428 memcpy(data, /* Memory */ 3429 soc_mem_entry_null(pcid_info->unit, mem), 3430 4 * soc_mem_entry_words(pcid_info->unit, mem)); 3431 } else { 3432 memset(data, 0, 4 * soc_mem_entry_words(pcid_info->unit, mem)); 3433 } 3434 3435 return 0; 3436 } else { 3437 return soc_internal_read_aggrmem(pcid_info, addr, data); 3438 } 3439 } 3440 3441 int 3442 soc_internal_extended_write_aggrmem(pcid_info_t *pcid_info, 3443 soc_block_t block, int acc_type, 3444 uint32 addr, uint32 *data) 3445 { 3446 uint32 ent[SOC_MAX_MEM_WORDS]; 3447 uint32 fv[SOC_MAX_MEM_WORDS]; 3448 soc_mem_t *m = NULL; 3449 int index, i; 3450 int offset; 3451 int adj_offset = 0; 3452 int f; 3453 int nfield; 3454 int pck_factor; 3455 soc_mem_t mem; 3456 soc_mem_info_t *amemp; 3457 soc_mem_info_t *memp; 3458 soc_field_info_t *fieldp; 3459 soc_field_info_t *asflds; /* array for aggregate mem sorted fields */ 3460 soc_field_info_t *sflds; /* array for partial mem sorted fields */ 3461 uint8 acc_type_member; 3462 uint32 member_addr; 3463 int unit = pcid_info->unit; 3464 3465 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3466 /* To fill in */ 3467 3468 mem = soc_addr_to_mem_extended(pcid_info->unit, block, acc_type, addr); 3469 3470 if (mem == INVALIDm) 3471 { 3472 return SOC_E_PARAM; 3473 } 3474 3475 memset(ent, 0, 4 * soc_mem_entry_words(unit, mem)); 3476 offset = (addr ^ SOC_MEM_INFO(unit, mem).base) & 0x3ffffff; 3477 index = 0; 3478 do { 3479 m = SOC_MEM_AGGR(unit, index); 3480 if (m[0] == mem) { 3481 /* Fetch the individual components */ 3482 nfield = 1; 3483 for(i = 1; m[i] != INVALIDm; i++) { 3484 /* 3485 ** Multiple entries compacted into one entry like HIT 3486 ** requires special handling. 3487 */ 3488 amemp = &SOC_MEM_INFO(unit, mem); 3489 if(!soc_mem_index_max(unit, m[i]) || !soc_mem_index_max(unit, mem)) { 3490 continue; 3491 } 3492 pck_factor = (soc_mem_index_max(unit, mem) / 3493 soc_mem_index_max(unit, m[i])); 3494 assert(pck_factor != 0); 3495 adj_offset = offset / pck_factor; 3496 memp = &SOC_MEM_INFO(unit, m[i]); 3497 member_addr = 3498 soc_mem_addr_get(unit, m[i], 0, 3499 SOC_MEM_BLOCK_ANY(unit, m[i]), 3500 adj_offset, &acc_type_member); 3501 3502 /* Iterate thru' the fields in this View */ 3503 if (pck_factor == 1) { 3504 for (f = memp->nFields - 1; f >= 0; f--) { 3505 fieldp = &memp->fields[f]; 3506 if (soc_mem_field_valid(unit, mem, fieldp->field) && 3507 soc_mem_field_valid(unit, m[i], fieldp->field)) { 3508 soc_mem_field_get(unit, mem, data, fieldp->field, 3509 fv); 3510 soc_mem_field_set(unit, m[i], ent, fieldp->field, 3511 fv); 3512 } 3513 nfield++; 3514 } 3515 } else if (memp->nFields == pck_factor) { 3516 asflds = sal_alloc(amemp->nFields * 3517 sizeof(soc_field_info_t), 3518 "aggregate fields"); 3519 if (!asflds) { 3520 return SOC_E_INTERNAL; 3521 } 3522 sflds = sal_alloc(memp->nFields * 3523 sizeof(soc_field_info_t), 3524 "mem fields"); 3525 if (!sflds) { 3526 sal_free(asflds); 3527 return SOC_E_INTERNAL; 3528 } 3529 _soc_internal_fields_sort(amemp->fields, 3530 amemp->nFields, asflds); 3531 _soc_internal_fields_sort(memp->fields, memp->nFields, 3532 sflds); 3533 fieldp = &asflds[amemp->nFields - nfield]; 3534 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 3535 soc_internal_extended_read_mem(pcid_info, block, 3536 acc_type_member, 3537 member_addr, ent); 3538 fieldp = &sflds[memp->nFields - 3539 (offset % pck_factor) - 1]; 3540 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 3541 nfield++; 3542 sal_free(asflds); 3543 sal_free(sflds); 3544 } else if (memp->nFields == (pck_factor * 2)) { 3545 asflds = sal_alloc(amemp->nFields * 3546 sizeof(soc_field_info_t), 3547 "aggregate fields"); 3548 if (!asflds) { 3549 return SOC_E_INTERNAL; 3550 } 3551 sflds = sal_alloc(memp->nFields * 3552 sizeof(soc_field_info_t), 3553 "mem fields"); 3554 if (!sflds) { 3555 sal_free(asflds); 3556 return SOC_E_INTERNAL; 3557 } 3558 _soc_internal_fields_sort(amemp->fields, 3559 amemp->nFields, asflds); 3560 _soc_internal_fields_sort(memp->fields, memp->nFields, 3561 sflds); 3562 fieldp = &asflds[amemp->nFields - nfield]; 3563 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 3564 soc_internal_extended_read_mem(pcid_info, block, 3565 acc_type_member, 3566 member_addr, ent); 3567 fieldp = &sflds[memp->nFields - 3568 (offset % pck_factor) - 1]; 3569 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 3570 nfield++; 3571 3572 fieldp = &asflds[(amemp->nFields - nfield)]; 3573 soc_mem_field_get(unit, mem, data, fieldp->field, fv); 3574 fieldp = &sflds[memp->nFields - pck_factor - 3575 (offset % pck_factor) - 1]; 3576 soc_mem_field_set(unit, m[i], ent, fieldp->field, fv); 3577 nfield++; 3578 sal_free(asflds); 3579 sal_free(sflds); 3580 } else { 3581 LOG_ERROR(BSL_LS_SOC_COMMON, 3582 (BSL_META_U(unit, 3583 "soc_internal_extended_write_mem:mem=%d" 3584 "Unable to handle Aggregate Mem component %d\n"), 3585 mem, m[i])); 3586 } 3587 soc_internal_extended_write_mem 3588 (pcid_info, block, acc_type_member, member_addr, ent); 3589 } 3590 return(0); 3591 } 3592 index++; 3593 } while (m[0] != INVALIDm); 3594 3595 /* Not found in the table of aggregate memories */ 3596 LOG_ERROR(BSL_LS_SOC_COMMON, 3597 (BSL_META_U(unit, 3598 "soc_internal_write_aggrmem:mem=%d missing in Aggregate Mem List\n"), 3599 mem)); 3600 return 0; 3601 } else { 3602 return soc_internal_write_aggrmem(pcid_info, addr, data); 3603 } 3604 } 3605 3606 int 3607 soc_internal_extended_read_bytes(pcid_info_t *pcid_info, 3608 soc_block_t block, int acc_type, 3609 uint32 address, uint8 *data, int len) 3610 { 3611 uint32 temp[SOC_MAX_MEM_WORDS]; 3612 int rv; 3613 3614 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3615 /* To fill in */ 3616 3617 if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) { 3618 return 1; 3619 } 3620 3621 /* reading bytes is supported only for bcmsim */ 3622 if ((pcid_info->regmem_cb) && 3623 (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, address, 3624 (uint32 *) data, (len * 8)) == 0)) { 3625 return 0; 3626 } 3627 3628 /* if no registered call-back, default to read_mem */ 3629 rv = soc_internal_extended_read_mem(pcid_info, block, acc_type, address, 3630 temp); 3631 if (!rv) { 3632 sal_memcpy(data, temp, len); 3633 } 3634 return rv; 3635 } else { 3636 return soc_internal_read_bytes(pcid_info, address, data, len); 3637 } 3638 } 3639 3640 int 3641 soc_internal_extended_write_bytes(pcid_info_t *pcid_info, 3642 soc_block_t block, int acc_type, 3643 uint32 address, uint8 *data, int len) 3644 { 3645 uint32 temp[SOC_MAX_MEM_WORDS]; 3646 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3647 /* To fill in */ 3648 3649 if ((len < 0) || (len > (SOC_MAX_MEM_WORDS * (sizeof(uint32))))) { 3650 return 1; 3651 } 3652 3653 /* writing bytes is supported only for bcmsim */ 3654 if ((pcid_info->regmem_cb) && 3655 (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, address, 3656 (uint32 *)data, (len * 8)) == 0)) { 3657 return 0; 3658 } 3659 3660 /* if no registered call-back, default to write_mem */ 3661 sal_memset(temp, 0, (SOC_MAX_MEM_WORDS * sizeof(uint32))); 3662 sal_memcpy(temp, data, len); 3663 return soc_internal_extended_write_mem(pcid_info, block, acc_type, 3664 address, temp); 3665 } else { 3666 return soc_internal_write_bytes(pcid_info, address, data, len); 3667 } 3668 } 3669 3670 int 3671 soc_internal_extended_write_mem_index(pcid_info_t *pcid_info, soc_mem_t mem, 3672 int index, uint32 *data) 3673 { 3674 int block_info_index; 3675 int block; 3676 uint8 acc_type; 3677 uint32 addr; 3678 3679 block_info_index = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem); 3680 block = SOC_BLOCK2SCH(pcid_info->unit, block_info_index); 3681 addr = soc_mem_addr_get(pcid_info->unit, mem, 0, block_info_index, index, 3682 &acc_type); 3683 3684 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3685 if (pcid_info->regmem_cb) { 3686 if (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_WRITE, addr, 3687 data, SOC_MAX_MEM_WORDS * 4 * 8) == 0) { 3688 return 0; 3689 } 3690 } 3691 return _soc_internal_extended_write_mem(pcid_info, mem, block, 3692 acc_type, addr, data); 3693 } else { 3694 return soc_internal_write_mem(pcid_info, addr, data); 3695 } 3696 } 3697 3698 int 3699 soc_internal_extended_read_mem_index(pcid_info_t *pcid_info, soc_mem_t mem, 3700 int index, uint32 *data) 3701 { 3702 int block_info_index; 3703 int block; 3704 uint8 acc_type; 3705 uint32 addr; 3706 3707 block_info_index = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem); 3708 block = SOC_BLOCK2SCH(pcid_info->unit, block_info_index); 3709 addr = soc_mem_addr_get(pcid_info->unit, mem, 0, block_info_index, index, 3710 &acc_type); 3711 3712 if (SBUS_ADDR_VERSION_2 == pcid_info->sbus_addr_version) { 3713 if (pcid_info->regmem_cb != NULL) { 3714 if (pcid_info->regmem_cb(pcid_info, BCMSIM_SCHAN_MEM_READ, addr, 3715 data, SOC_MAX_MEM_WORDS * 4 * 8) == 0) { 3716 return 0; 3717 } 3718 } 3719 return _soc_internal_extended_read_mem(pcid_info, mem, block, 3720 acc_type, addr, data); 3721 } else { 3722 return soc_internal_read_mem(pcid_info, addr, data); 3723 } 3724 }