phymod_symbol_fields.c (4101B)
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 8 /******************************************************************************* 9 * 10 * PHYMOD Symbol Field Routines 11 */ 12 13 #include <phymod/phymod_symbols.h> 14 15 /* 16 * Function: 17 * phymod_field_get 18 * Purpose: 19 * Extract multi-word field value from multi-word register/memory. 20 * Parameters: 21 * entbuf - current contents of register/memory (word array) 22 * sbit - bit number of first bit of the field to extract 23 * ebit - bit number of last bit of the field to extract 24 * fbuf - buffer where to store extracted field value 25 * Returns: 26 * Pointer to extracted field value. 27 */ 28 uint32_t * 29 phymod_field_get(const uint32_t *entbuf, int sbit, int ebit, uint32_t *fbuf) 30 { 31 int i, wp, bp, len; 32 33 bp = sbit; 34 len = ebit - sbit + 1; 35 36 wp = bp / 32; 37 bp = bp & (32 - 1); 38 i = 0; 39 40 for (; len > 0; len -= 32, i++) { 41 if (bp) { 42 fbuf[i] = (entbuf[wp++] >> bp) & ((1 << (32 - bp)) - 1); 43 if (len > (32 - bp)) { 44 fbuf[i] |= entbuf[wp] << (32 - bp); 45 } 46 } else { 47 fbuf[i] = entbuf[wp++]; 48 } 49 if (len < 32) { 50 fbuf[i] &= ((1 << len) - 1); 51 } 52 } 53 54 return fbuf; 55 } 56 57 /* 58 * Function: 59 * phymod_field_set 60 * Purpose: 61 * Assign multi-word field value in multi-word register/memory. 62 * Parameters: 63 * entbuf - current contents of register/memory (word array) 64 * sbit - bit number of first bit of the field to extract 65 * ebit - bit number of last bit of the field to extract 66 * fbuf - buffer with new field value 67 * Returns: 68 * Nothing. 69 */ 70 int 71 phymod_field_set(uint32_t *entbuf, int sbit, int ebit, uint32_t *fbuf) 72 { 73 uint32_t mask; 74 int i, wp, bp, len; 75 76 if (fbuf == NULL) { 77 return -1; 78 } 79 80 bp = sbit; 81 len = ebit - sbit + 1; 82 if (len <= 0) { 83 return -1; 84 } 85 86 wp = bp / 32; 87 bp = bp & (32 - 1); 88 i = 0; 89 90 for (; len > 0; len -= 32, i++) { 91 if (bp) { 92 if (len < 32) { 93 mask = (1 << len) - 1; 94 } else { 95 mask = ~0; 96 } 97 entbuf[wp] &= ~(mask << bp); 98 entbuf[wp++] |= fbuf[i] << bp; 99 if (len > (32 - bp)) { 100 entbuf[wp] &= ~(mask >> (32 - bp)); 101 entbuf[wp] |= fbuf[i] >> (32 - bp) & ((1 << bp) - 1); 102 } 103 } else { 104 if (len < 32) { 105 mask = (1 << len) - 1; 106 entbuf[wp] &= ~mask; 107 entbuf[wp++] |= (fbuf[i] & mask) << bp; 108 } else { 109 entbuf[wp++] = fbuf[i]; 110 } 111 } 112 } 113 return 0; 114 } 115 116 uint32_t * 117 phymod_field_info_decode(uint32_t* fp, phymod_field_info_t* finfo, const char** fnames) 118 { 119 if(!fp) { 120 return NULL; 121 } 122 123 if(finfo) { 124 /* 125 * Single or Double Word Descriptor? 126 */ 127 if(PHYMOD_SYMBOL_FIELD_EXT(*fp)) { 128 /* Double Word */ 129 finfo->fid = PHYMOD_SYMBOL_FIELD_EXT_ID_GET(*fp); 130 finfo->maxbit = PHYMOD_SYMBOL_FIELD_EXT_MAX_GET(*(fp+1)); 131 finfo->minbit = PHYMOD_SYMBOL_FIELD_EXT_MIN_GET(*(fp+1)); 132 } 133 else { 134 /* Single Word */ 135 finfo->fid = PHYMOD_SYMBOL_FIELD_ID_GET(*fp); 136 finfo->maxbit = PHYMOD_SYMBOL_FIELD_MAX_GET(*fp); 137 finfo->minbit = PHYMOD_SYMBOL_FIELD_MIN_GET(*fp); 138 } 139 140 if(fnames) { 141 finfo->name = fnames[finfo->fid]; 142 } 143 else { 144 finfo->name = NULL; 145 } 146 } 147 148 if(PHYMOD_SYMBOL_FIELD_LAST(*fp)) { 149 return NULL; 150 } 151 152 if(PHYMOD_SYMBOL_FIELD_EXT(*fp)) { 153 return fp+2; 154 } 155 156 return fp+1; 157 } 158 159 uint32_t 160 phymod_field_info_count(uint32_t* fp) 161 { 162 int count = 0; 163 while(fp) { 164 fp = phymod_field_info_decode(fp, NULL, NULL); 165 count++; 166 } 167 return count; 168 }