openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 }