datum.c (6609B)
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 caches the register/memory values. 8 */ 9 10 #include "pcid.h" 11 #include <soc/mem.h> 12 13 #define MAX_BROADCAST_WRITE_SIZE (SOC_MAX_NUM_BLKS - 1) 14 int 15 _soc_datum_read(pcid_info_t *pcid_info, int reg, 16 uint32 selectors, uint32 addr, int words, 17 uint32 *data) 18 { 19 int index; 20 soc_datum_t *d, **ht = reg ? pcid_info->reg_ht : pcid_info->mem_ht; 21 22 index = SOC_HASH_EXTENDED_DATUM(selectors, addr); 23 24 for (d = ht[index]; d != NULL; d = d->next) { 25 if ((d->selectors == selectors) && (d->addr == addr)) { 26 memcpy(data, d->data, words * 4); 27 return SOC_E_NONE; 28 } 29 } 30 return SOC_E_NOT_FOUND; 31 } 32 33 int 34 _soc_datum_write(pcid_info_t *pcid_info, int reg, 35 uint32 selectors, uint32 addr, int words, 36 uint32 *data) 37 { 38 int index; 39 soc_datum_t *d, **ht = reg ? pcid_info->reg_ht : pcid_info->mem_ht; 40 41 index = SOC_HASH_EXTENDED_DATUM(selectors, addr); 42 43 for (d = ht[index]; d != NULL; d = d->next) { 44 if ((d->selectors == selectors) && (d->addr == addr)) { 45 memcpy(d->data, data, words * 4); 46 return SOC_E_NONE; 47 } 48 } 49 return SOC_E_NOT_FOUND; 50 } 51 52 int 53 _soc_datum_add(pcid_info_t *pcid_info, int reg, 54 uint32 selectors, uint32 addr, int words, 55 uint32 *data) 56 { 57 int index; 58 soc_datum_t *d, **ht = reg ? pcid_info->reg_ht : pcid_info->mem_ht; 59 60 index = SOC_HASH_EXTENDED_DATUM(selectors, addr); 61 62 d = sal_alloc(sizeof(soc_datum_t), reg ? "rdatum_t" : "mdatum_t"); 63 if (NULL == d) { 64 return SOC_E_MEMORY; 65 } 66 67 d->selectors = selectors; 68 d->addr = addr; 69 memcpy(d->data, data, words * 4); 70 d->next = ht[index]; 71 ht[index] = d; 72 return SOC_E_NONE; 73 } 74 75 int 76 soc_datum_reg_read(pcid_info_t *pcid_info, soc_regaddrinfo_t ainfo, 77 uint32 selectors, uint32 addr, 78 uint32 *data) 79 { 80 int words; 81 words = 1; 82 if (SOC_REG_IS_64(pcid_info->unit, ainfo.reg)) { 83 words = 2; 84 } 85 if(SOC_REG_IS_ABOVE_64(pcid_info->unit, ainfo.reg)) { 86 words = SOC_REG_ABOVE_64_INFO(pcid_info->unit, ainfo.reg).size; 87 } 88 89 return _soc_datum_read(pcid_info, TRUE, selectors, addr, words, data); 90 91 } 92 93 int 94 soc_datum_reg_write(pcid_info_t *pcid_info, soc_regaddrinfo_t ainfo, 95 uint32 selectors, uint32 addr, 96 uint32 *data) 97 { 98 int rv = SOC_E_NONE, words; 99 uint64 mask; 100 int nof_blocks = 1, blocks[MAX_BROADCAST_WRITE_SIZE], i, unit = pcid_info->unit; 101 102 words = 1; 103 if (SOC_REG_IS_64(unit, ainfo.reg)) { 104 words = 2; 105 } 106 if(SOC_REG_IS_ABOVE_64(unit, ainfo.reg)) { 107 words = SOC_REG_ABOVE_64_INFO(unit, ainfo.reg).size; 108 } 109 110 111 blocks[0] = selectors; 112 #ifdef BCM_JERICHO_SUPPORT 113 if (SOC_IS_JERICHO(unit)) { 114 /* If this is a broadcast block, write to the broadcast members instead of to the broadcast block */ 115 soc_block_t br_block = ainfo.block; 116 if (br_block >= 0 && SOC_BLOCK_IS_BROADCAST(unit, br_block)) { 117 assert(SOC_BLOCK2SCH(unit, br_block) == selectors); 118 nof_blocks = SOC_BLOCK_BROADCAST_SIZE(unit, br_block); 119 assert(nof_blocks > 1 && nof_blocks <= MAX_BROADCAST_WRITE_SIZE); 120 /* fill the blocks array with the schannel block IDs */ 121 for (i = 0; i < nof_blocks; ++i) { 122 blocks[i] = SOC_BLOCK2SCH(unit, SOC_BLOCK_BROADCAST_MEMBER(unit, br_block, i)); 123 } 124 } 125 } 126 #endif /* BCM_JERICHO_SUPPORT */ 127 128 for (i = 0; i < nof_blocks && rv == SOC_E_NONE; ++i) { /* perform write for each block */ 129 130 rv = _soc_datum_write(pcid_info, TRUE, blocks[i], addr, words, data); 131 if (rv == SOC_E_NOT_FOUND) { 132 /* Add new entry to the data tables */ 133 if ((!SOC_COUNTER_INVALID(unit, ainfo.reg)) && 134 (SOC_REG_IS_COUNTER(unit, ainfo.reg))) { 135 COMPILER_64_SET(mask, 0, 1); 136 COMPILER_64_SHL(mask,SOC_REG_INFO(unit, 137 ainfo.reg).fields[0].len); 138 COMPILER_64_SUB_32(mask, 1); 139 data[1] &= COMPILER_64_HI(mask); 140 data[0] &= COMPILER_64_LO(mask); 141 } 142 rv = _soc_datum_add(pcid_info, TRUE, blocks[i], addr, words, data); 143 } 144 } 145 146 /* Keep the error code for further processing by the caller. */ 147 return rv; 148 } 149 150 int 151 soc_datum_mem_read(pcid_info_t *pcid_info, 152 uint32 selectors, uint32 addr, 153 uint32 *data) 154 { 155 return _soc_datum_read(pcid_info, FALSE, selectors, addr, 156 SOC_MAX_MEM_WORDS, data); 157 } 158 159 int 160 soc_datum_mem_write(pcid_info_t *pcid_info, 161 uint32 selectors, uint32 addr, 162 uint32 *data) 163 { 164 int rv = SOC_E_NONE; 165 int nof_blocks = 1, blocks[MAX_BROADCAST_WRITE_SIZE], i; 166 #ifdef BCM_JERICHO_SUPPORT 167 int unit = pcid_info->unit; 168 #endif /* BCM_JERICHO_SUPPORT */ 169 170 blocks[0] = selectors; 171 #ifdef BCM_JERICHO_SUPPORT 172 if (SOC_IS_JERICHO(unit)) { /* handle broadcast blocks */ 173 int blk; 174 /* Find the block of the given CMIC block */ 175 for (blk = 0; ; ++blk) { 176 if (SOC_BLOCK_TYPE(unit, blk) < 0) { 177 return INVALIDm; 178 } else if (SOC_BLOCK2OFFSET(unit, blk) == selectors) { 179 break; 180 } 181 } 182 /* If this is a broadcast block, write to the broadcast members instead of to the broadcast block */ 183 if (SOC_BLOCK_IS_BROADCAST(unit, blk)) { 184 nof_blocks = SOC_BLOCK_BROADCAST_SIZE(unit, blk); 185 assert(nof_blocks > 1 && nof_blocks <= MAX_BROADCAST_WRITE_SIZE); 186 /* fill the blocks array with the schannel block IDs */ 187 for (i = 0; i < nof_blocks; ++i) { 188 blocks[i] = SOC_BLOCK2SCH(unit, SOC_BLOCK_BROADCAST_MEMBER(unit, blk, i)); 189 } 190 } 191 } 192 #endif /* BCM_JERICHO_SUPPORT */ 193 194 for (i = 0; i < nof_blocks && rv == SOC_E_NONE; ++i) { /* perform write for each block */ 195 rv = _soc_datum_write(pcid_info, FALSE, blocks[i], addr, SOC_MAX_MEM_WORDS, data); 196 if (SOC_E_NOT_FOUND == rv) { 197 rv = _soc_datum_add(pcid_info, FALSE, blocks[i], addr, SOC_MAX_MEM_WORDS, data); 198 } 199 } 200 201 /* Keep the error code for futher processing in the caller. */ 202 return rv; 203 }