drvformat.c (16064B)
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 * format field manipulations. 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <assert.h> 13 14 #include <sal/core/libc.h> 15 16 #include <soc/drv.h> 17 18 #include <soc/mem.h> 19 #include <soc/memory.h> 20 #include <soc/format.h> 21 22 #include <soc/error.h> 23 24 #if defined(BCM_ESW_SUPPORT) 25 26 /* 27 * Macro used by memory accessor functions to fix order 28 */ 29 #define FIX_FORMAT_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \ 30 BITS2WORDS((m)->bits)-1-(v) : \ 31 (v)) 32 33 /************************************************************* 34 * Function: soc_format_field_length 35 * Purpose: Return the length of a format field in bits. 36 * Value is 0 if field is not found. 37 * Returns: bits in field 38 */ 39 int 40 soc_format_field_length(int unit, soc_format_t format, soc_field_t field) 41 { 42 soc_field_info_t *fld; 43 44 SOC_FIND_FIELD(field, 45 SOC_FORMAT_INFO(unit, format).fields, 46 SOC_FORMAT_INFO(unit, format).nFields, 47 fld); 48 if (fld == NULL) { 49 return 0; 50 } 51 return fld->len; 52 } 53 54 /******************************************************************** 55 * Function: _soc_formatinfo_field_get 56 * Purpose: Get a format field without reference to chip. 57 * Parameters: formatinfo -- direct reference to format 58 */ 59 STATIC uint32 * 60 _soc_formatinfo_field_get(soc_format_t format, soc_format_info_t *formatinfo, 61 const uint32 *entbuf, soc_field_t field, uint32 *fldbuf, 62 uint32 fldbuf_size) /* The number of uint32s in fldbuf */ 63 { 64 soc_field_info_t *fieldinfo; 65 int i, wp, bp, len; 66 67 SOC_FIND_FIELD(field, 68 formatinfo->fields, 69 formatinfo->nFields, 70 fieldinfo); 71 if (NULL == fieldinfo) { 72 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 73 LOG_CLI((BSL_META("format %s field %s is invalid\n"), 74 soc_format_name[format], soc_fieldnames[field])); 75 #endif 76 assert(fieldinfo); 77 } 78 79 /* 80 * COVERITY 81 * 82 * assert validates the input for NULL 83 */ 84 /* coverity[var_deref_op : FALSE] */ 85 bp = fieldinfo->bp; 86 len = fieldinfo->len; 87 assert(len / 32 <= fldbuf_size); /* assert we do not write beyond 88 * the end of the output buffer */ 89 90 if (len == 1) { /* special case single bits */ 91 wp = bp / 32; 92 bp = bp & (32 - 1); 93 if (entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] & (1<<bp)) { 94 fldbuf[0] = 1; 95 } else { 96 fldbuf[0] = 0; 97 } 98 return fldbuf; 99 } 100 101 if (fieldinfo->flags & SOCF_LE) { 102 wp = bp / 32; 103 bp = bp & (32 - 1); 104 i = 0; 105 106 for (; len > 0; len -= 32) { 107 if (bp) { 108 fldbuf[i] = 109 entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] >> bp & 110 ((1 << (32 - bp)) - 1); 111 if ( len > (32 - bp) ) { 112 fldbuf[i] |= entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] << 113 (32 - bp); 114 } 115 } else { 116 fldbuf[i] = entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)]; 117 } 118 119 if (len < 32) { 120 fldbuf[i] &= ((1 << len) - 1); 121 } 122 123 i++; 124 } 125 } else { 126 i = (len - 1) / 32; 127 128 while (len > 0) { 129 assert(i >= 0); 130 131 fldbuf[i] = 0; 132 133 do { 134 fldbuf[i] = 135 (fldbuf[i] << 1) | 136 ((entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] >> 137 (bp & (32 - 1))) & 1); 138 len--; 139 bp++; 140 } while (len & (32 - 1)); 141 142 i--; 143 } 144 } 145 146 return fldbuf; 147 } 148 149 /******************************************************************** 150 * Function: _soc_format_field_value_fit 151 * Purpose: Check if value will fit into a format field. 152 * Parameters: fieldinfo -- (IN)Direct reference to field description. 153 * value -- (IN)Value to be checked. 154 * Returns: 155 * TRUE - buffer fits into the field. 156 * FALSE - Otherwise. 157 */ 158 STATIC int 159 _soc_format_field_value_fit(soc_field_info_t *fieldinfo, uint32 *value) 160 { 161 uint32 mask; /* Value mask */ 162 uint16 len; /* Bits in field */ 163 int idx; /* Iteration index. */ 164 165 idx = (fieldinfo->len - 1) >> 5; 166 len = fieldinfo->len % 32; 167 168 if (!len) { 169 return TRUE; 170 } 171 172 mask = (1 << len) - 1; 173 if((value[idx] & ~mask) != 0) { 174 return (FALSE); 175 } 176 return (TRUE); 177 } 178 179 /************************************************************************ 180 * Function: _soc_formatinfo_field_set 181 * Purpose: Set a format field without reference to chip. 182 * Parameters: formatinfo -- direct reference format 183 */ 184 STATIC void 185 _soc_formatinfo_field_set(soc_format_t format, soc_format_info_t *formatinfo, 186 uint32 *entbuf, soc_field_t field, uint32 *fldbuf) 187 { 188 soc_field_info_t *fieldinfo; 189 uint32 mask; 190 int i, wp, bp, len; 191 192 SOC_FIND_FIELD(field, 193 formatinfo->fields, 194 formatinfo->nFields, 195 fieldinfo); 196 if (NULL == fieldinfo) { 197 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 198 LOG_CLI((BSL_META("format %s field %s is invalid\n"), 199 soc_format_name[format], soc_fieldnames[field])); 200 #endif 201 assert(fieldinfo); 202 } 203 204 /* Make sure value fits into the field. */ 205 /* 206 * COVERITY 207 * 208 * assert validates the input for NULL 209 */ 210 /* coverity[var_deref_model : FALSE] */ 211 if (!_soc_format_field_value_fit(fieldinfo, fldbuf)) { 212 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 213 LOG_CLI((BSL_META("format %s field %s value does not fit\n"), 214 soc_format_name[format], soc_fieldnames[field])); 215 #endif 216 assert(_soc_format_field_value_fit(fieldinfo, fldbuf)); 217 } 218 219 bp = fieldinfo->bp; 220 221 if (fieldinfo->flags & SOCF_LE) { 222 wp = bp / 32; 223 bp = bp & (32 - 1); 224 i = 0; 225 226 for (len = fieldinfo->len; len > 0; len -= 32) { 227 if (bp) { 228 if (len < 32) { 229 mask = (1 << len) - 1; 230 } else { 231 mask = -1; 232 } 233 234 entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &= ~(mask << bp); 235 entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] |= fldbuf[i] << bp; 236 if (len > (32 - bp)) { 237 entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &= 238 ~(mask >> (32 - bp)); 239 entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] |= 240 fldbuf[i] >> (32 - bp) & ((1 << bp) - 1); 241 } 242 } else { 243 if (len < 32) { 244 mask = (1 << len) - 1; 245 entbuf[FIX_FORMAT_ORDER_E(wp, formatinfo)] &= ~mask; 246 entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] |= 247 fldbuf[i] << bp; 248 } else { 249 entbuf[FIX_FORMAT_ORDER_E(wp++, formatinfo)] = fldbuf[i]; 250 } 251 } 252 253 i++; 254 } 255 } else { /* Big endian: swap bits */ 256 len = fieldinfo->len; 257 258 while (len > 0) { 259 len--; 260 entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] &= 261 ~(1 << (bp & (32-1))); 262 entbuf[FIX_FORMAT_ORDER_E(bp / 32, formatinfo)] |= 263 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1)); 264 bp++; 265 } 266 } 267 } 268 /*************************************************************** 269 * Function: 270 * soc_format_field_valid 271 * Purpose: 272 * Verify if field is valid & present in format 273 * Parameters: 274 * format - (IN)Format id. 275 * field - (IN)Field id. 276 * Return: 277 * TRUE -If field is present & valid. 278 * FALSE -Otherwise. 279 */ 280 int 281 soc_format_field_valid(int unit, soc_format_t format, soc_field_t field) 282 { 283 soc_format_info_t *formatinfo; 284 soc_field_info_t *finfop; /* Field information structure. */ 285 286 /* Verify that memory is present on the device. */ 287 if (!SOC_FORMAT_IS_VALID(unit, format)) { 288 return FALSE; 289 } 290 291 formatinfo = &SOC_FORMAT_INFO(unit, format); 292 SOC_FIND_FIELD(field, 293 formatinfo->fields, 294 formatinfo->nFields, 295 finfop); 296 return (finfop != NULL) ? TRUE : FALSE; 297 } 298 299 /**************************************************** 300 * Function: soc_format_field_get 301 * Purpose: Get a format field 302 * Parameters: unit - device 303 * format 304 * entbuf - format entry buffer 305 * field - which field to get 306 * fldbuf - field buffer 307 */ 308 uint32 * 309 soc_format_field_get(int unit, soc_format_t format, const uint32 *entbuf, 310 soc_field_t field, uint32 *fldbuf) 311 { 312 soc_format_info_t *formatinfo; 313 314 if (!SOC_FORMAT_IS_VALID(unit, format)) { 315 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 316 LOG_CLI((BSL_META_U(unit, 317 "format %s is invalid\n"), soc_format_name[format])); 318 #endif 319 assert(SOC_FORMAT_IS_VALID(unit, format)); 320 } 321 322 formatinfo = &SOC_FORMAT_INFO(unit, format); 323 324 return _soc_formatinfo_field_get(format, formatinfo, entbuf, 325 field, fldbuf, SOC_MAX_FORMAT_WORDS); 326 } 327 328 /******************************************************** 329 * Function: soc_format_field_set 330 * Purpose: Set a format field 331 * Parameters: unit - device 332 * format 333 * entbuf - format entry buffer 334 * field - which field to set 335 * fldbuf - field buffer 336 */ 337 void 338 soc_format_field_set(int unit, soc_format_t format, uint32 *entbuf, 339 soc_field_t field, uint32 *fldbuf) 340 { 341 soc_format_info_t *formatinfo; 342 343 if (!SOC_FORMAT_IS_VALID(unit, format)) { 344 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 345 LOG_CLI((BSL_META_U(unit, 346 "format %s is invalid\n"), 347 soc_format_name[format])); 348 #endif 349 assert(SOC_FORMAT_IS_VALID(unit, format)); 350 } 351 352 formatinfo = &SOC_FORMAT_INFO(unit, format); 353 354 _soc_formatinfo_field_set(format, formatinfo, entbuf, field, fldbuf); 355 } 356 357 /*********************************************************** 358 * Function: soc_format_field32_get 359 * Purpose: Get a <=32 bit field out of a format entry 360 * Returns: The value of the field 361 */ 362 uint32 363 soc_format_field32_get(int unit, soc_format_t format, const void *entbuf, 364 soc_field_t field) 365 { 366 uint32 value; 367 368 if (!SOC_FORMAT_IS_VALID(unit, format)) { 369 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 370 LOG_CLI((BSL_META_U(unit, "format %s is invalid\n"), 371 soc_format_name[format])); 372 #endif 373 assert(SOC_FORMAT_IS_VALID(unit, format)); 374 } 375 _soc_formatinfo_field_get(format, &SOC_FORMAT_INFO(unit, format), 376 entbuf, field, &value, 1); 377 378 return value; 379 } 380 381 /*********************************************************** 382 * Function: soc_format_field32_set 383 * Purpose: Set a <=32 bit field out of a format entry 384 * Returns: void 385 */ 386 void 387 soc_format_field32_set(int unit, soc_format_t format, void *entbuf, 388 soc_field_t field, uint32 value) 389 { 390 /* 391 * COVERITY 392 * 393 * We do this intentionally to use the generic function 394 * soc_format_field_set() which does the necessary handling. 395 */ 396 /* coverity[callee_ptr_arith : FALSE] */ 397 soc_format_field_set(unit, format, entbuf, field, &value); 398 } 399 400 /*********************************************************** 401 * Function: soc_dop_format_get 402 * Purpose: get the format corresponding to a dop_id 403 * Inputs: unit - device 404 * dop_id - 16 bit dop_id 405 * dop_block - block 406 * Outputs: format 407 * n_data_phase entry from the corresponding Format 408 * Returns: SOC_E_NONE if found 409 * SOC_E_NOT_FOUND if given DOP is not found 410 * SOC_E_UNAVAIL if DOP functionality is not available 411 */ 412 int 413 soc_dop_format_get(int unit, uint16 dop_id, uint16 dop_block, uint16 *n_data_phases, soc_format_t *format) 414 { 415 uint32 dop_id_blk = 0; 416 int i=0; 417 soc_dop_t *myDop = SOC_DOP_INFO(unit); 418 419 if (NULL == myDop) { 420 return SOC_E_UNAVAIL; 421 } 422 423 dop_id_blk = dop_id | (dop_block << 16); 424 425 while (myDop[i].dop_id != 0) 426 { 427 if (myDop[i].dop_id == dop_id_blk) 428 { 429 *n_data_phases = myDop[i].n_data_phases; 430 *format = myDop[i].dop_fmt; 431 return SOC_E_NONE; 432 } 433 i++; 434 } 435 return SOC_E_NOT_FOUND; 436 } 437 438 /******************************************************************** 439 * Function: _soc_format_fieldinfo_get 440 * Purpose: Get a format field info without reference to chip. 441 * Parameters: unit - device 442 * fmt - format 443 * field - Field in format 444 * Returns Reference to field info format 445 */ 446 soc_field_info_t * 447 soc_format_fieldinfo_get(int unit, soc_format_t fmt, soc_field_t field) 448 { 449 soc_field_info_t *fieldinfo; 450 soc_format_info_t *formatinfo; 451 452 if (!SOC_FORMAT_IS_VALID(unit, fmt)) { 453 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 454 LOG_CLI((BSL_META_U(unit, 455 "format %s is invalid\n"), soc_format_name[fmt])); 456 #endif 457 assert(SOC_FORMAT_IS_VALID(unit, fmt)); 458 } 459 460 formatinfo = &SOC_FORMAT_INFO(unit, fmt); 461 462 SOC_FIND_FIELD(field, 463 formatinfo->fields, 464 formatinfo->nFields, 465 fieldinfo); 466 if (NULL == fieldinfo) { 467 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 468 LOG_CLI((BSL_META("format %s field %s is invalid\n"), 469 soc_format_name[fmt], soc_fieldnames[field])); 470 #endif 471 assert(fieldinfo); 472 } 473 474 return fieldinfo; 475 } 476 477 /******************************************************************** 478 * Function: soc_format_entry_dump 479 * Purpose: Dump the format entry. 480 * Parameters: unit - device 481 * fmt - format 482 * entbuf - format entry buffer 483 * Returns: voiod 484 */ 485 void 486 soc_format_entry_dump(int unit, soc_format_t format, const uint32 *entbuf) 487 { 488 soc_format_info_t *formatinfo; 489 soc_field_info_t *finfo; 490 int f_idx; 491 uint32 fbuf[SOC_MAX_MEM_FIELD_WORDS]; 492 char tmp[512]; 493 494 if (!SOC_FORMAT_IS_VALID(unit, format)) { 495 assert(SOC_FORMAT_IS_VALID(unit, format)); 496 } 497 498 formatinfo = &SOC_FORMAT_INFO(unit, format); 499 500 BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit, 501 "%s"), "<")); 502 for (f_idx = 0; 503 f_idx < formatinfo->nFields; 504 f_idx++) { 505 finfo = &formatinfo->fields[f_idx]; 506 soc_format_field_get(unit, 507 format, 508 entbuf, 509 finfo->field, 510 fbuf); 511 sal_memset(tmp, 0, sizeof(tmp)); 512 _shr_format_long_integer(tmp, fbuf, BITS2BYTES(finfo->len)); 513 #if defined(BCM_ESW_SUPPORT) && !defined(SOC_NO_NAMES) 514 BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit, 515 "%s<%d:%d>=%s%s"), soc_fieldnames[finfo->field], finfo->bp, finfo->bp+finfo->len-1, 516 tmp, ",")); 517 #endif 518 } 519 BSL_LOG(BSL_LSS_CLI, (BSL_META_U(unit, 520 "%s\n"), ">")); 521 } 522 #endif